@Transactional yöntem, @Transactional anotation olmadan başka bir yöntemi çağırıyor mu?


89

Service sınıfında olarak işaretlenmiş bir yöntem gördüm @Transactional, ancak aynı sınıftaki, olarak işaretlenmemiş bazı diğer yöntemleri de çağırıyordu @Transactional.

Ayrı yöntemlere yapılan çağrının, uygulamanın DB'ye ayrı bağlantılar açmasına veya ana işlemi askıya almasına vb. Neden olduğu anlamına mı geliyor?

Ek açıklamalı başka bir yöntem tarafından çağrılan herhangi bir ek açıklama içermeyen bir yöntem için varsayılan davranış nedir @Transactional?

Yanıtlar:


119

Bir @Transactionalişlem bloğu içinde olmayan bir yöntemi çağırdığınızda , ana işlem yeni yönteme devam edecektir. Ana yöntemle (with @Transactional) aynı bağlantıyı ve çağrılan yöntemden kaynaklanan herhangi bir istisnayı kullanır (olmadan @Transactional, işlemin işlem tanımında yapılandırıldığı gibi geri alınmasına neden olmaz.

Aynı örnek içindeki @Transactionalbir yöntemden ek açıklama içeren bir yöntemi çağırırsanız @Transactional, çağrılan yöntemlerin işlem davranışının işlem üzerinde herhangi bir etkisi olmayacaktır. Ancak, bir işlem tanımına sahip başka bir yöntemden bir işlem tanımına sahip bir yöntemi çağırırsanız ve bunlar farklı örneklerdeyse, çağrılan yöntemdeki kod, çağrılan yöntemde verilen işlem tanımlarını izleyecektir.

Sen bölümünde daha fazla ayrıntı bulabilirsiniz Bildirimsel işlem yönetimi ve yay işlem belgelerinde .

Spring bildirim temelli işlem modeli AOP proxy kullanır. bu nedenle işlemlerin oluşturulmasından AOP vekili sorumludur. AOP proxy'si yalnızca örnekte bulunan yöntemler örneğin dışarıdan çağrılırsa etkin olacaktır.


bu baharın varsayılan davranışı mı?
goe

Evet. Varsayılan davranıştır.
Arun P Johny

2
@Tomasz Evet. Ancak başka bir @Transactional yönteminden çağrılan bir yöntemde işlem yayılmasının değiştirilmesinin hiçbir etkisi olmayacağından da bahsetmek gerekir.
Fil

1
@Tomasz, demek istediğim buydu will follow the transaction definitions given in the called method. Ancak çağrı aynı nesne örneğinden gelirse, işlemin sürdürülmesinden sorumlu olan aop proxy'leri aracılığıyla yayılmayacağından herhangi bir etkisi olmayacaktır.
Arun P Johny

5
@Filip, Bu tamamen doğru değil, Eğer @Transactionalfarklı bir nesne / örnekten tanımlı bir metodu çağırırsanız , çağıran metot farklı @Transactionalniteliklere sahip olsa bile , çağrılan metot kendi işlem tanımını takip edecektir.
Arun P Johny

24
  • Bu, ayrı yöntemlere yapılan çağrının, uygulamanın DB'ye ayrı bağlantılar açmasına veya ana işlemi askıya almasına vb. Neden olduğu anlamına mı geliyor?

Bu, yayılma düzeyine bağlıdır . İşte tüm olası seviye değerleri .

Örneğin, bir yayılma seviyesinin YERLEŞTİRİLMİŞ olması durumunda, mevcut bir işlem "askıya alınacak" ve yeni bir işlem yaratılacaktır ( not: iç içe bir işlemin gerçek oluşturulması yalnızca belirli işlem yöneticilerinde çalışacaktır )

  • @Transactional ek açıklama içeren başka bir yöntem tarafından çağrılan herhangi bir ek açıklama içermeyen bir yöntem için varsayılan davranış nedir?

Varsayılan yayılma seviyesi ("davranış" dediğiniz şey) GEREKLİDİR . Üzerinde bir @Transactionalaçıklama olan (veya XML aracılığıyla bildirimli olarak işlem gören) bir "iç" yöntem çağrıldığında , aynı işlem içinde yürütülür , örneğin "yeni bir şey" oluşturulmaz.


NOT_SUPPORTED'ın herhangi bir ek açıklaması olmayan alt aramalarına ne dersiniz? NOT_Supported'ı devralıyor mu veya REQURED varsayılan olduğu için yeni bir işlem mi açtı? Örneğin: f1 için NOT_SUPPORTED ve f2 için non notuyla f1.call () {f2 ()}.
Dave

8

@Transactional, işlem sınırını (başlangıç ​​/ bitiş) işaretler, ancak işlemin kendisi iş parçacığına bağlıdır. Bir işlem başladığında, orijinal yöntem geri dönene ve işlem tamamlayana / geri alınana kadar yöntem çağrılarında yayılır.

@Transactional ek açıklamasına sahip başka bir yöntem çağrılırsa, yayılma o açıklamanın yayılma özniteliğine bağlıdır.


3 cevap bir dereceye kadar birbiriyle çelişiyor, hangisinin daha doğru olduğundan emin değil.
Trump 2020 - Adalet

1
@EricWang Bugün bu senaryoyu test ettiğimi ve Arun P Johny'nin yanıtının (yorumlarla birlikte) bu dahili çağrı senaryosu için en doğru olduğunu paylaşmak istedim .
Vinay Vissh

3

İç yöntem @Transactional ile açıklanmadıysa, iç yöntem dış yöntemi etkileyecektir.

İç yöntemin de @Transactional ile açıklanması durumunda REQUIRES_NEW, aşağıdaki olacaktır.

...
@Autowired
private TestDAO testDAO;

@Autowired
private SomeBean someBean;

@Override
@Transactional(propagation=Propagation.REQUIRED)
public void outerMethod(User user) {
  testDAO.insertUser(user);
  try{
    someBean.innerMethod();
  } catch(RuntimeException e){
    // handle exception
  }
}


@Override
@Transactional(propagation=Propagation.REQUIRES_NEW)
public void innerMethod() {
  throw new RuntimeException("Rollback this transaction!");
}

İç yönteme açıklama eklenmiştir REQUIRES_NEWve bir RuntimeException oluşturur, böylece işlemin geri alınmasını ayarlar, ancak dış işlemi ETKİLEMEZ. Dış işlem, iç işlem başladığında DURAKLATILIR ve ardından iç işlem tamamlandıktan SONRA DEVAM EDİLİR. Birbirlerinden bağımsız olarak çalışırlar, bu nedenle dış işlem başarıyla gerçekleştirilebilir.


1
Yeni başlayanlar için açıklığa kavuşturmak için, innerMethod () 'un dışMethod ()' dan farklı bir bean (diğer adıyla Spring-managed java Object) olması gerektiğinden oldukça eminim. İkisi de aynı çekirdek üzerindeyse, innerMethod'un ek açıklamasında belirtilen İşlem davranışını gerçekten kullanacağını sanmıyorum. Bunun yerine, OuterMethod () bildiriminde bildirileni kullanacaktır. Bunun nedeni, Spring'in @Transactional ek açıklamaları için kullanılan AOP'yi işleme biçimi ( docs.spring.io/spring/docs/3.0.x/spring-framework-reference/… )
johnsimer
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.