Session.Merge ve session.SaveOrUpdate arasındaki fark nedir?


87

Bazen ebeveyn / çocuk nesnelerimle veya çoktan çoğa ilişkilerimle ya SaveOrUpdateda aramam gerektiğini fark ediyorum Merge. Genellikle, aramam gerektiğinde SaveOrUpdate, aradığımda aldığım istisna, Mergeönce kaydedilmeyen geçici nesnelerle ilgilidir.

Lütfen ikisi arasındaki farkı açıklayın.

Yanıtlar:


158

Bu bölüm 10.7'den. Hazırda Bekletme Referans Dokümantasyonunun otomatik durum tespiti :

saveOrUpdate () şunları yapar:

  • nesne bu oturumda zaten kalıcıysa, hiçbir şey yapmayın
  • Eğer oturumla ilişkili başka bir nesne aynı tanımlayıcıya sahipse, bir istisna at
  • nesnenin tanımlayıcı özelliği yoksa, onu kaydedin ()
  • nesnenin tanımlayıcısı yeni başlatılmış bir nesneye atanmış değere sahipse, onu kaydedin ()
  • nesnenin sürümü değiştirilmişse (bir <sürüm> veya <timestamp>) ve version özelliği değeri yeni başlatılan bir nesneye atanan değerle aynı ise, onu kaydedin ()
  • aksi takdirde nesneyi güncelle ()

ve merge () çok farklıdır:

  • Şu anda oturumla ilişkili aynı tanımlayıcıya sahip kalıcı bir örnek varsa, verilen nesnenin durumunu kalıcı örneğe kopyalayın
  • Şu anda oturumla ilişkilendirilmiş kalıcı bir örnek yoksa, onu veritabanından yüklemeyi deneyin veya yeni bir kalıcı örnek oluşturun
  • kalıcı örnek döndürülür
  • verilen örnek oturumla ilişkilendirilmez, bağımsız kalır

Merge () 'yi, oturumdan bir noktada ayrılmış olan nesneleri güncellemeye çalışıyorsanız, özellikle de o anda oturumla ilişkili olan nesnelerin kalıcı örnekleri varsa, kullanmalısınız. Aksi takdirde, bu durumda SaveOrUpdate () kullanmak bir istisnaya neden olur.


iyi cevap ... Acaba yeni bir varlık üzerinde birleştirme kullanırsam, sonradan kaydetmeyi kullanmak için herhangi bir neden var mıdır yoksa birleştirmenin DB'de yeni varlığı oluşturduğundan emin olabilir miyim? (ve bağımsız bir varlık ise, değişiklikler DB'ye otomatik olarak atlanır mı?)
Dani

5
Bundan emin misin? NHiberante kaynağına bakıldığında SaveOrUpdateCopy, Merge işleviyle aynı parametrelere sahip bir Merge olayını tetikler. Bunların aynı olduğunu düşünüyorum, SaveOrUpdateCopy işlevi, 1.0'dan bu yana hazırda bekletme / nhibernate'de var olan bir şeydir, Birleştirme işlevi yeni ve yeni bir java standardına uymak için hazırda bekletmeye eklendi (sanırım)
Torkel

5
@Torkel - SaveOrUpdateCopyaynı şey değil SaveOrUpdate. Soruyu soran Mergekişinin ilkini mi yoksa ikincisini mi karşılaştırmak istediğinden emin değilim . ithal SaveOrUpdateCopyedilmeden önce NHibernate'de birleştirme yapan, artık kullanılmayan bir yöntemdir Merge.
codekaizen

bilmek güzel ... SaveOrUpdate eğitimlerde hala yoğun bir şekilde kullanılmaktadır.
anael

9

Anladığım kadarıyla, merge()geçerli oturum ile ilişkili olmayabilir bir nesne almak ve bir nesneye, devlet (vb özellik değerlerini,) kopyalar olduğu bir aynı PK değeri / tanımlayıcı ile (geçerli oturum ile ilişkili kurs).

saveOrUpdate() Arayacağım belirli bir nesnenin kimlik değerine göre oturumunuzda Kaydet veya Güncelle'yi .


4

SaveOrUpdateCopy()NHibernate 3.1 itibariyle artık kullanımdan kaldırılmıştır. Merge()bunun yerine kullanılmalıdır.


9
Bu var SaveOrUpdateCopyişaretlenmiş olan Obsoletedeğil SaveOrUpdate. Bu soru ve sonraki cevaplarda bu iki farklı yöntem arasında çok fazla kafa karışıklığı var gibi görünüyor.
codekaizen

2
** Update()**

: - oturumun aynı tanımlayıcıya sahip zaten kalıcı bir örnek içermediğinden eminseniz, verileri hazırda bekletme moduna kaydetmek için güncellemeyi kullanın

** Merge()**

: -Bir oturumun durumunu bilmeden herhangi bir zamanda değişikliklerinizi kaydetmek istiyorsanız, hazırda bekletme modunda merge () kullanın.


1

Bu tür bir istisnayı açıklayan oldukça iyi bir iş çıkaran bu bağlantıyı buldum :

Benim için işe yarayan şey şudur:

  1. Myclass.hbm.xml dosyası eşlemesinde, cascade="merge"
  2. SaveOrUpdate üst nesneye atamadan önce alt / bağımlı nesne.
  3. SaveOrUpdate üst nesne.

Ancak bu çözümün sınırlamaları vardır. yani, sizin için hazırda bekletmeye izin vermek yerine çocuğunuzu / bağımlı nesnenizi korumaya özen göstermelisiniz.

Daha iyi bir çözümü olan varsa görmek isterim.


-2
@Entity
@Table(name="emp")
public class Employee implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name="emp_id")
    private int id;
    @Column(name="emp_name")
    private String name;
    @Column(name="salary")
    private int Salary;


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getSalary() {
        return Salary;
    }

    public void setSalary(int salary) {
        this.Salary = salary;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
}

public enum HibernateUtil {
    INSTANCE;
    HibernateUtil(){
        buildSessionFactory();
    }
    private SessionFactory sessionFactory=null;

    public SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    private  void buildSessionFactory() {
        Configuration configuration = new Configuration();

        configuration.addAnnotatedClass (TestRefresh_Merge.Employee.class);
        configuration.setProperty("connection.driver_class","com.mysql.jdbc.Driver");
        configuration.setProperty("hibernate.connection.url", "jdbc:mysql://localhost:3306/hibernate");                                
        configuration.setProperty("hibernate.connection.username", "root");     
        configuration.setProperty("hibernate.connection.password", "root");
        configuration.setProperty("dialect", "org.hibernate.dialect.MySQLDialect");
        configuration.setProperty("hibernate.hbm2ddl.auto", "update");
        configuration.setProperty("hibernate.show_sql", "true");
        configuration.setProperty(" hibernate.connection.pool_size", "10");
        /* configuration.setProperty(" hibernate.cache.use_second_level_cache", "true");
         configuration.setProperty(" hibernate.cache.use_query_cache", "true");
         configuration.setProperty(" cache.provider_class", "org.hibernate.cache.EhCacheProvider");
         configuration.setProperty("hibernate.cache.region.factory_class" ,"org.hibernate.cache.ehcache.EhCacheRegionFactory");
        */
        // configuration
        StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties());
           sessionFactory = configuration.buildSessionFactory(builder.build());
           setSessionFactory(sessionFactory);
    }

    public  static SessionFactory getSessionFactoryInstance(){
        return INSTANCE.getSessionFactory();
    }
} 


public class Main {
    public static void main(String[] args) {
        HibernateUtil util=HibernateUtil.INSTANCE;
        SessionFactory factory=util.getSessionFactory();
        //save(factory); 
        retrieve(factory);
    }

     private static void retrieve(SessionFactory factory) {
        Session sessionOne=factory.openSession();

        Employee employee=(Employee)sessionOne.get(Employee.class, 5);

        sessionOne.close(); // detached Entity

        employee.setName("Deepak1");

        Session sessionTwo=factory.openSession();

        Employee employee1=(Employee)sessionTwo.get(Employee.class, 5);
        sessionTwo.beginTransaction();
        sessionTwo.saveOrUpdate(employee); // it will throw exception

        //sessionTwo.merge(employee); // it will work

        sessionTwo.getTransaction().commit();

        sessionTwo.close();

    }

    private static void save(SessionFactory factory) {
        Session sessionOne=factory.openSession();
        Employee emp=new Employee();
        emp.setName("Abhi");
        emp.setSalary(10000);
        sessionOne.beginTransaction();
        try{

            sessionOne.save(emp);
            sessionOne.getTransaction().commit();
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            sessionOne.close();
        }

    }
}

2
Yanıtınızı, etkilenen kodu gösterecek şekilde düzenlemeyi ve ardından belki de sonunda tam kod dökümünü düşünmelisiniz. Olduğu gibi aşağı kaydırmalı ve yorumlar arasında şansa ihtiyacımız var. Nasıl Cevaplanacağını görün .
Bugs
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.