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

时间:2008-10-04 20:40:10

标签: nhibernate session

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

请解释两者之间的区别。

7 个答案:

答案 0 :(得分:155)

这是来自Hibernate参考文档的10.7. Automatic state detection部分:

  

saveOrUpdate()执行以下操作:

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

和merge()非常不同:

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

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

答案 1 :(得分:9)

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

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

答案 2 :(得分:4)

从NHibernate 3.1开始,

SaveOrUpdateCopy()现已弃用。应该使用Merge()代替。

答案 3 :(得分:1)

我发现this链接在解释此类异常方面做得非常好:

对我有用的是:

  1. 在映射Myclass.hbm.xml文件中,设置cascade="merge"
  2. 在将子/依赖对象分配给父对象之前,先
  3. SaveOrUpdate
  4. SaveOrUpdate父对象。
  5. 但是,这种解决方案有局限性。也就是说,你必须注意保存你的孩子/依赖对象,而不是让冬眠为你做这件事。

    如果有人有更好的解决方案,我希望看到。

答案 4 :(得分:1)

新用户名,所以我无法对Quoc Truong的帖子发表评论或投票。但是,我也认为这个链接非常有用,如前所述。

http://www.roseindia.net/hibernate/hibernate4/org_hibernate_nonuniqueobjectexception.shtml

答案 5 :(得分:1)

** Update()**

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

** Merge()**

: - 如果你想在不知道会话状态的情况下随时保存你的修改,那么在hibernate中使用merge()。

答案 6 :(得分:-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();
        }

    }
}
相关问题