Eğer yerleştirmelidir @Transactional
içinde DAO
sı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ı?
Eğer yerleştirmelidir @Transactional
içinde DAO
sı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:
İş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.
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 @Transactional
ve 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.
@Transactional
Servis 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 ?
İş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
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
.
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,@Transaction
geleneğe göre. Etki alanı nesneleri üzerindeki işlem yayılımını, etki alanı nesneleri REQUIRED
hizmet ç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.
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.
Ben koyun @Transactional
üzerinde @Service
katmanın ve set rollbackFor
herhangi istisna ve readOnly
ayrıca işlem optimize etmek.
Varsayılan olarak @Transactional
yalnı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)
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.
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.
Ayrıca Spring, ek açıklamaların arabirimler üzerinde değil, yalnızca beton sınıflarında kullanılmasını önerir.
http://static.springsource.org/spring/docs/2.0.x/reference/transaction.html
Veritabanı düzeyinde İşlem için
çoğunlukla @Transactional
DAO'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)
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.
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(..);
}
}
Transactional
içindeJava
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.
@Transactional
Ek açıklamalar ayrılmaz tüm işlemlerin etrafına yerleştirilmelidir. Kullanılması @Transactional
baş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 Country
ve City
. İlişkisel Haritalama Country
ve City
model, bir Country
kiş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 @Transactional
olarak Hizmet, uç nokta ile bağlantıyı kapatmadan tek işlemde birden fazla çağrı yapabilir.
@Transactional
gerçekte ne olduğunun açıklanması
@Transactional
O 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
Hizmet katmanı, @Transactional
burada 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 @Transactional
hizmette 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.
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 .
@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 .
İdeal olarak, Hizmet katmanı (Yönetici) iş mantığınızı temsil eder ve bu nedenle açıklama eklenmelidir. Hizmet katmanı @Transactional
DB 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.
@Transactional
Metot düzeyinde hizmetler katmanında kullanmayı tercih ederim .