@Transactional 内部調用例子 🌰
在 Spring 的 AOP 代理下,隻有目标方法由外部調用,目标方法才由 Spring 生成的代理對象來管理,這會造成自調用問題。
若同一類中的其他沒有@Transactional 注解的方法内部調用有@Transactional 注解的方法,有@Transactional 注解的方法的事務被忽略,不會發生復原
@Service
public class A{
public void action(){
dosome();
}
@Transactional
public void dosome(){
doa.insert(new Object());
}
}
如上代碼,在方法dosome()中抛出異常時,資料操作不會復原
解決方案
思路: 強制使用 AspectJ 對方法進行切面
Springboot 引入 AspectJ 切面
pom.xml 中添加AspectJ:
org.springframework.boot
spring-boot-starter-aop
org.aspectj
aspectjweaver
1.9.5
啟動類中添加 @EnableAspectJAutoProxy(exposeProxy = true)
@SpringBootApplication
@EnableAspectJAutoProxy(exposeProxy = true)
public class DonngPartsApplication {
public static void main(String[] args) {
SpringApplication.run(DonngPartsApplication.class, args);
}
}
注意: exposeProxy = true 若不添加,則會報:
java.lang.IllegalStateException:
Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available,
and ensure that AopContext.currentProxy() is invoked in the same thread as the AOP invocation context.
代碼中 ((A) AopContext.currentProxy()).dosome()
修改為如下代碼,事務就生效啦
@Service
public class A{
public void action(){
((A) AopContext.currentProxy()).dosome();
}
@Transactional
public void dosome(){
doa.insert(new Object());
}
}
@Transactional 進階
1. @Transactional 注解的屬性資訊
屬性
描述
name
當在配置檔案中有多個 TransactionManager , 可以用該屬性指定選擇哪個事務管理器
propagation
事務的傳播行為,預設值為 REQUIRED
isolation
事務的隔離度,預設值采用 DEFAULT
timeout
事務的逾時時間,預設值為-1。如果超過該時間限制但事務還沒有完成,則自動復原事務
read-only
指定事務是否為隻讀事務,預設值為 false;為了忽略那些不需要事務的方法,比如讀取資料,可以設定 read-only 為 true
rollback-for
用于指定能夠觸發事務復原的異常類型,如果有多個異常類型需要指定,各類型之間可以通過逗号分隔
no-rollback- for
抛出 no-rollback-for 指定的異常類型,不復原事務
2. propagation 傳播行為
REQUIRED:如果有事務, 那麼加入事務, 沒有的話建立一個(預設情況下)
NOT_SUPPORTED:容器不為這個方法開啟事務
REQUIRES_NEW:不管是否存在事務,都建立一個新的事務,原來的挂起,新的執行完畢,繼續執行老的事務
MANDATORY:必須在一個已有的事務中執行,否則抛出異常
NEVER:必須在一個沒有的事務中執行,否則抛出異常(與MANDATORY相反)
SUPPORTS:如果其他bean調用這個方法,在其他bean中聲明事務,那就用事務.如果其他bean沒有聲明事務,那就不用事務.
NESTED: 如果目前存在事務,則在嵌套事務内執行。如果目前沒有事務,則進行與PROPAGATION_REQUIRED類似的操作。
3. 事物逾時設定
@Transactional(timeout=30) //預設是30秒
4. 事務隔離級别 isolation
READ_UNCOMMITTED:讀取未送出資料(會出現髒讀, 不可重複讀) 基本不使用
READ_COMMITTED:讀取已送出資料(會出現不可重複讀和幻讀)
REPEATABLE_READ:可重複讀(會出現幻讀)
SERIALIZABLE:串行化
注意
@Transactional 隻能被應用到public方法上
僅僅 @Transactional 注解的出現不足于開啟事務行為,它僅僅 是一種中繼資料
到此這篇關于Java注解@Transactional事務類内調用不生效問題及解決辦法的文章就介紹到這了,更多相關Java注解@Transactional調用内容請搜尋腳本之家以前的文章或繼續浏覽下面的相關文章希望大家以後多多支援腳本之家!