@Transactional anotasyonu hangi durumlarda çalışmaz? Self-invocation, rollback kuralları ve propagation tuzaklarını açıklayın.
Cevap
Spring @Transactional'ı AOP proxy ile uygular: bean'i çağırdığınızda aslında proxy'yi çağırırsınız; proxy transaction'ı açar, gerçek metodu çağırır, sonra commit/rollback yapar. Tuzakların çoğu bu mekanizmadan gelir.
1. Self-invocation
@Service
public class UserService {
public void register(User u) {
save(u); // this.save() -> proxy atlanır, transaction YOK
}
@Transactional
public void save(User u) { ... }
}Aynı sınıf içinden çağrı proxy'den geçmez. Çözüm: @Transactional'ı dış metoda koymak, metodu ayrı bir bean'e taşımak veya TransactionTemplate kullanmak.
2. Görünürlük
Proxy tabanlı yaklaşımda anotasyon public olmayan metotlarda yıllarca yok sayıldı. Spring 6.0+ class-based proxy'lerde protected ve package-private metotları da destekler, ama private metotlar hiçbir zaman çalışmaz.
3. Rollback kuralları
Varsayılan olarak yalnızca unchecked exception (RuntimeException, Error) rollback tetikler. Checked exception (IOException vb.) fırlatılırsa transaction commit edilir.
@Transactional(rollbackFor = Exception.class)Exception'ı metot içinde yakalayıp yutarsanız da rollback olmaz.
4. Propagation
REQUIRED(varsayılan): mevcut transaction'a katılır. İç metot exception fırlatıp dışarıda yakalansa bile transaction "rollback-only" işaretlenir ve dış commitUnexpectedRollbackExceptionverir.REQUIRES_NEW: mevcut transaction'ı askıya alıp yenisini açar (ör. hata olsa bile audit log yazmak). Ayrı bir DB bağlantısı kullanır; aşırı kullanımı connection pool'u tüketebilir.
5. Diğer tuzaklar
@Transactionalmetot içinde başlatılan@Asyncveya yeni thread transaction'ı paylaşmaz (transactionThreadLocal'a bağlıdır).- Transaction içinde uzak HTTP çağrısı yapmak bağlantıyı uzun süre tutar; dış çağrıları transaction dışına alın.
readOnly = trueokuma metotlarında Hibernate dirty checking'i atlayarak performans kazandırır.
İlgili Java & Spring soruları
- Java 21 virtual thread'ler nedir? Platform thread'lerden farkı nedir ve hangi durumlarda dikkatli olmak gerekir?
- ExecutorService ve CompletableFuture ile asenkron iş nasıl yapılır? Thread pool boyutunu nasıl belirlersiniz?
- JPA/Hibernate'te lazy ve eager loading farkı nedir? LazyInitializationException neden oluşur ve nasıl çözülür?
- Spring bean scope'ları nelerdir? Singleton bir bean'e prototype bean inject edilirse ne olur?
- Spring'de Dependency Injection nedir? Constructor injection neden field injection'a tercih edilir?
- Java'da Garbage Collection nasıl çalışır? G1 ve ZGC arasındaki farklar nelerdir, hangisini ne zaman seçersiniz?
Bu konuda başka bir soru biliyor musun?
Mülakatta karşılaştığın soruları ekle, onaylandıktan sonra yayına alınsın.