Spring的事务隔离级别等不介绍了 在Spring的事务应用中,有时候需要用到循环体内单个控制事务,每一次循环与上次循环不交叉影响,单独提交或回滚,不影响整个循环体。
//开启事务
@Transactional(propagation = Propagation.REQUIRED) public Result generateMeteringMonthlyBill() { Result ret = Result.success(); GenerateContractBillService billService = BillServiceGenerateFactory.getMeteringMonthlyBillService(); List<ServiceContractDTO> contractList = billService.getContractList(); for(ServiceContractDTO dto:contractList){ try { //单独事务,每次回滚或提交不影响,调用方法的事务(generateMeteringMonthlyBill),也不影响下次循环的事务 billService.processContract(dto,endDate); } catch (Exception e) { //调用日志服务,单独事务 sysLogService.addSysLog("", "", dto.getServicectrCode(), "T03", "", "计量月结合同生成账单失败-异常:" + e.getMessage()); e.printStackTrace(); } } return ret; }由于Spring的事务传播级别是类级别,如果类中的一个方法使用的某一个类型的事务,那么整个类的事务都是一种事务,而且回滚级别也是类级别的,也就是在同一个类中A方法调用B方法,A方法使用REQUIRED,B方法使用的REQUIRES_NEW,在B方法抛出RUNTIMEException,在A方法中捕获,回滚点不是到B方法,而是B方法不进行回滚,因为Spring事务认定级别以类为单位,所以只有退出类的调用时,对会触发事务的提交或回滚。所以即使在同个类中调用不同的事务级别,也是没有意义的。因为Spring 事务代理类执行方法的切入点是类: Spring 代理执行方法(1):
protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation) throws Throwable { // If the transaction attribute is null, the method is non-transactional. final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass); final PlatformTransactionManager tm = determineTransactionManager(txAttr); **final String joinpointIdentification = methodIdentification(method, targetClass);** 执行(2) targetClass不会为NULL: protected String methodIdentification(Method method, Class<?> targetClass) { return (targetClass != null ? targetClass : method.getDeclaringClass()).getName() + "." + method.getName(); }鉴于这个原因,解决方法需要在循环体内的进行单独事务控制的方法,放在一个A类中,包含循环体的方法放在一个B类中,这个A类中方法使用REQUIRES_NEW事务控制,B类使用REQUIRED事务控制。这样就解决了循环体内的相互影响
