新项目中使用了neo4j,支持事务,但是@Transactional注解不支持多个事务管理器,默认使用transactionManager,需要实现@Transactional管理mysql事务,我的做法是,定义@MultiTransaction注解,使用@Around环绕通知,一起提交或回滚neo4j事务和mysql事务
1.依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2.定义注解
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MultiTransaction {
//这里可以自定义参数
}
3.定义Aspect
@Aspect
@Component
public class TransactionAspect {
/**
* 定义neo4j事务管理器
* @param sessionFactory
* @return
*/
@Bean("neo4jTransactionManager")
public Neo4jTransactionManager neo4jTransactionManager(SessionFactory sessionFactory) {
return new Neo4jTransactionManager(sessionFactory);
}
/**
* 定义mysql事务管理器,必须有transactionManager作为默认事务管理器
* @param emf
* @return
*/
@Bean("transactionManager")
public JpaTransactionManager jpaTransactionManager(EntityManagerFactory emf) {
return new JpaTransactionManager(emf);
}
@Autowired
@Qualifier("neo4jTransactionManager")
Neo4jTransactionManager neo4jTransactionManager;
@Autowired
@Qualifier("transactionManager")
JpaTransactionManager jpaTransactionManager;
@Around("@annotation(MultiTransaction)")
public Object multiTransaction(ProceedingJoinPoint proceedingJoinPoint) {
TransactionStatus neo4jTransactionStatus = neo4jTransactionManager.getTransaction(new DefaultTransactionDefinition());
TransactionStatus jpaTransactionStatus = jpaTransactionManager.getTransaction(new DefaultTransactionDefinition());
try {
Object obj = proceedingJoinPoint.proceed();
//注意:事务之间必须是包含关系,不能交叉
jpaTransactionManager.commit(jpaTransactionStatus);
neo4jTransactionManager.commit(neo4jTransactionStatus);
return obj;
} catch (Throwable throwable) {
jpaTransactionManager.rollback(jpaTransactionStatus);
neo4jTransactionManager.rollback(neo4jTransactionStatus);
throw new RuntimeException(throwable);
}
}
}
4.使用
@RequestMapping("/test")
@MultiTransaction
public void test() {
//
}