EntityManager.merge()
yeni nesneler ekleyebilir ve mevcut olanları güncelleyebilir.
Neden kullanmak istesin persist()
(ki bu sadece yeni nesneler yaratabilir)?
EntityManager.merge()
yeni nesneler ekleyebilir ve mevcut olanları güncelleyebilir.
Neden kullanmak istesin persist()
(ki bu sadece yeni nesneler yaratabilir)?
Yanıtlar:
Her iki şekilde de bir varlık PersistenceContext'e eklenir, fark, daha sonra varlıkla yaptığınız şeydir.
Persist, bir varlık örneğini alır, onu bağlama ekler ve bu örneği yönetilmesini sağlar (yani, varlığın gelecekteki güncellemeleri izlenir).
Birleştirme, durumun birleştirildiği yönetilen örneği döndürür. PersistenceContext içinde var olan bir şeyi döndürür veya varlığınızın yeni bir örneğini oluşturur. Her durumda, durumu sağlanan varlıktan kopyalar ve yönetilen kopyayı döndürür. Aktardığınız örnek yönetilmeyecek (birleştirme işlemini tekrar çağırmadıkça yaptığınız değişiklikler işlemin bir parçası olmayacaktır). Döndürülen örneği (yönetilen) kullanabilirsiniz.
Belki bir kod örneği yardımcı olacaktır.
MyEntity e = new MyEntity();
// scenario 1
// tran starts
em.persist(e);
e.setSomeField(someValue);
// tran ends, and the row for someField is updated in the database
// scenario 2
// tran starts
e = new MyEntity();
em.merge(e);
e.setSomeField(anotherValue);
// tran ends but the row for someField is not updated in the database
// (you made the changes *after* merging)
// scenario 3
// tran starts
e = new MyEntity();
MyEntity e2 = em.merge(e);
e2.setSomeField(anotherValue);
// tran ends and the row for someField is updated
// (the changes were made to e2, not e)
Senaryo 1 ve 3 kabaca eşdeğerdir, ancak Senaryo 2'yi kullanmak isteyebileceğiniz bazı durumlar vardır.
merge
bir nesnenin yönetilmeden önce tam kopyası bir performans isabetine sahiptir?
@GeneratedId
senaryo 2'de alabilir miyim?
Kalıcılık ve birleşme iki farklı amaç içindir (hiç alternatif değildirler).
(farklılık bilgilerini genişletmek için düzenlenmiştir)
inat:
birleştirmek:
sürekli () verimlilik:
persist () anlambilimi:
Misal:
{
AnyEntity newEntity;
AnyEntity nonAttachedEntity;
AnyEntity attachedEntity;
// Create a new entity and persist it
newEntity = new AnyEntity();
em.persist(newEntity);
// Save 1 to the database at next flush
newEntity.setValue(1);
// Create a new entity with the same Id than the persisted one.
AnyEntity nonAttachedEntity = new AnyEntity();
nonAttachedEntity.setId(newEntity.getId());
// Save 2 to the database at next flush instead of 1!!!
nonAttachedEntity.setValue(2);
attachedEntity = em.merge(nonAttachedEntity);
// This condition returns true
// merge has found the already attached object (newEntity) and returns it.
if(attachedEntity==newEntity) {
System.out.print("They are the same object!");
}
// Set 3 to value
attachedEntity.setValue(3);
// Really, now both are the same object. Prints 3
System.out.println(newEntity.getValue());
// Modify the un attached object has no effect to the entity manager
// nor to the other objects
nonAttachedEntity.setValue(42);
}
Bu şekilde varlık yöneticisindeki herhangi bir kayıt için yalnızca 1 ekli nesne bulunur.
kimliğine sahip bir varlık için merge () yöntemi şöyledir:
AnyEntity myMerge(AnyEntity entityToSave) {
AnyEntity attached = em.find(AnyEntity.class, entityToSave.getId());
if(attached==null) {
attached = new AnyEntity();
em.persist(attached);
}
BeanUtils.copyProperties(attached, entityToSave);
return attached;
}
Her ne kadar MySQL birleştirme () ile bağlanmışsa ON DUPLICATE KEY UPDATE seçeneğiyle INSERT çağrısı kullanılarak persist () kadar etkili olabilse de, JPA çok üst düzey bir programdır ve bunun her yerde böyle olacağını varsayamazsınız.
em.persist(x)
ile x = em.merge(x)
?
merge()
da atabilirEntityExistsException
RuntimeException
, ama Javadoc'da belirtilmemiş.
Atanmış oluşturucuyu kullanıyorsanız, sürekli yerine birleştirme kullanmak gereksiz bir SQL deyimine neden olabilir , bu nedenle performansı etkileyebilir.
Ayrıca, yönetilen varlıklar için birleştirme çağrısında yönetilen varlıklar otomatik hazırda tarafından yönetilir ve bunların devlet tarafından veritabanı kaydı ile senkronize edildiğinden ayrıca bir hatadır kirli kontrol mekanizması üzerine Sebat Bağlamını kızarma .
Tüm bunların nasıl çalıştığını anlamak için önce Hazırda Beklet'in geliştirici zihniyetini SQL deyimlerinden varlık durumu geçişlerine kaydırdığını bilmelisiniz .
Bir varlık Hazırda Bekletme tarafından aktif olarak yönetildikten sonra, tüm değişiklikler otomatik olarak veritabanına yayılır.
Hazırda bekletme modu, halihazırda bağlı olan varlıkları izler. Ancak bir işletmenin yönetilebilmesi için doğru varlık durumunda olması gerekir.
JPA durum geçişlerini daha iyi anlamak için aşağıdaki diyagramı görselleştirebilirsiniz:
Veya Hazırda Bekletme özel API'sini kullanıyorsanız:
Yukarıdaki şemalarda gösterildiği gibi, bir varlık aşağıdaki dört durumdan birinde olabilir:
Yeni (Geçici)
Bir Hazırda Bekletme Session
(akaPersistence Context
) ve herhangi bir veritabanı tablosu satırına eşlenmemiş Yeni (Geçici) durumunda olduğu kabul edilir.
Kalıcı olmak için ya EntityManager#persist
yöntemi açıkça çağırmamız ya da geçişli kalıcılık mekanizmasını kullanmamız gerekir.
Kalıcı (Yönetilen)
Kalıcı bir varlık, bir veritabanı tablosu satırıyla ilişkilendirildi ve şu anda çalışan Persistence Context tarafından yönetiliyor. Böyle bir kuruluşta yapılan herhangi bir değişiklik tespit edilecek ve veritabanına yayılacaktır (Oturum boşaltma süresi boyunca). Hazırda Bekletme ile artık INSERT / UPDATE / DELETE deyimlerini yürütmemiz gerekmiyor. Hazırda Beklet, işlemsel bir yazma arkası çalışma stili kullanır ve değişiklikler en son sorumlu anda, geçerli Session
yıkama zamanı sırasında senkronize edilir .
bağımsız
Çalışmakta olan Persistence Context kapatıldıktan sonra, önceden yönetilen tüm varlıklar ayrılır. Art arda yapılan değişiklikler artık izlenmeyecek ve otomatik veritabanı senkronizasyonu gerçekleşmeyecek.
Ayrılmış bir varlığı etkin bir Hazırda Bekletme Oturumuyla ilişkilendirmek için aşağıdaki seçeneklerden birini belirleyebilirsiniz:
yeniden takma
Hazırda Beklet (ancak JPA 2.1 değil), Oturum # güncelleme yöntemiyle yeniden eklemeyi destekler. Hazırda Bekletme Oturumu, belirli bir veritabanı satırı için yalnızca bir Varlık nesnesini ilişkilendirebilir. Bunun nedeni Kalıcılık Bağlamının bir bellek içi önbellek (birinci düzey önbellek) görevi görmesi ve belirli bir anahtarla (varlık türü ve veritabanı tanımlayıcısı) yalnızca bir değerin (varlık) ilişkilendirilmesidir. Varlık yalnızca geçerli Hazırda Bekletme Oturumuyla ilişkilendirilmiş başka bir JVM nesnesi (aynı veritabanı satırıyla eşleşen) yoksa yeniden bağlanabilir.
birleştirme
Birleştirme, ayrılmış varlık durumunu (kaynak) yönetilen varlık örneğine (hedef) kopyalayacaktır. Birleştirilen varlığın geçerli Oturumda eşdeğeri yoksa, biri veritabanından getirilir. Ayrılmış nesne örneği, birleştirme işleminden sonra bile ayrılmaya devam eder.
Kaldırılan
JPA yalnızca yönetilen varlıkların kaldırılmasına izin verilmesine rağmen, Hazırda Beklet ayrıca ayrılan varlıkları da silebilir (ancak yalnızca bir Oturum # silme yöntemi çağrısı yoluyla). Kaldırılan varlık yalnızca silinmek üzere zamanlanır ve gerçek veritabanı DELETE deyimi Oturum çalma süresi sırasında yürütülür.
Kullandığımda em.merge
, JPA'nın benim için ürettiği bir alan olmasa bile, SELECT
her biri için bir açıklama aldım INSERT
- birincil anahtar alanının kendimi ayarladığım bir UUID olduğunu fark ettim. Geçtim em.persist(myEntityObject)
ve sadece INSERT
ifadeler aldım .
merge()
. Ben karmaşık görünümü ile PostgreSQL veritabanı vardı : görünümü birkaç tablodan veri toplandı (tablolar aynı yapıya sahipti ama farklı isimler). Böylece JPA yapmaya çalıştı merge()
, ama aslında JPA ilk olarak yapıldı SELECT
(görünüm ayarları nedeniyle veritabanı farklı tablolardan aynı birincil anahtarla birkaç kayıt döndürebilir!), Ardından JPA (Hazırda Beklet bir uygulama idi) başarısız oldu: aynı anahtarla birkaç kayıt var ( org.hibernate.HibernateException: More than one row with the given identifier was found
). Benim durumumda persist()
bana yardımcı oldu.
JPA spesifikasyonu hakkında şunları söylüyor persist()
.
Eğer X, bir müstakil amacı,
EntityExistsException
çalışma çağrılır devam veya atılır edilebilirEntityExistsException
veya başka birPersistenceException
temizleme atılan edilebilir ya da zaman işlemek.
Bu nedenle persist()
, nesne ayrılmış bir nesne olmamalı olduğunda kullanmak uygun olacaktır . Kodun PersistenceException
hızlı bir şekilde başarısız olması için atmasını tercih edebilirsiniz .
Şartname belirsiz olsa da , bir nesne için persist()
ayarlayabilir @GeneratedValue
@Id
. merge()
ancak @Id
önceden oluşturulmuş bir nesneye sahip olmalıdır .
merge()
Ancak, @Id
önceden oluşturulmuş bir nesneye sahip olmalıdır . " EntityManager nesne kimliği alanı için bir değer bulamadığında, veri tabanına kalıcı olarak eklenir (eklenir).
Birleştirmeyle ilgili birleştirme kullanmanıza yardımcı olacak bazı daha fazla ayrıntı devam eder:
Orijinal varlık dışında yönetilen bir örneğin döndürülmesi, birleştirme işleminin kritik bir parçasıdır. Kalıcılık bağlamında aynı tanıtıcıya sahip bir varlık örneği zaten varsa, sağlayıcı durumunun üzerine birleştirilen varlığın durumunun üzerine yazacaktır, ancak var olan yönetilen sürümün istemciye döndürülmesi gerekir. Kullanılmış. Sağlayıcı, Çalışan örneğini kalıcılık bağlamında güncellemediyse, söz konusu örneğe yapılan tüm başvurular birleştirilen yeni durumla tutarsız hale gelir.
Merge () yeni bir varlıkta çağrıldığında, sürekli () işlemine benzer şekilde davranır. Varlığı kalıcılık bağlamına ekler, ancak orijinal varlık örneğini eklemek yerine yeni bir kopya oluşturur ve bunun yerine bu örneği yönetir. Merge () işlemi tarafından oluşturulan kopya, sürekli () yöntemi çağrılmış gibi devam eder.
İlişkilerin varlığında, merge () işlemi yönetilen varlığı, bağımsız varlık tarafından başvurulan varlıkların yönetilen sürümlerini gösterecek şekilde güncellemeye çalışır. Varlığın kalıcı kimliği olmayan bir nesne ile ilişkisi varsa, birleştirme işleminin sonucu tanımlanmamıştır. Bazı sağlayıcılar yönetilen kopyanın kalıcı olmayan nesneyi işaret etmesine izin verirken, diğerleri hemen bir istisna atabilir. Bir istisna oluşmasını önlemek için bu durumlarda merge () işlemi isteğe bağlı olarak basamaklandırılabilir. Birleştirme () işleminin bu bölümün ilerleyen bölümlerinde anlatılacağız. Birleştirilen varlık kaldırılan bir varlığa işaret ediyorsa, IllegalArgumentException istisnası atılır.
Tembel yükleme ilişkileri, birleştirme işleminde özel bir durumdur. Tembel yükleme ilişkisi, varlık ayrılmadan önce tetiklenmediyse, varlık birleştirildiğinde bu ilişki yok sayılır. İlişki yönetilirken tetiklendiyse ve daha sonra varlık ayrılırken null değerine ayarlanırsa, kuruluşun yönetilen sürümü de birleştirme sırasında ilişkinin silinmesini sağlar. "
Yukarıdaki bilgilerin tamamı Mike Keith ve Merrick Schnicariol tarafından "Pro JPA 2 Java ™ Kalıcılık API'sında Mastering" den alınmıştır. Bölüm 6. Bölüm ayırma ve birleştirme. Bu kitap aslında yazarlar tarafından JPA'ya ayrılmış ikinci bir kitaptır. Bu yeni kitap eskisinden çok yeni bilgiye sahiptir. JPA ile ciddi bir şekilde ilgilenecek olanlar için bu kitabı gerçekten tavsiye ettim. İlk cevabımı anonim olarak gönderdiğim için üzgünüm.
merge
Ve arasında daha fazla fark varpersist
(Yine o zaten burada yayınlanan numaralandırma):
D1. merge
iletilen varlığı yönetmez, yönetilen başka bir örneği döndürür. persist
diğer tarafta, geçen varlığı yönetir:
//MERGE: passedEntity remains unmanaged, but newEntity will be managed
Entity newEntity = em.merge(passedEntity);
//PERSIST: passedEntity will be managed after this
em.persist(passedEntity);
D2. Bir varlığı kaldırır ve sonra varlığı devam ettirmeye karar verirseniz, bunu yalnızca persist () ile yapabilirsiniz, çünkü merge
bir IllegalArgumentException
.
D3. Kimliklerinize el ile bakmaya karar verdiyseniz (örn. UUID'leri kullanarak), bir merge
işlem SELECT
bu kimliğe sahip varlıkları aramak için sonraki sorguları tetiklerken , persist
bu sorgulara gerek duymayabilir.
D4. Kodunuzu çağıran koda güvenmediğiniz durumlar vardır ve hiçbir verinin güncellenmediğinden emin olunur, ancak eklenir persist
.
Oturumda olan tembel yüklü bir koleksiyona erişmeye çalıştığım için, varlığım üzerinde özel durumları istisna alıyordum.
Ne yapacağım ayrı bir istek oldu, oturumdan varlık almak ve sonra sorunlu jsp sayfamda bir koleksiyon erişmeye çalışın.
Bunu hafifletmek için, denetleyicimdeki aynı varlığı güncelledim ve jsp'ye geçtim, ancak oturumda yeniden kaydettiğimde, yine de erişilebilir olacağını SessionScope
ve birLazyLoadingException
bir örnek 2 modifikasyonu :
Aşağıdakiler benim için çalıştı:
// scenario 2 MY WAY
// tran starts
e = new MyEntity();
e = em.merge(e); // re-assign to the same entity "e"
//access e from jsp and it will work dandy!!
Bu açıklamayı Hazırda Bekletme belgelerinden aydınlatıcı buldum, çünkü bir kullanım durumu içeriyorlar:
Merge () kullanımı ve semantiği yeni kullanıcılar için kafa karıştırıcı görünmektedir. İlk olarak, başka bir yeni varlık yöneticisinde bir varlık yöneticisine yüklenen nesne durumunu kullanmaya çalışmadığınız sürece, merge () kullanmanız gerekmez . Bazı uygulamaların hiçbiri bu yöntemi kullanmayacaktır.
Genellikle merge () aşağıdaki senaryoda kullanılır:
- Uygulama, ilk varlık yöneticisine bir nesne yükler
- nesne sunum katmanına aktarılır
- nesnede bazı değişiklikler yapılır
- nesne iş mantığı katmanına geri aktarılır
- uygulama, ikinci bir varlık yöneticisinde merge () yöntemini çağırarak bu değişikliklere devam eder
İşte merge () 'nin tam semantiği:
- şu anda kalıcılık bağlamıyla ilişkilendirilmiş aynı tanımlayıcıya sahip bir yönetilen örnek varsa, verilen nesnenin durumunu yönetilen örneğe kopyalayın
- şu anda kalıcılık bağlamıyla ilişkilendirilmiş yönetilen bir örnek yoksa, veritabanından yüklemeyi deneyin veya yeni bir yönetilen örnek oluşturun
- yönetilen örnek döndürülür
- verilen örnek kalıcılık bağlamıyla ilişkilendirilmez, bağımsız kalır ve genellikle atılır
Gönderen: http://docs.jboss.org/hibernate/entitymanager/3.6/reference/en/html/objectstate.html
Cevapları incelerken `` Çağlayan '' ve kimlik oluşturma ile ilgili bazı ayrıntılar eksik. Soruya bakın
Ayrıca, Cascade
birleştirmek ve devam etmek için ayrı ek açıklamalara sahip olabileceğinizi belirtmek gerekir : Cascade.MERGE
veCascade.PERSIST
kullanılan yönteme göre işlenecek.
Spec senin arkadaşın;)
JPA, Java platformu üzerine kurulmuş kurumsal uygulamaların alanında tartışmasız büyük bir basitleştirmedir. J2EE'deki eski varlık fasulyelerinin incelikleriyle başa çıkmak zorunda olan bir geliştirici olarak, Java EE spesifikasyonları arasında JPA'nın dahil edilmesini büyük bir sıçrama olarak görüyorum. Ancak, JPA ayrıntılarını daha derinlemesine incelerken, o kadar kolay olmayan şeyler buluyorum. Bu makalede, EntityManager'ın üst üste binme davranışı sadece bir acemi için karışıklığa neden olabilecek birleştirme ve kalıcı yöntemlerin karşılaştırılması ile ilgileniyorum. Dahası, her iki yöntemi de daha genel bir yöntemin birleştirdiği özel durumlar olarak gören bir genelleme öneriyorum.
Kalıcı varlıklar
Birleştirme yönteminin aksine, sürekli yöntem oldukça basit ve sezgiseldir. Kalıcı yöntem kullanımının en yaygın senaryosu aşağıdaki gibi özetlenebilir:
"Varlık sınıfının yeni oluşturulan bir örneği persist yöntemine geçirilir. Bu yöntem döndükten sonra, varlık yönetilir ve veritabanına eklenmesi planlanır. Bu işlem, işlem başlamadan önce veya önce veya temizleme yöntemi çağrıldığında gerçekleşebilir. İşletme, PERSIST basamaklı stratejisi ile işaretlenmiş bir ilişki yoluyla başka bir kuruluşa başvuruyorsa, bu yordam da uygulanır. "
Şartname daha fazla ayrıntıya girer, ancak bu ayrıntıların sadece az çok egzotik durumları kapsadığı için bunları hatırlamak önemli değildir.
Varlıkları birleştirme
Kalıcılığa kıyasla, birleştirme davranışının açıklaması o kadar basit değildir. Kalıcı olması durumunda olduğu gibi ana bir senaryo yoktur ve bir programcı doğru bir kod yazmak için tüm senaryoları hatırlamak zorundadır. Bana öyle geliyor ki, JPA tasarımcıları birincil kaygısı bağımsız varlıkları ele almak olan bir yönteme sahip olmak istiyordu (öncelikle yeni oluşturulan varlıklarla ilgilenen kalıcı yöntemin aksine). Birleştirme yönteminin ana görevi, devleti bir devamlılık bağlamında yönetilen muadiline yönetilmeyen varlık (argüman olarak geçti). Ancak bu görev, genel yöntemin davranışının anlaşılabilirliğini daha da kötüleştiren birkaç senaryoya ayrılmaktadır.
JPA belirtiminden paragrafları tekrarlamak yerine, birleştirme yönteminin davranışını şematik olarak gösteren bir akış diyagramı hazırladım:
Peki, ne zaman kalıcı ve ne zaman birleştirme kullanmalıyım?
inat
birleştirmek
Senaryo X:
Tablo: Spitter (Bir), Tablo: Spittles (Çok) (Spittles, FK: spitter_id ile ilişkinin sahibidir)
Bu senaryo tasarruf sağlar: Aynı Spitter'a aitmiş gibi Spitter ve her iki Spittles.
Spitter spitter=new Spitter();
Spittle spittle3=new Spittle();
spitter.setUsername("George");
spitter.setPassword("test1234");
spittle3.setSpittle("I love java 2");
spittle3.setSpitter(spitter);
dao.addSpittle(spittle3); // <--persist
Spittle spittle=new Spittle();
spittle.setSpittle("I love java");
spittle.setSpitter(spitter);
dao.saveSpittle(spittle); //<-- merge!!
Senaryo Y:
Bu, Spitter'ı kurtaracak, 2 Spittles'i kurtaracak, ancak aynı Spitter'a referans vermeyecekler!
Spitter spitter=new Spitter();
Spittle spittle3=new Spittle();
spitter.setUsername("George");
spitter.setPassword("test1234");
spittle3.setSpittle("I love java 2");
spittle3.setSpitter(spitter);
dao.save(spittle3); // <--merge!!
Spittle spittle=new Spittle();
spittle.setSpittle("I love java");
spittle.setSpitter(spitter);
dao.saveSpittle(spittle); //<-- merge!!
Başka bir gözlem:
merge()
yalnızca otomatik olarak oluşturulan bir kimliği (test edilen IDENTITY
ve üzerinde SEQUENCE
), tablonuzda bu tür bir kimliğe sahip bir kayıt zaten varsa dikkate alır. Bu durumda merge()
kaydı güncellemeye çalışacaktır. Bununla birlikte, bir kimlik yoksa veya mevcut kayıtlarla eşleşmiyorsa, merge()
bunu tamamen yok sayar ve bir db'den yeni bir kayıt tahsis etmesini ister. Bu bazen çok fazla hata kaynağıdır. merge()
Yeni bir kayıt için kimliği zorlamak için kullanmayın .
persist()
Öte yandan, bir kimlik bile geçirmenize asla izin vermeyecektir. Hemen başarısız olur. Benim durumumda:
Nedeni: org.hibernate.PersistentObjectException: bağımsız varlık devam etmek için geçti
hibernate-jpa javadoc'un bir ipucu var:
Atar : javax.persistence.EntityExistsException - varlık zaten varsa. (Varlık zaten varsa, sürekli işlem çağrıldığında EntityExistsException atılabilir veya EntityExistsException veya başka bir PersistenceException, çalma veya yürütme sırasında fırlatılabilir.)
persist()
bir kimliği olduğundan şikayet etmeyecektir, sadece aynı kimliğe sahip bir şey veritabanında olduğunda şikayet eder.
Buraya ne zaman kalıcı ve ne zaman birleştirme kullanılacağı konusunda tavsiye için gelmiş olabilirsiniz. . Ben duruma bağlı olduğunu düşünüyorum: yeni bir kayıt oluşturmak için ne kadar olası ve kalıcı veri almak için ne kadar zor.
Doğal bir anahtar / tanımlayıcı kullanabileceğinizi varsayalım.
Verilerin kalıcı olması gerekiyor, ancak arada bir kayıt var ve güncelleme gerekiyor. Bu durumda, bir süreklilik deneyebilirsiniz ve bir EntityExistsException özel durumu atarsa, onu arar ve verileri birleştirirsiniz:
{entityManager.persist (entity)} 'yi deneyin
catch (EntityExistsException istisnası) {/ * al ve birleştir * /}
Kalıcı verilerin güncellenmesi gerekir, ancak arada bir veriler için henüz kayıt yoktur. Bu durumda ararsınız ve varlık eksikse kalıcı olur:
entity = entityManager.find (anahtar);
if (entity == null) {entityManager.persist (entity); }
başka {/ * birleştirme * /}
Doğal anahtarınız / tanımlayıcınız yoksa, varlığın var olup olmadığını veya nasıl aranacağını bulmak için daha zor zamanınız olacaktır.
Birleşmeler iki şekilde de ele alınabilir:
persist (varlık) tamamen yeni varlıklarla kullanılmalıdır, bunları DB'ye eklemek için (varlık DB'de zaten varsa EntityExistsException atımı olacaktır).
Eğer varlık ayrılır ve değiştirilirse, varlığı kalıcılık bağlamına sokmak için birleştirme (varlık) kullanılmalıdır.
Muhtemelen kalıcı INSERT sql deyimi üretiyor ve UPDATE sql deyimi birleştiriyor (ama emin değilim).