自定义JDBCTemplate的事务注解
如果你使用mybatis使用惯了,习惯了他的transactional事务注解,那么如果有一天你接手一个项目,没有使用到orm框架,而是使用了类似于jdbctemplate这样连接数据库的类,这种是没有现成的事务的,是需要你自己配置,所以我这里集成了一个jdbctemplate的事务注解@Transactional。
本文对事务的实现是基于AOP实现的,还是比较简单,建议收藏,只需要两步即可使用。
-
第一步,创建注解@Transactional。
@Target({ElementType.METHOD,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Transactional { int propagation() default TransactionDefinition.PROPAGATION_REQUIRED; }
-
在配置类装配事务管理器对象和数据源对象的bean
@Bean(name = "pethome") @Primary//主数据源 @ConfigurationProperties(prefix = "spring.datasource.druid.pethome") public DataSource pethome() { return DataSourceBuilder.create().build(); } /** * 装配事务管理器 * @return */ @Bean("bookTransactionManager") public DataSourceTransactionManager transactionManager1(DataSource dataSource1) { return new DataSourceTransactionManager(dataSource1); }
-
第二步,使用AOP实现注解功能。
@Aspect @Component public class TransactionalAspect { @Resource(name = "bookTransactionManager") private DataSourceTransactionManager dataSourceTransactionManager; /** * 切入点 * 匹配top.alanlee.template.controller包及其子包下的所有类的所有方法 */ @Pointcut("@within(cn.antu.dynamic.annotation.Transactional) || @annotation(cn.antu.dynamic.annotation.Transactional)") public void pointCut(){ } /** * 环绕通知 * 环绕通知非常强大,可以决定目标方法是否执行,什么时候执行,执行时是否需要替换方法参数,执行完毕是否需要替换返回值。 * 环绕通知第一个参数必须是org.aspectj.lang.ProceedingJoinPoint类型 * @param proceedingJoinPoint */ @Around("pointCut() && @annotation(transactional)") public Object aroundAdvice(ProceedingJoinPoint proceedingJoinPoint,Transactional transactional){ //获得目标类字节码 TransactionStatus transactionStatus = null; try{ transactionStatus = beginTransaction(dataSourceTransactionManager,transactional.propagation()); //执行原方法 Object proceed = proceedingJoinPoint.proceed(); commitTransaction(dataSourceTransactionManager,transactionStatus); return proceed; }catch (Exception e){ e.printStackTrace(); rollbackTransaction(dataSourceTransactionManager,transactionStatus); } catch (Throwable throwable) { throwable.printStackTrace(); rollbackTransaction(dataSourceTransactionManager,transactionStatus); } return null; } /** * 开启事务 */ public TransactionStatus beginTransaction(DataSourceTransactionManager transactionManager,int propagationRequired){ DefaultTransactionDefinition def = new DefaultTransactionDefinition();//事务定义类 def.setPropagationBehavior(propagationRequired); TransactionStatus status = transactionManager.getTransaction(def);// 返回事务对象 return status; } /** * 提交事务 * @param transactionManager * @param status */ public void commitTransaction(DataSourceTransactionManager transactionManager,TransactionStatus status){ transactionManager.commit(status); } /** * 事务回滚 * @param transactionManager * @param status */ public void rollbackTransaction(DataSourceTransactionManager transactionManager,TransactionStatus status){ transactionManager.rollback(status); }
-
创建控制器或者测试类进行测试
@Resource(name = "pethome") private DataSource pethome; @Resource(name = "bookTransactionManager") private DataSourceTransactionManager dataSourceTransactionManager; @RequestMapping(value="/test2",method= RequestMethod.POST) @ApiOperation(value = "测试事务注解", notes = "测试事务注解") @Transactional public List<Map<String,Object>> test2(){ JdbcTemplate jdbcTemplate = new JdbcTemplate(pethome); jdbcTemplate.update("delete FROM t_menu WHERE id = 23"); System.out.println(1/0); jdbcTemplate.update("delete FROM t_employee WHERE id = 338"); return null; }
好了,这就是完整的事务注解创建过程,赶快收藏吧。
欢迎大佬们指导!