Hibernate'de persist () vs save () 'nin avantajı nedir?


Yanıtlar:


154

Gönderen Bu forum yazı

persist()iyi tanımlanmış. Geçici bir örneği kalıcı hale getirir. Ancak, tanımlayıcı değerin kalıcı örneğe derhal atanacağını garanti etmez, atama yıkama sırasında gerçekleşebilir. Spesifikasyon bununla ilgili sorun olduğunu söylemiyor persist().

persist()ayrıca işlem sınırları dışında çağrılırsa INSERT deyimi yürütmeyeceğini de garanti eder. Bu, genişletilmiş Oturum / kalıcılık bağlamına sahip uzun süren konuşmalarda kullanışlıdır.

Gibi bir yöntem persist()gereklidir.

save()aynısını garanti etmez, bir tanımlayıcı döndürür ve tanımlayıcıyı almak için bir INSERT yürütülmesi gerekiyorsa (örn. "dizi" değil "kimlik" üreteci), bu INSERT, içinde veya dışında olmanız fark etmeksizin hemen gerçekleşir bir işlem. Genişletilmiş Oturum / kalıcılık bağlamıyla uzun süren bir konuşmada bu iyi değildir.


44
aynı yazıdan daha fazlasını eklemek için, mızmızlanmak için: "Ne yazık ki, 5 yıl sonra, bu konu hala bu konu hakkında tek net bilgi kaynağı olmaya devam ediyor. Christian'ın son gönderisi neden Oturumda değil? Javadoc sadece bir Hibernate dokümantasyon gizemi. "
kommradHomer

persist () yönteminin varlığı bağımsız durumda ve save () öğesini ekli durumda yapacak mı?
rekinyz

2
Son zamanlarda bir-çok yönlü bir eşleme hem kaydetme ve kalıcı olarak kullanılır. Kaydetmek çocuğa çağlayan olmadığını öğrendim, yani, sadece Ebeveyn kaydedilir / tabloya eklenir. Bununla birlikte, ısrar hem Ebeveyn hem de Çocuk'ı bir çağrıda kaydetme görevini yerine getirdi. Oluşturulan bir kimlik değil bir bileşik kimliği kullanıyorum.
arn-arn

68

Yerel makinemde birkaç kez çalıştırmayı da içeren save () vs persist () üzerinde iyi araştırmalar yaptım. Önceki tüm açıklamalar kafa karıştırıcıdır ve doğru değildir. Kapsamlı bir araştırmadan sonra aşağıdaki save () ve persist (() yöntemlerini karşılaştırdım.

Save()

  1. Kaydettikten sonra oluşturulan kimliği döndürür. Onun Serializabledönüş türü.
  2. db'deki değişiklikleri işlemin dışında saklayın.
  3. Oluşturulan kimliği devam etmekte olduğunuz varlığa atar
  4. Ayrılmış bir nesne için Session.save (), tabloda yeni bir satır oluşturur.

Persist()

  1. Kaydettikten sonra oluşturulan kimliği döndürmez. Boş dönüş türü.
  2. İşlem dışında db'deki değişiklikleri kaydetmez.
  3. Devam etmekte generated idolduğunuz varlığa atar
  4. session.persist()çünkü müstakil bir nesne PersistentObjectExceptionizin verilmediği gibi fırlar.

Tüm bunlar denenir / test edilir Hibernate v4.0.1.


Save () ve Persist () için 3. Noktadan bahsedilir ancak aslında aynı değildir. Persist () yöntemi de işlemin dışındaki db'ye yapılan değişiklikleri kaydeder.
Ravi.Kumar

2
idam

Yani # 1 ve # 5 ikisi arasındaki gerçek fark nedir? Geri gönderilen bir kimliğe veya yeni bir satır oluşturmaya ihtiyacınız varsa Save()?
user2490003

İşlem dışında 3 Kaydet nasıl mümkündür
vikas singh

24

Ben arasındaki farkı kaydetmek için test bazı alay yaptım save()ve persist().

Her iki yöntem gibi sesler Geçici Varlık ile uğraşırken aynı şekilde davranır, ancak Müstakil Varlık ile uğraşırken farklılık gösterir.

Aşağıdaki örnek için, EmployeeVehicle'ı vehicleIdoluşturulan bir değer olan PK ile bir Varlık olarak alın vevehicleName özelliklerinden biri olarak .

Örnek 1: Geçici Nesne ile İlişkiler

Session session = factory.openSession();
session.beginTransaction();
EmployeeVehicle entity = new EmployeeVehicle();
entity.setVehicleName("Honda");
session.save(entity);
// session.persist(entity);
session.getTransaction().commit();
session.close();

Sonuç:

select nextval ('hibernate_sequence') // This is for vehicle Id generated : 36
insert into Employee_Vehicle ( Vehicle_Name, Vehicle_Id) values ( Honda, 36)

Zaten var olan bir nesneyi alıp kaydettiğinizde sonucun aynı olduğunu unutmayın

EmployeeVehicle entity =  (EmployeeVehicle)session.get(EmployeeVehicle.class, 36);
entity.setVehicleName("Toyota");
session.save(entity);    -------> **instead of session.update(entity);**
// session.persist(entity);

Kullanarak aynı işlemi tekrarlayın. persist(entity) yeni Id ile aynı sonucu verecektir (37, honda deyin);

Örnek 2: Müstakil Nesne ile İlişkiler

// Session 1 
// Get the previously saved Vehicle Entity 
Session session = factory.openSession();
session.beginTransaction();
EmployeeVehicle entity = (EmployeeVehicle)session.get(EmployeeVehicle.class, 36);
session.close();

// Session 2
// Here in Session 2 , vehicle entity obtained in previous session is a detached object and now we will try to save / persist it 
// (i) Using Save() to persist a detached object 
Session session2 = factory.openSession();
session2.beginTransaction();
entity.setVehicleName("Toyota");
session2.save(entity);
session2.getTransaction().commit();
session2.close();

Sonuç: Önceki oturumda elde edilen kimliğe sahip araç: 36 "Toyota" adıyla güncelleniyor olabilir. Ancak olan şey, yeni bir varlığın DB için oluşturulan ve "Toyota" olarak adlandırılan yeni kimliğe sahip olması

select nextval ('hibernate_sequence')
insert into Employee_Vehicle ( Vehicle_Name, Vehicle_Id) values ( Toyota, 39)

Ayrılmış varlığı devam ettirmek için persist özelliğini kullanma

// (ii) Using Persist()  to persist a detached
// Session 1 
Session session = factory.openSession();
session.beginTransaction();
EmployeeVehicle entity = (EmployeeVehicle)session.get(EmployeeVehicle.class, 36);
session.close();

// Session 2
// Here in Session 2 , vehicle entity obtained in previous session is a detached object and now we will try to save / persist it 
// (i) Using Save() to persist a detached
Session session2 = factory.openSession();
session2.beginTransaction();
entity.setVehicleName("Toyota");
session2.persist(entity);
session2.getTransaction().commit();
session2.close();

Sonuç:

Exception being thrown : detached entity passed to persist

Bu nedenle, Transient nesnesiyle uğraşırken save'in dikkatli bir şekilde kullanılması gerektiğinden Save () yerine Persist () kullanmak her zaman daha iyidir.

Önemli Not: Yukarıdaki örnekte, araç varlığının pk değeri üretilen bir değerdir, bu nedenle ayrılmış bir varlığı devam ettirmek için save () kullanılırken hazırda bekletme modu kalıcı olması için yeni bir kimlik oluşturur. Ancak bu pk, oluşturulan bir değer değilse, anahtarın ihlal edildiğini belirten bir istisnaya neden olur.


13

Bu sorunun Hazırda Bekletme durumundaki farklı kalıcılık yöntemleri hakkında bazı iyi yanıtları vardır. Sorunuzu doğrudan yanıtlamak için save () ile insert deyimi, işlem durumuna bakılmaksızın hemen yürütülür. Aşağıdaki gibi bir şey yapabilmeniz için eklenen anahtarı döndürür:

long newKey = session.save(myObj);

Bu nedenle, kalıcı örneğe hemen atanan bir tanımlayıcıya ihtiyacınız varsa save () öğesini kullanın.

Persist () ile, insert deyimi mutlaka hemen değil, bir işlemde yürütülür. Çoğu durumda bu tercih edilir.

Eklemenin işlem sırasında sıralı olması için ve insert anahtarının döndürülmesine ihtiyacınız yoksa persist () kullanın.


6

Kalıcı ve tasarruf yöntemlerinin avantajlarını anlamanıza yardımcı olabilecek farklılıklar şunlardır:

  • Kaydetme ve kalıcılık arasındaki ilk fark dönüş türleridir. Persist yönteminin dönüş türü geçersiz olurken, save
    yönteminin dönüş türü Serializable nesnesidir.
  • Persist () yöntemi, tanımlayıcı değerin derhal kalıcı duruma atanacağını garanti etmez, atama yıkama zamanında gerçekleşebilir.

  • Persist () yöntemi, işlem sınırları dışında çağrılırsa bir ekleme sorgusu yürütmez. Save () yöntemi, bir işlemin içinde veya dışında olması fark etmeksizin, tanımlayıcıyı almak için hemen bir ekleme sorgusu yürütülmesi için bir tanımlayıcı döndürür.

  • Kalıcı yöntem, işlem sınırları dışında çağrılır, genişletilmiş Oturum bağlamıyla uzun süren konuşmalarda kullanışlıdır. Öte yandan, genişletilmiş Oturum bağlamıyla uzun süren bir konuşmada kaydetme yöntemi iyi değildir.

  • Hazırda Bekletme'de kaydetme ve kalıcı yöntem arasındaki beşinci fark: Kalıcılık, yalnızca Hazırda Bekletme tarafından desteklenirken JPA tarafından desteklenir.

Hazırda Bekletme modunda kaydet ve sürdürebilirlik yöntemi arasındaki farktan tam çalışma örneğini görebilirsiniz


Önce "persisted () yöntemi, işlem sınırlarının dışında çağrılırsa bir ekleme sorgusu yürütmez" diyorsunuz. Sonra "Kalıcı yöntem işlem sınırları dışında çağrılır, bu genişletilmiş Oturum bağlamı ile uzun süren konuşmalarda yararlıdır." Çelişkili değiller mi? Anlamıyorum.
Kumar Manish

@KumarManish Kalıcı yöntem durumunda, ekleme sorgusu yıkama zamanında gerçekleşir. Uzun süren konuşmalarda en iyi uygulama bu
David Pham

5

save () - Yöntem adından da anlaşılacağı gibi, hazırda bekletme save () öğesi varlığı veritabanına kaydetmek için kullanılabilir. Bu yöntemi bir işlemin dışında çağırabiliriz. Bunu işlem yapmadan kullanırsak ve varlıklar arasında basamaklandırırsak, oturumu temizlemedikçe yalnızca birincil varlık kaydedilir.

persist () - Hazırda bekletme sürekliliği kaydetme işlemiyle benzerdir ve varlık nesnesini kalıcı bağlama ekler, böylece diğer değişiklikler izlenir. İşlem tamamlanmadan veya oturum temizlenmeden önce nesne özellikleri değiştirilirse, veritabanına da kaydedilir. Ayrıca, persist () yöntemini yalnızca bir işlemin sınırları içinde kullanabiliriz, bu nedenle güvenlidir ve basamaklı nesnelerle ilgilenir. Son olarak, persist hiçbir şey döndürmez, bu nedenle oluşturulan tanımlayıcı değerini elde etmek için kalıcı nesneyi kullanmamız gerekir.


5

Fark şu:

  1. kayıt etmek:

    1. nesne veritabanına kaydedildiğinde kimliği / tanımlayıcıyı döndürür.
    2. nesne ayrıldıktan sonra yeni bir oturum açarak aynısını yapmaya çalışıldığında da kaydedilecektir.
  2. Persist:

    1. nesne veritabanına kaydedildiğinde geçersiz sayı döndürür.
    2. yeni nesneyle ayrılmış nesneyi kaydetmeye çalışıldığında PersistentObjectException özel durumunu atar.

Snippet ile bir örnek gösterebilir misiniz? Bu yararlı olur.
Avikool91

5

Temel kural diyor ki:

Tanımlayıcı oluşturulmuş Varlıklar için:

save (): Nesneyi kalıcı hale getirmenin yanı sıra bir varlığın tanımlayıcısını hemen döndürür. Böylece bir ekleme sorgusu derhal tetiklenir.

persist (): Kalıcı nesneyi döndürür. Tanımlayıcıyı hemen iade etme zorunluluğu yoktur, bu nedenle ekin hemen ateşleneceğini garanti etmez. Bir kesici ucu derhal ateşleyebilir ancak garanti edilmez. Bazı durumlarda, sorgu hemen tetiklenirken, bazılarında oturum boşaltma zamanında tetiklenebilir.

Atanmış tanımlayıcıya sahip Varlıklar için:

save (): Bir varlığın tanımlayıcısını hemen döndürür. Tanımlama, kaydetme çağrılmadan önce varlığa zaten atandığından, ekleme derhal tetiklenmez. Seans yıkama zamanında ateşlenir.

persist (): save ile aynı. Aynı zamanda yıkama sırasında yangın eki.

Oluşturulan tanımlayıcıyı aşağıdaki gibi kullanan bir varlığımız olduğunu varsayalım:

@Entity
@Table(name="USER_DETAILS")
public class UserDetails {
    @Id
    @Column(name = "USER_ID")
    @GeneratedValue(strategy=GenerationType.AUTO)
    private int userId;

    @Column(name = "USER_NAME")
    private String userName;

    public int getUserId() {
        return userId;
    }
    public void setUserId(int userId) {
        this.userId = userId;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
}

kayıt etmek() :

    Session session = sessionFactory.openSession();
    session.beginTransaction();
    UserDetails user = new UserDetails();
    user.setUserName("Gaurav");
    session.save(user); // Query is fired immediately as this statement is executed.
    session.getTransaction().commit();
    session.close();

persist ():

    Session session = sessionFactory.openSession();
    session.beginTransaction();
    UserDetails user = new UserDetails();
    user.setUserName("Gaurav");
    session.persist(user); // Query is not guaranteed to be fired immediately. It may get fired here.
    session.getTransaction().commit(); // If it not executed in last statement then It is fired here.
    session.close();

Şimdi, id alanı ek açıklama oluşturmadan aşağıdaki gibi tanımlanmış aynı varlığa sahip olduğumuzu varsayalım, yani kimlik manuel olarak atanacaktır.

@Entity
@Table(name="USER_DETAILS")
public class UserDetails {
    @Id
    @Column(name = "USER_ID")
    private int userId;

    @Column(name = "USER_NAME")
    private String userName;

    public int getUserId() {
        return userId;
    }
    public void setUserId(int userId) {
        this.userId = userId;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
}

save () için:

Session session = sessionFactory.openSession();
session.beginTransaction();
UserDetails user = new UserDetails();
user.setUserId(1);
user.setUserName("Gaurav");
session.save(user); // Query is not fired here since id for object being referred by user is already available. No query need to be fired to find it. Data for user now available in first level cache but not in db.
session.getTransaction().commit();// Query will be fired at this point and data for user will now also be available in DB
session.close();

persist () için:

Session session = sessionFactory.openSession();
session.beginTransaction();
UserDetails user = new UserDetails();
user.setUserId(1);
user.setUserName("Gaurav");
session.persist(user); // Query is not fired here.Object is made persistent. Data for user now available in first level cache but not in db.
session.getTransaction().commit();// Query will be fired at this point and data for user will now also be available in DB
session.close();

Yukarıdaki durumlar, bir işlemin içinden kaydetme veya kalıcı çağrı çağrıldığında doğrudur.

Save ve persist arasındaki diğer fark noktaları:

  1. save () işlemi bir işlemin dışında çağrılabilir. Atanmış tanımlayıcı kullanılırsa, kimlik zaten mevcut olduğundan, hiçbir ekleme sorgusu hemen tetiklenmez. Sorgu yalnızca oturum temizlendiğinde tetiklenir.

  2. Oluşturulan tanımlayıcı kullanılırsa, id'nin oluşturulması gerektiğinden, ekleme derhal tetiklenir. Ancak yalnızca birincil varlığı kaydeder. Varlığın bazı basamaklı varlıkları varsa, bunlar bu noktada db'ye kaydedilmez. Oturum temizlendiğinde kaydedilirler.

  3. Persist () bir işlemin dışındaysa, ekleme ne tür bir tanımlayıcı (oluşturulmuş veya atanmış) kullanılırsa kullanılsın yalnızca oturum temizlendiğinde tetiklenir.

  4. Kalıcı bir nesne üzerinden kaydetme çağrılırsa, varlık güncelleme sorgusu kullanılarak kaydedilir.


2

Aslında, hibernate save () ve persist () yöntemleri arasındaki fark kullandığımız jeneratör sınıfına bağlıdır.
Jeneratör sınıfımız atanırsa, save () ve persist () yöntemleri arasında fark yoktur. Jeneratör 'atanmış' anlamına gelir, bir programcı olarak veritabanına kaydetmek için birincil anahtar değerini vermeliyiz [Umarım bu jeneratörler konseptini biliyorsunuz] Atanmış jeneratör sınıfı dışında bir durumda, jeneratör sınıfı adımızın Artış anlamı olup olmadığını varsayalım hazırda bekletme modunun kendisi veritabanına birincil anahtar id değerini atar [atanmış jeneratör dışında, hazırda bekletme yalnızca birincil anahtar id değerini hatırlamak için kullanılır], bu durumda save () veya persist () yöntemini çağırırsak, kaydı normal olarak veritabanına ekler.
Ancak burada, save () yöntemi hazırda bekletme tarafından oluşturulan birincil anahtar kimliği değerini döndürebilir ve bunu
long s = session.save (k) ile görebiliriz;
Aynı durumda, persist () hiçbir zaman istemciye herhangi bir değer vermez, void türünü döndürür.
persist () ayrıca, işlem sınırları dışında çağrıldığında bir INSERT ifadesi yürütmeyeceğini de garanti eder.
save () içinde ise, bir işlemin içinde veya dışında olsanız da INSERT hemen gerçekleşir.


1

Herhangi bir varlığı saklarken ID'deki "jeneratör" tipi temelinde tamamen cevap verdi. Üreticinin değeri "atanmışsa", kimliği sağladığınız anlamına gelir. Ardından, kaydetme veya devam etme için hazırda bekletme modunda fark oluşturmaz. İstediğiniz herhangi bir yöntemle gidebilirsiniz. Değer "atanmazsa" ve save () kullanıyorsanız, save () işleminden dönüş olarak ID alırsınız.

Başka bir kontrol, işlemi işlem sınırı dışında gerçekleştirip gerçekleştirmediğinizdir. Çünkü persist (), hazırda bekletme için save () işlevini kullanırken JPA'ya aittir. Bu nedenle, persist () dışında işlem sınırlarının kullanılması, buna izin vermeyecek ve kalıcı ile ilgili istisnaları atamayacaktır. save () ile böyle bir kısıtlama yoktur ve bir save () üzerinden işlem limitinin dışında DB işlemi ile gidilebilir.

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.