88

我有时注意到我的父/子对象或多对多关系,我需要调用SaveOrUpdateor Merge。通常,当我需要调用时SaveOrUpdate,我调用的异常Merge与未首先保存的瞬态对象有关。

请说明两者的区别。

4

6 回答 6

160

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

saveOrUpdate() 执行以下操作:

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

和 merge() 非常不同:

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

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

于 2008-10-04T21:20:09.290 回答
9

据我了解,merge()将获取一个可能与当前会话无关的对象,并将其状态(属性值等)复制到与当前会话关联的对象具有相同的 PK 值/标识符,课程)。

saveOrUpdate()将根据给定对象的标识值在您的会话上调用SaveUpdate 。

于 2008-10-04T21:23:14.023 回答
4

SaveOrUpdateCopy()现在已弃用 NHibernate 3.1。Merge()应改为使用。

于 2011-04-05T11:38:37.747 回答
2
** Update()**

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

** Merge()**

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

于 2015-04-20T09:13:07.237 回答
1

我发现这个链接很好地解释了这种类型的异常:

对我有用的是以下内容:

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

然而,这种解决方案有局限性。即,您必须注意保存您的孩子/依赖对象,而不是让 hibernate 为您做这件事。

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

于 2014-02-17T21:23:55.913 回答
-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();
        }

    }
}
于 2016-03-06T18:24:54.647 回答