admin管理员组文章数量:1558103
@Transactional 同一个类中无事务方法a()内部调用有事务方法b()的问题
Methods should not call same-class methods with incompatible "@Transactional" values
When using Spring proxies, calling a method in the same class (e.g. this.aMethod()
) with an incompatible @Transactional
requirement will result in runtime exceptions because Spring only "sees" the caller and makes no provisions for properly invoking the callee.
Therefore, certain calls should never be made within the same class:
From | To |
---|---|
non-@Transactional |
MANDATORY, NESTED, REQUIRED, REQUIRES_NEW |
MANDATORY | NESTED, NEVER, NOT_SUPPORTED, REQUIRES_NEW |
NESTED | NESTED, NEVER, NOT_SUPPORTED, REQUIRES_NEW |
NEVER | MANDATORY, NESTED, REQUIRED, REQUIRES_NEW |
NOT_SUPPORTED | MANDATORY, NESTED, REQUIRED, REQUIRES_NEW |
REQUIRED or @Transactional |
NESTED, NEVER, NOT_SUPPORTED, REQUIRES_NEW |
REQUIRES_NEW | NESTED, NEVER, NOT_SUPPORTED, REQUIRES_NEW |
SUPPORTS | MANDATORY, NESTED, NEVER, NOT_SUPPORTED, REQUIRED, REQUIRES_NEW |
Noncompliant Code Example
@Override public void doTheThing() { // ... actuallyDoTheThing(); // Noncompliant } @Override @Transactional public void actuallyDoTheThing() { // ... }
org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only↵ at org.springframework.transaction.support.AbstractPlatformTransactionManagermit(AbstractPlatformTransactionManager.java:724)↵ at org.springframework.transaction.interceptor.TransactionAspectSupportmitTransactionAfterReturning(TransactionAspectSupport.java:518)↵ at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:292)↵ at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)↵ at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)↵ at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:97)↵ at com.chanjet.paasmon.base.interceptor.ExceptionInterceptor.around(ExceptionInterceptor.java:63)↵ at sun.reflect.GeneratedMethodAccessor85.invoke(Unknown Source)↵ at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)↵ at java.lang.reflect.Method.invoke(Method.java:498)↵ at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:629)↵ at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:618)↵ at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)↵ at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:168)↵ at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)↵ at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)↵ at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:673)↵
Spring事务分类
Spring 提供了两种事务管理方式:声明式事务管理和编程式事务管理。
图解SPRING事务
声明式事务
配置方式
注:以下配置代码参考自Spring事务配置的五种方式
根据代理机制的不同,总结了五种Spring事务的配置方式,配置文件如下:
1、每个Bean有一个代理
2、所有Bean共享一个代理基类
3、使用拦截器
4、使用tx标签配置拦截器
<!-- 事务管理 -->
<bean >
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 使用annotation定义事务 -->
<tx:annotation-driven transaction-manager="transactionManager" proxy-target- />
<aop:config>
<aop:advisor pointcut="execution(* com.*.*.event.local.service.*.*(..))" advice-ref="txAdviceLocalEvent"/>
</aop:config>
<tx:advice >
<tx:attributes>
<tx:method name="update*"/>
<tx:method name="add*"/>
<tx:method name="del*"/>
<tx:method name="*" read-only="true"/>
</tx:attributes>
</tx:advice>
5、全注解方式
一个声明式事务的实例
注:该实例参考自Spring中的事务管理实例详解
首先是数据库表
book(isbn, book_name, price)
account(username, balance)
book_stock(isbn, stock)
然后是XML配置
<beans xmlns="http://www.springframework/schema/beans"
xmlns:xsi="http://www.w3/2001/XMLSchema-instance"
xmlns:context="http://www.springframework/schema/context"
xmlns:aop="http://www.springframework/schema/aop"
xmlns:tx="http://www.springframework/schema/tx"
xsi:schemaLocation="http://www.springframework/schema/beans
http://www.springframework/schema/beans/spring-beans-3.0.xsd
http://www.springframework/schema/context
http://www.springframework/schema/context/spring-context-3.0.xsd
http://www.springframework/schema/aop http://www.springframework/schema/aop/spring-aop-2.5.xsd
http://www.springframework/schema/tx http://www.springframework/schema/tx/spring-tx-2.5.xsd">
<import resource="applicationContext-db.xml" />
<context:component-scan
base-package="com.springinaction.transaction">
</context:component-scan>
<tx:annotation-driven transaction-manager="txManager"/>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
使用的类
BookShopDao
package com.springinaction.transaction;
public interface BookShopDao {
// 根据书号获取书的单价
public int findBookPriceByIsbn(String isbn);
// 更新书的库存,使书号对应的库存-1
public void updateBookStock(String isbn);
// 更新用户的账户余额:account的balance-price
public void updateUserAccount(String username,
版权声明:本文标题:Spring事务管理 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dianzi/1727342443a1109578.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论