JPA / Hazırda Bekletmede doğru flush () kullanımı


111

Flush () yöntemi hakkında bilgi topluyordum, ancak onu ne zaman ve nasıl doğru şekilde kullanacağımı tam olarak bilmiyorum. Okuduğum kadarıyla, benim anladığım kadarıyla, kalıcılık bağlamının içeriğinin veri tabanı ile senkronize edileceği, yani bekleyen beyanlar yayınlayarak veya varlık verilerini tazeleyecek.

Şimdi iki varlıklı Ave B(bire bir ilişki içinde, ancak JPA tarafından zorlanmayan veya modellenen) aşağıdaki senaryoyu aldım . Amanuel olarak ayarlanan ve ayrıca otomatik oluşturulmuş bir KİMLİK alanına sahip bir bileşik PK'ye sahiptir recordId. Bu recordId, Byabancı anahtar olarak varlığa yazılmalıdır A. Tasarruf ediyorum Ave Btek bir işlemde. Sorun otomatik oluşturulan değer olduğunu A.recordIdben açık bir çağrı yapmak sürece, işlem içinde kullanılamaz em.flush()çağırdıktan sonra em.persist()üzerine A. (Otomatik oluşturulmuş bir IDENTITY PK'm varsa, değer doğrudan varlıkta güncellenir, ancak burada durum böyle değildir.)

Can em.flush()bir hareket içinde onu kullanırken herhangi bir zararı?

Yanıtlar:


150

Muhtemelen kesin ayrıntıları em.flush()uygulamaya bağlıdır. Genel olarak yine de, Hibernate gibi JPA sağlayıcıları, genellikle işlemi gerçekten gerçekleştirene kadar veritabanına göndermeleri gereken SQL talimatlarını önbelleğe alabilir. Örneğin, aradığınızda em.persist(), Hibernate bir veritabanı INSERT yapması gerektiğini hatırlar, ancak siz işlemi gerçekleştirene kadar talimatı fiilen yürütmez. Afaik, bu esas olarak performans nedenleriyle yapılır.

Bazı durumlarda yine de SQL komutlarının hemen yürütülmesini istersiniz; genellikle otomatik olarak oluşturulmuş bir anahtar veya bir veritabanı tetikleyicisi gibi bazı yan etkilerin sonucuna ihtiyaç duyduğunuzda.

Yapılması em.flush()gereken, dahili SQL talimatları önbelleğini boşaltmak ve bunu derhal veritabanında yürütmektir.

Sonuç olarak: herhangi bir zarar verilmez, SQL talimatlarını veritabanına göndermek için en iyi zamanlamayla ilgili olarak JPA sağlayıcı kararlarını geçersiz kıldığınız için yalnızca (küçük) bir performans düşüşüne sahip olabilirsiniz.


1
O ne dedi. em.flush () davranışı, arabelleğe alınan tüm verilerin uygun hedefe gönderildiği java.io.Flushable.flush () yankılar.
Erik

4
flush () veri veritabanına gönderirse? bundan sonra bir istisna olursa ne olur? Varlık yöneticisi her şeyi geri alacak mı? ilk yıkamada yazılan veriler bile?
Jaime Hablutzel

101
flush (), veritabanına INSERT, UPDATE vb. gibi SQL komutları gönderir. COMMIT göndermez, bu nedenle flush () sonrasında bir istisnanız varsa, yine de tam bir geri dönüşe sahip olabilirsiniz.
Flavio

17
DB'yi geri alabilirsiniz, ancak nesnelerdeki herhangi bir değişikliği geri almayacaktır, örneğin, otomatik olarak artırılan 'sürüm', otomatik oluşturulan kimlik, vb. Ayrıca, bir geri dönüşten sonra varlık yöneticisi kapatılacaktır. Sadece nesneyi başka bir oturumla 'birleştirmeyi' denerseniz, özellikle otomatik olarak artırılan 'sürümün' bir OptimisticLockException'a neden olabileceğine dikkat edin.
Peter Davis

11
Yan etkileri tetiklemenin yanı sıra, flush () kullanmanın bir başka nedeni de veritabanındaki bir işlemin etkilerini JPQL / HQL (örneğin bir testte) kullanarak okuyabilmektir. JPA, bu sorguları yürütürken önbelleğe alınmış verileri kullanamaz, bu nedenle yalnızca veritabanında bulunan şeyler okunacaktır.
sleske

2

Aslında, em.flush()önbelleğe alınmış SQL komutlarını göndermekten daha fazlasını yapın. Kalıcılık bağlamını temeldeki veritabanıyla senkronize etmeye çalışır. Önbelleğiniz senkronize edilecek koleksiyonlar içeriyorsa, süreçlerinizde çok fazla zaman tüketimine neden olabilir.

Kullanmaya dikkat edin.


2

Em.flush () bir işlem içinde kullanıldığında herhangi bir zarar verebilir mi?

Evet, veritabanında gerekenden daha uzun süre kilitler tutabilir.

Genel olarak, JPA kullanırken, işlem yönetimini konteynere devredersiniz (diğer adıyla CMT - iş yöntemlerinde @ İşlem ek açıklamasını kullanarak), bu, yönteme girerken bir işlemin otomatik olarak başlatıldığı ve sonunda taahhüt edildiği / geri alındığı anlamına gelir. EntityManager'ın veritabanı senkronizasyonunu yönetmesine izin verirseniz, sql ifadelerinin yürütülmesi yalnızca commitden hemen önce tetiklenecek ve bu da veritabanında kısa ömürlü kilitlere yol açacaktır. Aksi takdirde, el ile yıkanan yazma işlemleriniz, kalan yöntem yürütme süresine göre uzun sürebilecek olan manuel yıkama ve otomatik tamamlama arasındaki kilitleri tutabilir.

Bazı işlemlerin otomatik olarak bir yıkamayı tetiklediğini not eder: aynı oturuma karşı yerel bir sorgu yürütme (SQL sorgusu tarafından erişilebilmesi için EM durumu yıkanmalıdır), yerel olarak oluşturulan kimliği kullanarak varlıklar ekleme (veritabanı tarafından oluşturulur, bu nedenle insert deyimi tetiklendiğinden EM, oluşturulan kimliği alabilir ve ilişkileri uygun şekilde yönetebilir)

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.