session.Merge和session.SaveOrUpdate有什么区别?


86

我发现有时与父母/子女对象或多对多关系,我需要调用SaveOrUpdateMerge。通常,当我需要调用时SaveOrUpdate,我遇到的异常Merge与未首先保存的临时对象有关。

请说明两者之间的区别。

Answers:


157

这来自第10.7Hibernate参考文档的自动状态检测

saveOrUpdate()执行以下操作:

  • 如果对象在此会话中已经持久,则不执行任何操作
  • 如果与该会话关联的另一个对象具有相同的标识符,则引发异常
  • 如果对象没有标识符属性,请保存()
  • 如果对象的标识符具有分配给新实例化的对象的值,则将其保存()
  • 如果对象已版本化(通过<version>或<timestamp>),并且version属性值与分配给新实例化的对象的值相同,则save()
  • 否则update()对象

和merge()非常不同:

  • 如果存在与会话当前关联的具有相同标识符的持久实例,则将给定对象的状态复制到持久实例上
  • 如果当前没有与该会话关联的持久性实例,请尝试从数据库中加载它,或创建一个新的持久性实例
  • 持久实例返回
  • 给定实例未与会话关联,它保持分离

如果您尝试更新从会话分离的某一时刻的对象,则应该使用Merge(),尤其是如果当前存在与会话相关联的那些对象的持久实例。否则,在这种情况下使用SaveOrUpdate()将导致异常。


很好的答案...我想知道-如果我在新实体上使用合并,是否有任何理由使用保存后缀,或者我可以肯定合并肯定在数据库中创建了新实体?(如果是独立实体,则合并后是否会自动将更改遗忘给数据库?)
Dani

5
你确定吗?查看NHiberante源SaveOrUpdateCopy会触发具有与Merge函数相同参数的Merge事件。我认为它们是相同的,自1.0以来,SaveOrUpdateCopy函数在hibernate / nhibernate中已经存在。Merge函数是新的,并且已添加到hibernate中以符合新的Java标准(我认为)
Torkel,2010年

5
@Torkel-SaveOrUpdateCopy与相同SaveOrUpdate。我不确定提问者是否想比较Merge前者或后者。SaveOrUpdateCopy是一种过时的方法,在Merge导入之前在NHibernate中进行了合并。
codekaizen 2011年

必知... SaveOrUpdate仍在教程中大量使用。
anael 2011年

9

据我所知,merge()将可能不与当前会话相关联的对象,并且其状态(属性值等)拷贝到一个对象与当前会话相关联的(具有相同的PK值/标识符,的课程)。

saveOrUpdate()将根据给定对象的标识值在您的会话上调用保存更新



2
** Update()**

:-如果您确定会话不包含具有相同标识符的已经存在的实例,则使用update将数据保存在休眠状态

** Merge()**

:-如果您想在不了解会话状态的情况下随时保存您的修改,请在休眠状态下使用merge()。


1

我发现链接在解释这种类型的异常方面做得很好:

对我有用的是:

  1. 在映射Myclass.hbm.xml文件中,设置 cascade="merge"
  2. SaveOrUpdate 子对象/依赖对象首先分配给父对象。
  3. SaveOrUpdate 父对象。

但是,此解决方案有局限性。即,您必须注意保存子对象/依赖对象,而不要让休眠模式为您做这件事。

如果有人有更好的解决方案,我想看看。


-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
您应该考虑编辑答案以显示受影响的代码,然后在最后考虑完整的代码转储。就目前情况而言,我们必须向下滚动,并在注释中保留机会。请参阅如何回答
Bug,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.