sql >> Database teknologi >  >> NoSQL >> MongoDB

Spring Data MongoDB Transaktioner

1. Oversigt

Fra 4.0-udgivelsen understøtter MongoDB multi-dokument ACID-transaktioner. Og Spring Data Lovelace giver nu support til disse indbyggede MongoDB-transaktioner .

I denne øvelse vil vi diskutere Spring Data MongoDB-understøttelse af synkrone og reaktive transaktioner.

Vi tager også et kig på Spring Data TransactionTemplate for ikke-indfødte transaktioner support.

For en introduktion til dette Spring Data-modul, se vores introduktionsskrift.

2. Konfigurer MongoDB 4.0

Først skal vi konfigurere den seneste MongoDB for at prøve den nye native transaktionssupport.

For at komme i gang skal vi downloade den seneste version fra MongoDB Download Center.

Dernæst starter vi mongod tjeneste ved hjælp af kommandolinjen:

mongod --replSet rs0

Til sidst skal du starte replikasæt – hvis ikke allerede:

mongo --eval "rs.initiate()"

Bemærk, at MongoDB i øjeblikket understøtter transaktioner over et replikasæt.

3. Maven-konfiguration

Dernæst skal vi tilføje følgende afhængigheder til vores pom.xml :

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-mongodb</artifactId>
    <version>3.0.3.RELEASE</version>
</dependency>

Den seneste udgivelse af biblioteket kan findes på Central Repository

4. MongoDB-konfiguration

Lad os nu tage et kig på vores konfiguration:

@Configuration
@EnableMongoRepositories(basePackages = "com.baeldung.repository")
public class MongoConfig extends AbstractMongoClientConfiguration{

    @Bean
    MongoTransactionManager transactionManager(MongoDatabaseFactory dbFactory) {
        return new MongoTransactionManager(dbFactory);
    }

    @Override
    protected String getDatabaseName() {
        return "test";
    }

    @Override
    public MongoClient mongoClient() {
        final ConnectionString connectionString = new ConnectionString("mongodb://localhost:27017/test");
        final MongoClientSettings mongoClientSettings = MongoClientSettings.builder()
            .applyConnectionString(connectionString)
            .build();
        return MongoClients.create(mongoClientSettings);
    }
}

Bemærk, at vi skal registrere MongoTransactionManager i vores konfiguration for at aktivere indbyggede MongoDB-transaktioner, da de er deaktiveret som standard.

5. Synkrone transaktioner

Efter vi har afsluttet konfigurationen, er alt, hvad vi skal gøre for at bruge native MongoDB-transaktioner – at annotere vores metode med @Transactional .

Alt inde i den kommenterede metode vil blive udført i én transaktion:

@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<User> users = mongoTemplate.find(query, User.class);

    assertThat(users.size(), is(1));
}

Bemærk, at vi ikke kan bruge listCollections kommando inde i en multi-dokument transaktion – for eksempel:

@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));
    }
}

Dette eksempel kaster en MongoTransactionException som vi brugte collectionExists() metode.

6. Transaktionsskabelon

Vi så, hvordan Spring Data understøtter ny MongoDB-indbygget transaktion. Derudover giver Spring Data også den ikke-native mulighed.

Vi kan udføre ikke-native transaktioner ved hjælp af 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<User> users = mongoTemplate.find(query, User.class);

    assertThat(users.size(), is(1));
}

Vi skal indstille SessionSynchronization til ALTID at bruge ikke-native Spring Data-transaktioner.

7. Reaktive transaktioner

Til sidst vil vi tage et kig på Spring Data support for MongoDB reaktive transaktioner .

Vi bliver nødt til at tilføje et par flere afhængigheder til pom.xml at arbejde med reaktiv MongoDB:

<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongodb-driver-reactivestreams</artifactId>
    <version>4.1.0</version>
</dependency>

<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongodb-driver-sync</artifactId>
    <version>4.0.5</version>
</dependency>
        
<dependency>
    <groupId>io.projectreactor</groupId>
    <artifactId>reactor-test</artifactId>
    <version>3.2.0.RELEASE</version>
    <scope>test</scope>
</dependency>

Afhængighederne mongodb-driver-reactivestreams, mongodb-driver-sync og reactor-test er tilgængelige på Maven Central.

Og selvfølgelig skal vi konfigurere vores Reactive MongoDB:

@Configuration
@EnableReactiveMongoRepositories(basePackages 
  = "com.baeldung.reactive.repository")
public class MongoReactiveConfig 
  extends AbstractReactiveMongoConfiguration {

    @Override
    public MongoClient reactiveMongoClient() {
        return MongoClients.create();
    }

    @Override
    protected String getDatabaseName() {
        return "reactive";
    }
}

For at bruge transaktioner i reaktiv MongoDB skal vi bruge inTransaction() metode i ReactiveMongoOperations :

@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)));
}

Mere information om reaktive depoter i Spring Data er tilgængelig her.


  1. Hvordan konverterer man en pymongo.cursor.Cursor til en diktat?

  2. hvordan man gemmer et komplekst objekt i redis (ved hjælp af redis-py)

  3. Laravel 5.5 redis-køen er for langsom

  4. Sådan bruges aggregrate i mongodb til $match _id