Spring Data MongoDBトランザクション
1. 概要
4.0リリースから、MongoDBはマルチドキュメントACIDトランザクションをサポートします。 そして、Spring Data Lovelace now provides support for these native MongoDB transactions。
このチュートリアルでは、同期トランザクションとリアクティブトランザクションに対するSpring DataMongoDBのサポートについて説明します。
また、非ネイティブトランザクションのサポートに関するSpring DataTransactionTemplateについても見ていきます。
このSpringDataモジュールの概要については、introductory write-upをご覧ください。
2. MongoDB4.0をセットアップする
まず、新しいネイティブトランザクションのサポートを試すために、最新のMongoDBをセットアップする必要があります。
開始するには、MongoDB Download Centerから最新バージョンをダウンロードする必要があります。
次に、コマンドラインを使用してmongodサービスを開始します。
mongod --replSet rs0
最後に、レプリカセットを開始します(まだ開始されていない場合)。
mongo --eval "rs.initiate()"
MongoDBは現在、レプリカセットを介したトランザクションをサポートしていることに注意してください。
3. Mavenの構成
次に、次の依存関係をpom.xmlに追加する必要があります。
org.springframework.data
spring-data-mongodb
2.1.0.RELEASE
org.springframework.data
spring-data-releasetrain
Lovelace-M3
pom
import
マイルストーンリポジトリをpom.xmlにも追加する必要があることに注意してください。
spring-milestones
Spring Milestones
https://repo.spring.io/milestone
false
ライブラリの最新リリースは、Central Repositoryにあります。
4. MongoDBの構成
それでは、構成を見てみましょう。
@Configuration
@EnableMongoRepositories(basePackages = "com.example.repository")
public class MongoTransactionConfig extends AbstractMongoConfiguration{
@Bean
MongoTransactionManager transactionManager(MongoDbFactory dbFactory) {
return new MongoTransactionManager(dbFactory);
}
@Override
protected String getDatabaseName() {
return "test";
}
@Override
public MongoClient mongoClient() {
return new MongoClient("127.0.0.1", 27017);
}
}
デフォルトでは無効になっているため、ネイティブMongoDBトランザクションを有効にするための構成のwe need to register MongoTransactionManagerに注意してください。
5. 同期トランザクション
構成が完了したら、ネイティブのMongoDBトランザクションを使用するために必要なことはannotate our method with*@Transactional*.だけです。
注釈付きメソッド内のすべてが1つのトランザクションで実行されます。
@Test
@Transactional
public void whenPerformMongoTransaction_thenSuccess() {
userRepository.save(new User("John", 30));
userRepository.save(new User("Ringo", 35));
Query query = new Query().addCriteria(Criteria.where("name").is("John"));
List users = mongoTemplate.find(query, User.class);
assertThat(users.size(), is(1));
}
マルチドキュメントトランザクション内ではlistCollectionsコマンドを使用できないことに注意してください。例:
@Test(expected = MongoTransactionException.class)
@Transactional
public void whenListCollectionDuringMongoTransaction_thenException() {
if (mongoTemplate.collectionExists(User.class)) {
mongoTemplate.save(new User("John", 30));
mongoTemplate.save(new User("Ringo", 35));
}
}
この例では、collectionExists()メソッドを使用したため、MongoTransactionExceptionがスローされます。
また、マルチドキュメントトランザクション内でcountを実行することはできません。
@Test(expected = MongoCommandException.class)
@Transactional
public void whenCountDuringMongoTransaction_thenException() {
userRepository.save(new User("John", 30));
userRepository.save(new User("Ringo", 35));
userRepository.count();
}
ただし、単純なクエリでこの問題を回避し、結果のリストのサイズを取得できます。
@Test
@Transactional
public void whenQueryDuringMongoTransaction_thenSuccess() {
userRepository.save(new User("Jane", 20));
userRepository.save(new User("Nick", 33));
List users = mongoTemplate.find(new Query(), User.class);
assertTrue(users.size() > 1);
}
6. TransactionTemplate
Spring Dataが新しいMongoDBネイティブトランザクションをサポートする方法を見ました。 さらに、Spring Dataは非ネイティブオプションも提供します。
We can perform non-native transactions using Spring Data TransactionTemplate:
@Test
public void givenTransactionTemplate_whenPerformTransaction_thenSuccess() {
mongoTemplate.setSessionSynchronization(SessionSynchronization.ALWAYS);
TransactionTemplate transactionTemplate = new TransactionTemplate(mongoTransactionManager);
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
mongoTemplate.insert(new User("Kim", 20));
mongoTemplate.insert(new User("Jack", 45));
};
});
Query query = new Query().addCriteria(Criteria.where("name").is("Jack"));
List users = mongoTemplate.find(query, User.class);
assertThat(users.size(), is(1));
}
非ネイティブのSpringDataトランザクションを使用するには、SessionSynchronizationをALWAYSに設定する必要があります。
7. リアクティブトランザクション
最後に、Spring Data support for MongoDB reactive transactionsを見てみましょう。
リアクティブMongoDBを使用するには、pom.xmlにさらにいくつかの依存関係を追加する必要があります。
org.mongodb
mongodb-driver-reactivestreams
1.9.2
io.projectreactor
reactor-test
3.2.0.RELEASE
test
mongodb-driver-reactivestreamsおよびreactor-testの依存関係は、MavenCentralで利用できます。
そしてもちろん、Reactive MongoDBを構成する必要があります。
@Configuration
@EnableReactiveMongoRepositories(basePackages
= "com.example.reactive.repository")
public class MongoReactiveConfig
extends AbstractReactiveMongoConfiguration {
@Override
public MongoClient reactiveMongoClient() {
return MongoClients.create();
}
@Override
protected String getDatabaseName() {
return "reactive";
}
}
リアクティブMongoDBでトランザクションを使用するには、ReactiveMongoOperationsでinTransaction()メソッドを使用する必要があります。
@Autowired
private ReactiveMongoOperations reactiveOps;
@Test
public void whenPerformTransaction_thenSuccess() {
User user1 = new User("Jane", 23);
User user2 = new User("John", 34);
reactiveOps.inTransaction()
.execute(action -> action.insert(user1)
.then(action.insert(user2)));
}
Spring Dataのリアクティブリポジトリの詳細については、hereを参照してください。
8. 結論
この記事では、Spring Dataを使用してネイティブおよび非ネイティブのMongoDBトランザクションを使用する方法を学びました。
例の完全なソースコードは利用可能ですover on GitHub.