Spring数据和mongodb – 在@Transactional中简单回滚弹簧

我有2个存储库,一个用于mongodb(DocumentRepository),另一个用于hibernate实体(EntityRepository)

我有一个简单的服务:

@Transactional public doSomePersisting() { try { this.entityRepository.save(entity); this.documentRepository.save(document); } catch(...) { //Rollback mongoDB here } } 

是否可以在“// Rollback mongoDB here”行回滚mongoDB? 我已经从实体部分回滚(Transactional annotation)

MongoDB不支持事务(至少不在单个文档的范围之外)。 如果您想要回滚更改,您需要亲自手工制作。 有一些资源可以描述在Mongo中实现自己的事务的方法,如果你在某些情况下真的需要它们的话。 你可以看看..

http://docs.mongodb.org/manual/tutorial/perform-two-phase-commits/

这只是您可以使用的模式的解释。 如果您发现应用程序中绝对需要事务处理,则应考虑MongoDB是否适合您的需求。

很抱歉重新发布我的回答。

允许更早的代码将数据插入MongoDB,甚至将数据插入到PostgreSQL中的查询exception(使用myBatis)。

我已经解决了MongoDB和Relational数据库之间的数据事务问题,并且@Transactional通过在上面的代码中进行这些更改来完美地工作。

@Transactional Management的解决方案。

Mongo Config类

 @Configuration public class MongoConfig extends AbstractMongoConfiguration{ private static final Logger LOG = LoggerFactory.getLogger(MongoConfig.class); @Value("${spring.data.mongodb.database}") private String dbName; @Value("${spring.data.mongodb.host}") private String dbHost; @Value("${spring.data.mongodb.port}") private int dbPort; @Override public String getDatabaseName() { return dbName; } @Bean public MongoClient mongoClient(){ return new MongoClient(dbHost, dbPort); } @Bean public MongoDbFactory mongoDbFactory(){ return new SimpleMongoDbFactory(mongoClient(),dbName); } @Bean public MongoTemplate mongoTemplate() { DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory()); MappingMongoConverter mappingMongoConverter = new MappingMongoConverter(dbRefResolver, new MongoMappingContext()); // Don't save _class to mongo mappingMongoConverter.setTypeMapper(new DefaultMongoTypeMapper(null)); MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory(),mappingMongoConverter); mongoTemplate.setSessionSynchronization(SessionSynchronization.ON_ACTUAL_TRANSACTION); return mongoTemplate; } public MongoTemplate fetchMongoTemplate(int projectId) { DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory()); MappingMongoConverter mappingMongoConverter = new MappingMongoConverter(dbRefResolver, new MongoMappingContext()); // Don't save _class to mongo mappingMongoConverter.setTypeMapper(new DefaultMongoTypeMapper(null)); MongoDbFactory customizedDBFactory = new SimpleMongoDbFactory(mongoClient(), dbName+"_"+projectId); MongoTemplate mongoTemplate = new MongoTemplate(customizedDBFactory,mappingMongoConverter); MongoTransactionManager mongoTransactionManager = new MongoTransactionManager(customizedDBFactory); return mongoTemplate; } @Bean public MongoTransactionManager mongoTransactionManager() { return new MongoTransactionManager(mongoDbFactory()); } } 

数据插入的服务类

 @Service @Component public class TestRepositoryImpl implements TestRepository{ private static final Logger LOG = LoggerFactory.getLogger(TestRepositoryImpl.class); @Autowired MongoConfig mongoConfig; @Autowired MongoTemplate mongoTemplate; @Autowired MongoTransactionManager mongoTransactionManager; @Autowired UserService userService; @Override @Transactional public void save(Test test){ int projectId = 100; if (projectId != 0) { mongoTemplate = mongoConfig.fetchMongoTemplate(100); mongoTemplate.setSessionSynchronization(SessionSynchronization.ALWAYS); } mongoTemplate.insert(test); IdName idName = new IdName(); idName.setName("test"); mongoTemplate.insert(idName); User user = new User(); user.setName("Demo"); user.setEmail("srini@abspl.in"); user.setPassword("sdfsdfsdf"); userService.save(user); } } 

的pom.xml

   4.0.0 com.abcplusd.sample.mongoapi sample-mongo-api 1.0-SNAPSHOT Sample Spring Boot Mongo API Demo project for Spring Boot Mongo with Spring Data Mongo  org.springframework.boot spring-boot-starter-parent 2.0.1.RELEASE     UTF-8 1.8    org.springframework.boot spring-boot-starter-web   org.springframework.boot spring-boot-starter-actuator   org.springframework.data spring-data-mongodb 2.1.0.RELEASE   org.mongodb mongo-java-driver     org.springframework.data spring-data-commons 2.1.0.RELEASE   org.mongodb mongo-java-driver 3.8.2   org.mybatis mybatis-spring 1.3.1   org.postgresql postgresql 42.2.2   org.mybatis.spring.boot mybatis-spring-boot-starter 1.3.2   org.mybatis mybatis 3.4.5      org.springframework.boot spring-boot-maven-plugin     

MongoDB回滚不适用于@Transactional和MongoTransactionManager。 完整的代码实现在这里。

MongoDB 4.0,mongo-java-driver(版本3.8.2),spring-data-mongodb(版本2.1.0)

MongoConfig类

 @Configuration public class MongoConfig extends AbstractMongoConfiguration{ private static final Logger LOG = LoggerFactory.getLogger(MongoConfig.class); @Value("${spring.data.mongodb.database}") private String dbName; @Value("${spring.data.mongodb.host}") private String dbHost; @Value("${spring.data.mongodb.port}") private int dbPort; @Override public String getDatabaseName() { return dbName; } @Bean public MongoClient mongoClient(){ return new MongoClient(dbHost, dbPort); } @Bean public MongoDbFactory mongoDbFactory(){ return new SimpleMongoDbFactory(mongoClient(),dbName); } @Bean public MongoTemplate mongoTemplate() { DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory()); MappingMongoConverter mappingMongoConverter = new MappingMongoConverter(dbRefResolver, new MongoMappingContext()); // Don't save _class to mongo mappingMongoConverter.setTypeMapper(new DefaultMongoTypeMapper(null)); MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory(),mappingMongoConverter); return mongoTemplate; } public MongoTemplate fetchMongoTemplate(int projectId) { DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory()); MappingMongoConverter mappingMongoConverter = new MappingMongoConverter(dbRefResolver, new MongoMappingContext()); // Don't save _class to mongo mappingMongoConverter.setTypeMapper(new DefaultMongoTypeMapper(null)); MongoTemplate mongoTemplate = new MongoTemplate(new SimpleMongoDbFactory(mongoClient(), dbName+"_"+projectId),mappingMongoConverter); return mongoTemplate; } @Bean public MongoTransactionManager mongoTransactionManager() { return new MongoTransactionManager(mongoDbFactory()); } } 

用于在mongodb和postgreSQL中插入数据的服务类(使用mybatis)。

 @Service @Component public class TestRepositoryImpl implements TestRepository{ private static final Logger LOG = LoggerFactory.getLogger(TestRepositoryImpl.class); @Autowired MongoTemplate mongoTemplate; @Autowired MongoConfig mongoConfig; //@Autowired MongoClient mongoClient; @Autowired UserService userService; @Override @Transactional public void save(Test test){ LOG.info("mongoTemplate <{}>", mongoTemplate.getDb().getName()); int projectId = 100; if (projectId != 0) { mongoTemplate = mongoConfig.fetchMongoTemplate(100); LOG.info("mongoTemplate <{}>", mongoTemplate.getDb().getName()); } //Inserting data to mongodb mongoTemplate.insert(test); IdName idName = new IdName(); idName.setName("test"); mongoTemplate.insert(idName); //Inserting data to postgreSQL User user = new User(); user.setName("Demo"); user.setEmail("XXXX@XXXX.in"); user.setPassword("sdfsdfsdf"); userService.save(user); //This line throws query exception. } 

数据不会在mongodb上回滚,甚至在此行抛出exceptionuserService.save(user); //此行在插入查询exception时抛出无效语法。

 ### SQL: insert into test.user(id,name,email,password values(?,?,?,?) ### Cause: org.postgresql.util.PSQLException: ERROR: syntax error at or near "values" Position: 50 ; bad SQL grammar []; nested exception is org.postgresql.util.PSQLException: ERROR: syntax error at or near "values" Position: 50] with root cause