1. 程式人生 > >spring的service類呼叫自己方法事務無效

spring的service類呼叫自己方法事務無效

前言

今天在寫程式碼的時候,遇見了一個非常奇怪的問題,我在spring的一個service方法中呼叫本類中的另一個方法(該方法並不是實現介面來的方法,只是把重複的程式碼抽出來的,只在本類中使用),事務竟然無效。我用的是宣告式事務,之前是直接將註解標註在Controller呼叫的service方法上,由於某種原因,我必須將事務開啟到下面的B方法上,但是將事務移動到B方法上時,事務無效了,大概如下:

TestController.java

package com.ryx.test;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;


@Controller
public class TestController {


	@Autowired
	private TestService testService;
	
	@RequestMapping("testTransactional")
	public void testTransactional(){
		testService.testTransactional_A();
	}
}

TestService.java

package com.ryx.test;


import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


@Service
public class TestService {


	@Transactional
	public void testTransactional_A() {
		System.out.println("這裡是呼叫jdbc存庫");
		
		//這裡是執行另一部分邏輯
		testTransactional_B();
	}
	
	public void testTransactional_B() {
		
		//這裡是執行另一部分邏輯
		System.out.println("這裡是呼叫jdbc存庫");
		
	}


}

之前事務是這樣的,我是將@Transactional 放到了方法A上,方法A是是Controller直接呼叫的方法,方法B也是包含在方法A的事務中,事務是可用的,但是我需要將事務只開在B方法上,A方法不需要開啟事務,然後將@Transactional註解 移到B方法上,事務失效了。

然後搜尋了一下@Transactional註解無效,得到以下有用資訊:
1.在需要事務管理的地方加@Transactional 註解。@Transactional 註解可以被應用於介面定義和介面方法、類定義和類的 public 方法上。

[email protected] 註解只能應用到 public 可見度的方法上。 如果你在 protected、private 或者 package-visible 的方法上使用 @Transactional 註解,它也不會報錯, 但是這個被註解的方法將不會展示已配置的事務設定。

3.注意僅僅 @Transactional 註解的出現不足於開啟事務行為,它僅僅 是一種元資料。必須在配置檔案中使用配置元素,才真正開啟了事務行為。(spring配置檔案中,開啟宣告式事務)

4.通過 元素的 “proxy-target-class” 屬性值來控制是基於介面的還是基於類的代理被建立。如果 “proxy-target-class” 屬值被設定為 “true”,那麼基於類的代理將起作用(這時需要CGLIB庫cglib.jar在CLASSPATH中)。如果 “proxy-target-class” 屬值被設定為 “false” 或者這個屬性被省略,那麼標準的JDK基於介面的代理將起作用。

5.Spring團隊建議在具體的類(或類的方法)上使用 @Transactional 註解,而不要使用在類所要實現的任何介面上。在介面上使用 @Transactional 註解,只能當你設定了基於介面的代理時它才生效。因為註解是 不能繼承 的,這就意味著如果正在使用基於類的代理時,那麼事務的設定將不能被基於類的代理所識別,而且物件也將不會被事務代理所包裝。

[email protected]
的事務開啟 ,或者是基於介面的 或者是基於類的代理被建立。所以在同一個類中一個無事務的方法呼叫另一個有事務的方法,事務是不會起作用的。

看到了最後一條,在同一類中一個呼叫本類中另一個有事務的方法,事務是無效的. 網上也給出瞭解決方法:
          1.將這部分業務程式碼寫到另一個service中,然後注入呼叫
          2.要呼叫代理類才會被切進去。 

那麼應該怎麼做呢?既然只有呼叫代理類的方法才能切入,那我們拿到代理類不就好了嘛。網上說直接通過applicationContext.getBean()可以獲得代理物件,我沒有測試,有想法的可以試一下

我用的另一種方法
第一步:首先在spring的配置檔案中加入以下配置
<!-- 啟用自動代理功能 -->
<aop:aspectj-autoproxy/>
<aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true" />
第二步:將之前使用普通呼叫的方法,換成使用代理呼叫
((TestService)AopContext.currentProxy()).testTransactional2();
親測單獨在B方法上開啟事務生效!



相關推薦

spring的service呼叫自己方法事務無效

前言今天在寫程式碼的時候,遇見了一個非常奇怪的問題,我在spring的一個service方法中呼叫本類中的另一個方法(該方法並不是實現介面來的方法,只是把重複的程式碼抽出來的,只在本類中使用),事務竟然無效。我用的是宣告式事務,之前是直接將註解標註在Controller呼叫的

呼叫自己的靜態方法必須把該方法設定為public

    否則調用不了 ParaChecker.isOK(bindingResult);   public class ParaChecker { static BaseResult paraCheck(BindingResu

獲取呼叫自己方法的使用者的包名和

此功能可以獲得第三方的對自己功能的使用情況,可以知道非法操作! //下面程式碼段是獲取呼叫自己方法的人的包名和類名 1.比如一個叫MainActivity內部呼叫了這個初始化 MainActivity中有呼叫:ABC.getInstance(); 結果:name:com.xx.Mai

抽象呼叫自己的抽象方法,實現來自實現(很常用)

直接上程式碼 public abstract class Parent { public abstract void dosomething(); public void say(){ dosomething(); Sys

實現父的抽象方法,父呼叫抽象方法

首先,父類有一個抽象方法,並且在自身的其他方法中呼叫了 public abstract class Baba { public abstract void say(String a); public void dosomething(String a){ say(a); }

關於QWidget的子呼叫show()方法不能顯示的問題

        Qt學了不久,對於它的用法我還不是很熟悉。今天遇到了一個問題:我定義了一個QWidget的子類,程式裡面還有一個主類,主類某一個成員就是QWidget子類的指標,然後用主類去初始化這個指標並呼叫show方法來顯示一些東西,然而這個子類並不能顯示。      

關於在Spring 中方法內部呼叫自身方法事務 REQUIRE_NEW 不生效的解釋

開發十年,就只剩下這套架構體系了! >>>   

Spring的Service調用本方法聲明式事務無效的解決方案

{} 解決 ostc oid color wire ont spa 出了 示例: class Test{ public void a(){ b(); } @Transactional pubic void b(){} }

Spring service本方法呼叫另一個方法事務不生效問題

前些日子一朋友在需要在目標物件中進行自我呼叫,且需要實施相應的事務定義,且網上的一種通過BeanPostProcessor的解決方案是存在問題的。因此專門寫此篇帖子分析why。 1、預備知識 使用AOP 代理後的方法呼叫執行流程,如圖所示 也就是說我們首先呼叫的是

spring 本方法呼叫另外一個方法事務不生效

1、在spring配置檔案中新增 <aop:aspectj-autoproxy expose-proxy="true"/&g

關於呼叫自己寫控制元件庫後,導致主窗體出現索引超範圍,或者值無效等等的問題,以下是解決方法

錯誤如下圖,該錯誤在程式碼中並不會報紅。大家可以看看能否解決。     自定義窗體控制元件,在呼叫的時候會有一個預讀的過程,這個時候如果我們定義下拉選單,如下: comboBox1.Items.Clear(); comboBox1.Items

2.2.1 傳播行為 當事務方法被另一個事務方法調用時,必須指定事務應該如何傳播。例如:方法可能繼續在現有事務中運行,也可能開啟一個新事務,並在自己事務中運行。

相同 comment 自己的 執行 run lose 傳播 tty 可能 2.2.1 傳播行為 當事務方法被另一個事務方法調用時,必須指定事務應該如何傳播。例如:方法可能繼續在現有事務中運行,也可能開啟一個新事務,並在自己的事務中運行。 2.2.1 傳播行為 當事務

繼承----super 呼叫的相同方法(python)

如果一個子類繼承多個父類,然後呼叫父類的相同的方法,使用__mro__ 可以檢視查詢次序 在python 中 有這樣的機制,如果之前一個父類中的方法呼叫過了,下一次就會繼續往下找,而不是重複呼叫 例項: class A: @classmethod

spring 事務處理中,同一個中:A方法(無事務)調B方法(有事務),事務不生效問題

public class MyEntry implements IBaseService{ public String A(String jsonStr) throws Exception{ UserInfo user = null; UserDetail userDetail = nul

子函式呼叫父函式,父函式呼叫方法,子函式重寫了,那麼最後父函式呼叫的是自己方法,還是子函式的方法

Q:子類呼叫父類的方法,父類中某個方法所呼叫的方法,子類也重寫了,那麼最後父類中的方法呼叫的是自己的方法,還是子類的方法。 A:呼叫的是子類的方法。     看程式碼: public class Parent { public void used

和物件 - 方法呼叫

  這個方法呼叫  列印的結果是  1  跟 2  :基本資料型別問題 解:change方法呼叫的時候 傳進去的引數屬於基本資料型別。 change方法在壓站執行的時候 只是重新賦值了  a 跟 b ;main方法執行完change的方法之後

#Java#【1】子呼叫被重寫的方法

一、程式碼 package com.atguigu.exer1; //========== Son =================== public class Son extends Father { public String str = "

java 如何使用多執行緒呼叫的靜態方法

  1.情景展示   靜態方法內部實現:將指定內容生成圖片格式的二維碼;   如何通過多執行緒實現? 2.分析   之所以採用多執行緒,是為了節省時間  3.解決方案   準備工作   logo檔案     將生成的檔案儲存在F

Android:JNI呼叫C++自定義的詳細方法

一般情況下,我們都是用 JNI 呼叫 C++ 的某個方法的程式碼,包括直接使用 android studio 生成的程式碼也是如此。但有時我們需要新建、或者得到的是 C++ 的一個自定義類,在呼叫時就不能像呼叫 C++ 方法那樣了,查閱了一部分其他人的部落格,寫的都比較籠統、模糊,對沒接觸過這塊知識

通過反射建立私有化的物件,呼叫的私有方法,改變私有屬性

首先建立一個類 public class ReflectDemo { private int m=0; //私有屬性 private ReflectDemo(){ //私有無參建構函式 } public ReflectDemo(int aa