Как реализовать Spring data mon go транзакции с несколькими базами данных - PullRequest
0 голосов
/ 19 июня 2020

Я создал приложение, которое копирует данные из одной базы данных в другую на основе этого учебника . Фактически, мне нужно сделать метод, который вставляет в две разные базы данных транзакционные. Возможно ли это с MongoDB? и как это реализовать?

1 Ответ

0 голосов
/ 23 июля 2020

Чтобы использовать многодокументные транзакции в MongoDB для нескольких баз данных в Spring Data MongoDB, вам необходимо настроить MongoTemplate для каждой базы данных, но все они должны использовать один и тот же MongoDbFactory, потому что он рассматривается как транзакционный ресурс.

Это означает, что вам нужно будет переопределить пару методов MongoTemplate, чтобы он использовал базу данных, которую он должен использовать (а не тот, который настроен внутри SimpleMongoClientDbFactory).

Давайте Предположим, что ваши базы данных называются «один» и «два». Затем это выглядит так:

public class MongoTemplateWithFixedDatabase extends MongoTemplate {
    private final MongoDbFactory mongoDbFactory;
    private final String databaseName;

    public MongoTemplateWithFixedDatabase(MongoDbFactory mongoDbFactory,
            MappingMongoConverter mappingMongoConverter, String databaseName) {
        super(mongoDbFactory, mappingMongoConverter);
        this.mongoDbFactory = mongoDbFactory;
        this.databaseName = databaseName;
    }

    @Override
    protected MongoDatabase doGetDatabase() {
        return MongoDatabaseUtils.getDatabase(databaseName, mongoDbFactory, ON_ACTUAL_TRANSACTION);
    }
}

и

@Bean
public MongoDbFactory mongoDbFactory() {
    // here, some 'default' database name is configured, the following MongoTemplate instances will ignore it
    return new SimpleMongoDbFactory(mongoClient(), getDatabaseName());
}

@Bean
public MongoTransactionManager mongoTransactionManager() {
    return new MongoTransactionManager(mongoDbFactory());
}

@Bean
public MongoTemplate mongoTemplateOne(MongoDbFactory mongoDbFactory,
        MappingMongoConverter mappingMongoConverter) {
    MongoTemplate template = new MongoTemplateWithFixedDatabase(mongoDbFactory,
            mappingMongoConverter, "one");
    return template;
}

@Bean
public MongoTemplate mongoTemplateTwo(MongoDbFactory mongoDbFactory,
        MappingMongoConverter mappingMongoConverter) {
    MongoTemplate template = new MongoTemplateWithFixedDatabase(mongoDbFactory,
            mappingMongoConverter, "two");
    return template;
}

Затем просто введите mongoTemplateOne и mongoTemplateTwo в свой сервис, отметьте его метод @Transactional, и он должен работать .

Реактивный случай

В реактивном случае очень похоже. Конечно, вам нужно использовать реактивные версии классов, такие как ReactiveMongoTemplate, ReactiveMongoDatabaseFactory, ReactiveMongoTransactionManager.

Также есть пара предостережений. Во-первых, вам нужно переопределить 3 метода, а не 2 (поскольку getCollection(String) также нужно переопределить). Кроме того, мне пришлось сделать это с помощью абстрактного класса, чтобы он работал:

@Bean
public ReactiveMongoOperations reactiveMongoTemplateOne(
        @ReactiveMongoDatabaseFactory reactiveMongoDatabaseFactory,
        MappingMongoConverter mappingMongoConverter) {
    ReactiveMongoTemplate template = new ReactiveMongoTemplate(reactiveMongoDatabaseFactory,
            mappingMongoConverter) {

        @Override
        protected Mono<MongoDatabase> doGetDatabase() {
            return ReactiveMongoDatabaseUtils.getDatabase("one", reactiveMongoDatabaseFactory,
                    ON_ACTUAL_TRANSACTION);
        }

        @Override
        public MongoDatabase getMongoDatabase() {
            return reactiveMongoDatabaseFactory.getMongoDatabase(getDatabaseName());
        }

        @Override
        public MongoCollection<Document> getCollection(String collectionName) {
            Assert.notNull(collectionName, "Collection name must not be null!");

            try {
                return reactiveMongoDatabaseFactory.getMongoDatabase(getDatabaseName())
                        .getCollection(collectionName);
            } catch (RuntimeException e) {
                throw potentiallyConvertRuntimeException(e,
                        reactiveMongoDatabaseFactory.getExceptionTranslator());
            }
        }

        private RuntimeException potentiallyConvertRuntimeException(RuntimeException ex,
                PersistenceExceptionTranslator exceptionTranslator) {
            RuntimeException resolved = exceptionTranslator.translateExceptionIfPossible(ex);
            return resolved == null ? ex : resolved;
        }
    };
    return template;
}

PS предоставленный код был протестирован с помощью spring-data-mongodb 2.2.4.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...