@ İşlemsel ek açıklama nereye aittir?


528

Eğer yerleştirmelidir @Transactionaliçinde DAOsınıfları ve / veya bunların yöntemlerle ya da daha iyisini DAO nesneleri kullanarak aradığınız Servis sınıfları açıklama etmektir? Yoksa her iki "katmana" açıklama eklemek mantıklı mı?

Yanıtlar:


537

İşlemlerin Hizmet katmanına ait olduğunu düşünüyorum. İş birimleri ve kullanım durumlarını bilen kişi. Tek bir işlemde birlikte çalışması gereken bir Hizmete enjekte edilmiş birkaç DAO'nuz varsa, doğru yanıt budur.


Buna katılıyorum. Bazen önemli değil, ancak bazen bundan yararlanabiliyorken örneğin Hazırda Bekleme oturumu süre hareketine yayılmış olduğundan, yüklenen tüm nesneler 1. düzey önbellekte olur ve nesneleri tekrar oturum açmak için yeniden bağlamanız gerekmez, ayrıca tembel olarak yüklenir özellikler fuzz olmadan çalışır.
dma_k

5
Global bir işlem bu @Transactional (yayılma = Yayılma.REQUIRED) değerinden birden fazlasını içerebilir mi? Veya @Tacacactional her zaman bir işlemin sınırı mıdır? Belgelerden aldığımdan emin değilim, ancak
@Transaksiyonel

1
Evet, Bence @Transactional, Yayılım.REQUIRED açıksa işlemin sınırı haline gelir.
duffymo


309

Genel olarak, işlemlerin genellikle hizmet düzeyinde başlatıldığını belirten diğerlerine katılıyorum (elbette ihtiyacınız olan ayrıntı düzeyine bağlı olarak).

Bununla birlikte, bu arada @Transactional(propagation = Propagation.MANDATORY)DAO katmanıma (ve işlemleri başlatmasına izin verilmeyen, ancak mevcut olanları gerektiren) diğer katmanları da eklemeye başladım , çünkü arayanda bir işlemi başlatmayı unuttuğunuz hataları tespit etmek çok daha kolay ( hizmet). DAO'nuza zorunlu yayılma ek açıklamaları eklenirse, yöntem çağrıldığında etkin bir işlem olmadığını belirten bir istisna alırsınız.

Ayrıca, bu ek açıklama için tüm fasulyeleri (fasulye postası işlemcisi) kontrol ettiğim @Transactionalve hizmetler katmanına ait olmayan bir fasulyede Zorunlu dışında bir ek açıklama varsa başarısız olduğum bir entegrasyon testim var . Bu şekilde işlemlere yanlış katman üzerinde başlamadığımızdan emin olurum.


3
Bu dao (arayüzler) katmanında dao impl. katman veya her ikisi mi?
Johan

3
Bu tartışmaya uygun olup olmadığını bilmiyorum, ama başka bir ipucu yazma işlemlerinde dao impl @Transactional (readOnly = true) eklemek olabilir.
maxivis

10
@Johan Spring, İşlem ek açıklamalarını arabirimler yerine uygulama sınıflarına koymanızı önerir.
Mathias G.

Gerçekten bu fikir gibi, benim de projeler için o çalışıyor
Thomas Einwaller

1
Lemme anlıyor muyum ... @TransactionalServis uygulama sınıfına koymam gerektiğini @Transactional(propagation = MANDATORY)mi ve DAO (depo) sınıf uygulamasına mı koymam gerektiğini mi söylüyorsunuz ?
John Henckel

93

İşlem Ek Açıklamaları ayrılmaz tüm işlemlerin etrafına yerleştirilmelidir.

Örneğin, aramanız "şifreyi değiştir" şeklindedir. Bu iki işlemden oluşur

  1. Şifreyi değiştir.
  2. Değişikliği denetleyin.
  3. Şifrenin değiştiği istemciye e-posta gönderin.

Yani, yukarıda, denetim başarısız olursa, şifre değişikliği de başarısız mı olmalı? Öyleyse, işlem 1 ve 2 civarında olmalıdır (hizmet katmanında). E-posta başarısız olursa (muhtemelen bu konuda bir çeşit başarısız güvenli olmalıdır, bu yüzden başarısız olmaz), o zaman değişiklik şifresini ve denetimi geri almalı mı?

Bunlar, nereye koyacağınıza karar verirken sormanız gereken sorulardır @Transactional.


41

Geleneksel Bahar mimarileri için doğru cevap, diğerlerinin daha önce açıkladığı nedenlerle, hizmet sınıflarına işlemsel semantik yerleştirmektir.

İlkbaharda yükselen bir trend, alan güdümlü tasarıma (DDD) doğru. Spring Roo bu eğilimi güzel bir şekilde örnekliyor. Fikri alan nesne POJOs çok sağlamaktır zengin (genellikle onlar tipik Spring mimarileri Hangi daha anemik ) ve alan nesneler kendilerini özellikle de işlem ve kalıcılık semantik koymak. Gereken tek şeyin basit CRUD işlemleri olması durumunda, web denetleyicileri doğrudan etki alanı nesnesi POJO'larında çalışır (bu bağlamda varlık olarak işlev görürler) ve hizmet katmanı yoktur. Etki alanı nesneleri arasında bir tür koordinasyonun gerekli olduğu durumlarda,@Transactiongeleneğe göre. Etki alanı nesneleri üzerindeki işlem yayılımını, etki alanı nesneleri REQUIREDhizmet çekirdeğinde başlatılan işlemler gibi varolan işlemleri kullanacak şekilde ayarlayabilirsiniz .

Teknik olarak bu teknik AspectJ ve <context:spring-configured />. Roo, varlık semantiğini (işlemler ve kalıcılık) etki alanı nesne öğelerinden (temelde alanlar ve iş yöntemleri) ayırmak için AspectJ türler arası tanımları kullanır.


38

Normal durum, hizmet katmanı düzeyinde açıklama eklemek olacaktır, ancak bu gerçekten gereksinimlerinize bağlıdır.

Hizmet katmanına açıklama eklemek DAO düzeyinde açıklama eklemekten daha uzun işlemlerle sonuçlanır. Eşzamanlı işlemler birbirlerinin değişikliklerini görmeyeceği için, sorunları çözebileceğiniz işlem yalıtım düzeyine bağlı olarak. TEKRARLANABİLİR OKUYUN.

DAO'lara açıklama eklemek, hizmet katmanınızın gösterdiği işlevin tek bir (geri alınabilir) işlemle yapılmayacağı dezavantajı ile işlemleri mümkün olduğunca kısa tutacaktır.

Yayılma modu varsayılan olarak ayarlanmışsa, her iki katmana da açıklama eklemek mantıklı değildir.


31

Ben koyun @Transactionalüzerinde @Servicekatmanın ve set rollbackForherhangi istisna ve readOnlyayrıca işlem optimize etmek.

Varsayılan olarak @Transactionalyalnızca (İşaretli İstisnalar) öğesini arar RuntimeException, geri almayı Exception.class(İşaretli İstisnalar) olarak ayarlayarak herhangi bir istisna için geri döner.

@Transactional(readOnly = false, rollbackFor = Exception.class)

Bkz. İşaretli ve Denetlenmeyen İstisnalar .


17

Yoksa her iki "katmana" açıklama eklemek mantıklı mı? - hem hizmet katmanına hem de dao katmanına açıklama eklemek mantıklı değil mi - eğer DAO yönteminin DAO'da "zorunlu" yayılım olan bir hizmet katmanından her zaman çağrıldığından (yayıldığından) emin olmak istiyorsanız. Bu, DAO yöntemlerinin UI katmanından (veya denetleyicilerinden) çağrılması için bazı kısıtlamalar sağlayacaktır. Ayrıca - özellikle DAO katmanını birim test ederken - DAO'nun açıklanması da işlemsel işlevsellik açısından test edilmesini sağlayacaktır.


Bu sonuç iç içe geçmiş işlemlerle sonuçlanmaz mı? Ve onunla birlikte giden tüm ince sorunlar?
HDave

11
Hayır, JPA'da iç içe geçmiş işlem yok. Her ikisine de koymak gayet iyi olurdu - DAO'ya bastığınızda zaten bir işlem yapıyorsanız, bu işlem devam edecektir.
fool4jesus

4
Kullandığınız iç içe işlem gerçekleşebilir propagation=Propagation.REQUIRES_NEW. Aksi takdirde, propogasyon = zorunlu da dahil olmak üzere çoğu durumda, DAO yalnızca hizmet katmanı tarafından başlatılan mevcut işleme katılacaktır.
dan carter


15

Veritabanı düzeyinde İşlem için

çoğunlukla @TransactionalDAO'larda sadece yöntem düzeyinde kullandım, bu yüzden yapılandırma özellikle bir yöntem için kullanılabilir / varsayılanı kullanarak (gerekli)

  1. DAO'nun veri getirme yöntemi (select ..) - buna gerek yoktur @Transactional , işlem durdurucu / ve yürütülmesi gereken AOP proxy'si nedeniyle bazı ek yüklere neden olabilir.

  2. DAO'nun ekleme / güncelleme yapan yöntemleri @Transactional

transctional hakkında çok iyi blog

Uygulama seviyesi için -
İş mantığı için işlem kullanıyorum Beklenmedik hata durumunda geri dönebilmeyi istiyorum

@Transactional(rollbackFor={MyApplicationException.class})
public void myMethod(){

    try {    
        //service logic here     
    } catch(Throwable e) {

        log.error(e)
        throw new MyApplicationException(..);
    }
}

6
Yaklaşık 1 çok güzel bir yazı TransactionaliçindeJava
meşe

11

Genellikle, hizmet katmanına bir işlem konulmalıdır.

Ancak daha önce belirtildiği gibi, bir operasyonun atomikliği, bir ek açıklamanın nerede gerekli olduğunu bize söyler. Bu nedenle, bir nesne üzerinde tek bir "kaydet / güncelle / sil / ... değiştir" işleminin birden fazla tabloda (nesne grafiği boyunca basamaklı olması nedeniyle) birkaç satır değiştirme potansiyeli olan Hazırda Bekleme gibi çerçeveler kullanırsanız, Elbette bu özel DAO yönteminde işlem yönetimi de olmalıdır.


10

@TransactionalEk açıklamalar ayrılmaz tüm işlemlerin etrafına yerleştirilmelidir. Kullanılması @Transactionalbaşka bir yöntem akım yöntemiyle denir eğer işlem yayılmasını yöntemi devam eden işlem katılma seçeneğine sahip olacak o, automatically.In bu davayı ele alınır.

Şimdi örnek verelim:

Biz 2 modelin ie sahip Countryve City. İlişkisel Haritalama Countryve Citymodel, bir Countrykişinin birden fazla Şehri olabileceği gibi, bu nedenle haritalama

@OneToMany(fetch = FetchType.LAZY, mappedBy="country")
private Set<City> cities;

Burada Ülke birden fazla şehre getirilerek haritalandı Lazily. Dolayısıyla, @Transactinalülke nesnesini veritabanından aldığımızda rol alır, o zaman ülke nesnesinin tüm verilerini alırız, ancak şehirleri getireceğimiz için şehirler Setini almayacağız LAZILY.

//Without @Transactional
public Country getCountry(){
   Country country = countryRepository.getCountry();
   //After getting Country Object connection between countryRepository and database is Closed 
}

Şehir Kümesine ülke nesnesinden erişmek istediğimizde, bu Küme'de null değerler alırız, çünkü Set'in nesnesi yalnızca bu Kümeyi yarattı @Transactional, kullandığımız Set'in değerlerini almak için orada verilerle başlatılmaz, yani,

//with @Transactional
@Transactional
public Country getCountry(){
   Country country = countryRepository.getCountry();
   //below when we initialize cities using object country so that directly communicate with database and retrieve all cities from database this happens just because of @Transactinal
   Object object = country.getCities().size();   
}

Temel @Transactionalolarak Hizmet, uç nokta ile bağlantıyı kapatmadan tek işlemde birden fazla çağrı yapabilir.


2
çok bilgilendirici, teşekkürler! Tam aradığım şey, @Transactionalgerçekte ne olduğunun açıklanması
CybeX

6

Servis katmanına sahip olmak daha iyidir! Bu, dün karşılaştığım makalelerin birinde açıkça açıklandı! İşte kontrol edebileceğiniz bağlantı !


5

resim açıklamasını buraya girin

@TransactionalO iş mantığını içerdiğinden hizmet katmanında kullanılmalıdır. DAO katmanı genellikle yalnızca veritabanı CRUD işlemlerine sahiptir.

// the service class that we want to make transactional
@Transactional
public class DefaultFooService implements FooService {

    Foo getFoo(String fooName);

    Foo getFoo(String fooName, String barName);

    void insertFoo(Foo foo);

    void updateFoo(Foo foo);
}

Bahar doktoru: https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/transaction.html


5

Hizmet katmanı, @Transactionalburada mevcut olan iş mantığının çoğu gibi ek açıklamalar eklemek için en iyi yerdir , ayrıntı düzeyinde kullanım durumu davranışı içerir.

DAO'ya eklediğimizi ve hizmetten biri başarısız ve diğer başarı olan 2 DAO sınıfını çağırdığımızı varsayalım, bu durumda @Transactionalhizmette değilse bir DB yürütecek ve diğeri geri dönecektir.

Bu yüzden benim tavsiyem bu ek açıklamayı akıllıca kullanmak ve sadece Servis katmanında kullanmak.

Github Projesi- Java-Algos


ObjectOptimisticLockingFailureException gibi özel durumlar yalnızca işlem tamamlandıktan sonra gerçekleşir. Posta hizmeti gibi diğer işlemler için ayrı iş parçacıklarınız varsa, bu tasarım tamamen başarısız olur. Şu anda acı çekiyoruz. Sadece sol çözelti AOP olacaktır.
Nabin Kumar Khatiwada

4

Bu tür kullanımın gereken yer Öncelikle let yılların tanımlayan işlem ?

Bence doğru cevap - eylemler dizisinin bir atomik işlem olarak birlikte tamamlanacağından ya da eylemlerden biri başarısız olsa bile hiçbir değişiklik yapılmayacağından emin olmamız gerektiğinde.

İş mantığını hizmetlere sokmak iyi bilinen bir uygulamadır. Bu nedenle hizmet yöntemleri, tek bir mantıksal iş birimi olarak gerçekleştirilmesi gereken farklı eylemler içerebilir. Öyleyse - böyle bir yöntem İşlemsel olarak işaretlenmelidir . Tabii ki, her yöntem böyle bir sınırlama gerektirmez, bu nedenle tüm hizmeti işlem olarak işaretlemenize gerek yoktur .

Ve daha da fazlası - @Transactional'ın yöntem performansını düşürebileceğini dikkate almayı unutmayın . Resmin tamamını görmek için işlem yalıtım düzeylerini bilmeniz gerekir. Bunun gerekmediği yerlerde @Tacacactional kullanmaktan kaçınmanıza yardımcı olabileceğini bilmek .


3

@Tacactional'ı DAO ve Hizmet Katmanı arasında ayrı bir orta katmanda tutmak daha iyidir . Geri alma çok önemli olduğundan, tüm DB işlemlerinizi orta katmana yerleştirebilir ve Hizmet Katmanı'na iş mantığı yazabilirsiniz. Orta katman DAO katmanlarınızla etkileşime girer.

Bu, ObjectOptimisticLockingFailureException gibi birçok durumda size yardımcı olacaktır - Bu istisna yalnızca İşleminiz bittikten sonra gerçekleşir. Böylece, orta katmanda yakalayamazsınız, ancak şimdi hizmet katmanınızda yakalayabilirsiniz. Service katmanında @Tacacactional varsa bu mümkün olmaz. Denetleyiciyi yakalayabilmenize rağmen, Denetleyici mümkün olduğunca temiz olmalıdır.

Tüm kaydetme, silme ve güncelleme seçeneklerini tamamladıktan sonra ayrı bir iş parçacığında posta veya sms gönderiyorsanız, orta katmanda İşlem tamamlandıktan sonra bunu hizmette yapabilirsiniz. Yine, hizmet katmanında @ İşlemsel'den bahsederseniz, işleminiz başarısız olsa bile postalarınız gider.

Bu nedenle, orta @Transaction katmanına sahip olmak kodunuzu daha iyi ve kullanımı kolay hale getirir. Aksi takdirde, DAO katmanında kullanırsanız, tüm işlemleri geri alamayabilirsiniz. Hizmet katmanında kullanıyorsanız , belirli durumlarda AOP (En Boy Odaklı Programlama) kullanmanız gerekebilir .


2

İdeal olarak, Hizmet katmanı (Yönetici) iş mantığınızı temsil eder ve bu nedenle açıklama eklenmelidir. Hizmet katmanı @TransactionalDB işlemlerini gerçekleştirmek için farklı DAO'yu çağırabilir. Bir hizmet yönteminde N sayıda DAO işleminizin olduğu durumları varsayalım. 1. DAO işleminiz başarısız olduysa, diğerleri hala geçilebilir ve sonuçta tutarsız DB durumu elde edersiniz. Ek Açıklama Servisi katmanı sizi bu tür durumlardan kurtarabilir.



1

@Transactional@ControllerDAO katmanına ( @Repository) kontrol katmanı ( ) ve servis katmanı çağrısı kullanılarak çağrılan servis katmanında kullanılır, yani veri tabanı ile ilgili işlem.

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.