`
lcy0202
  • 浏览: 178215 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

session.merge ()方法的使用

阅读更多


问题情况:使用hibernate来进行对对象的保存操作时,出现了exception,导致数据保存不成功,具体报错如是:

Exception in thread "main" org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session:

使用情况(本人遇到):如果是在保存对象的时候,如果对象有外键,则在保存的时候,要根据外键来获取数据库所对应的记录的对象,之后再set入要保存的的对象中,如果是直接new一个外键的对象(外键的值在数据库有对应的值)再set入保存的对象中的时候,就会报错:Exception in thread "main" org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session:,这个是因为,在保存的时候,session会检查在内存的外简单的对象跟你new的对象是否一样(不是根据对象的值,而是根据在内存的地址是否一致来比较的),所以new出来的对象是无法跟内存里面的对象一致的,因而,会说不同的对象有一样的id,所以保存数据库的时候就直接根据外键来获取对应的数据库记录来保存对象,所以这个时候用merge方法还是解决不了问题的。

最后是在查了一下,采用session.merge (object c)代替session.save(object c),即可解决,主要涉及到session.merge ()方法的使用以及session.merge ()跟session.save()、session.update ()方法的区别,这篇博文详细说明了问题....

该方法将修改表中记录,其所需要的实体状态为脱管状态,但是注意,它并不影响调用方法前后的状态,也即该实体依然是脱管状,见例6.4。

例6.4:session.merge ()方法对状态的变化

     public void run() {

          //创建UserInfo实例

          UserInfo userInfo = new UserInfo();

          //使之成为脱管状态

          userInfo.setId(11112);

          userInfo.setName("RW3");

          userInfo.setSex("M");

          //创建UserInfo实例

          UserInfo userInfo2 = new UserInfo();

          //使之成为脱管状态

          userInfo2.setId(11112);

          userInfo2.setName("RW4");

          userInfo2.setSex("F");

          //启动Session

          Session session = HibernateSessionFactory.currentSession();

          //启动事务

          Transaction tx = session.beginTransaction();

          //调用merge方法,此时UserInfo实体状态并没有被持久化

          session.merge(userInfo);

          //调用merge方法,此时UserInfo实体状态并没有被持久化

          //但是数据库中的记录被更新了

          ①session.merge(userInfo2);

          //merge方法与update方法的差别在于针对同样的操作update方法会报错

          //原因在于update方法使得实体状态成为了持久化状态,而Session中不允许两个持久化实体有同样的持久化标识

          ②//session.update(userInfo);

          //session.update(userInfo2);

         //以下两句不会发送SQL,因为userInfo2不是持久化状态的实体

         ③userInfo2.setName("RW5");

          userInfo2.setSex("M");

          //提交事务

          tx.commit();

          //关闭Hibernate Session

          HibernateSessionFactory.closeSession();

     }

针对该段代码将执行如下SQL语句:

Hibernate:

/* ①session.merge(userInfo2)的动作 */

select

        userinfo0_.id as id0_0_,

        userinfo0_.NAME as NAME0_0_,

        userinfo0_.SEX as SEX0_0_,

        userinfo0_.roomid as roomid0_0_

    from

        userinfo userinfo0_

    where

        userinfo0_.id=?

Hibernate:

/* ①session.merge(userInfo2)的动作 */

update

            userinfo

        set

            NAME=?,

            SEX=?,

            roomid=?

        where

            id=?

session.merge()方法会首先发送一句select语句,去数据库端获取UserInfo持久化标识所对应的表记录;然后自动生成一个持久化状态的UserInfo实体,与脱管状态的UserInfo实体做比较是否有所改变;一旦发生了改变,才会发送update语句执行更新。而按执行顺序,若两句session.merge()方法针对同一个脱管状态的UserInfo实体,那其结果只会执行最后一个session.merge()方法所发出的update语句。即使执行了session.merge()方法,UserInfo实体依然是脱管状态,因此③userInfo2. setName("RW5")的语句不会同步数据库中的表。

本文来自:网易博客~http://blog.163.com/linyiliuzhen@126/blog/static/16481455720117161365386/

分享到:
评论

相关推荐

    session中merge和update的区别

    Hibernate中session的merge以及update方法

    Hibernate中的merge使用详情解说

    在第二个 Session 中,我们使用相同的 ID 从数据库中获取了一个 Students 对象,并使用 merge 方法将第一个 Session 中的对象数据赋值给第二个 Session 中的对象。 需要注意的是,在使用 merge 方法时,我们需要...

    hibernate session.doc

    另外,`Session`还有一系列方法用于处理对象的状态转换,如`lock()`、`merge()`、`refresh()`、`evict()`等,这些方法在处理对象生命周期的不同阶段时非常关键。 `Configuration`和`SessionFactory`也是Hibernate的...

    SSHnote session函数的对象状态转换

    要将脱管对象重新变为持久化,可以使用`Session.merge()`方法。`merge()`会复制脱管对象的所有属性到与之关联的数据库记录,然后返回一个与当前Session关联的新持久化对象。 5. **脱管到瞬时:** 这个转换不需要...

    使用hibernate连接oracle数据库的详细方法,代码实现实现数据库的增删改查.zip

    - 修改:`Session.update()`或`Session.merge()`用于更新数据。 - 查询:`Session.get()`, `Session.load()`, `Session.createQuery()`, `Session.createSQLQuery()`等方法用于获取数据。 6. **事务处理** - ...

    hibernate示例

    - **更新(Update)**:使用`Session.update()`或`Session.merge()`方法更新对象状态。例如: ```java Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); entity.set...

    hibernate--3.Hibernate数据持久化(通过 Session 操纵对象)

    然后,可以使用Session的`save()`或`saveOrUpdate()`方法将新对象持久化到数据库。例如: ```java SessionFactory sessionFactory = ...; // 获取SessionFactory Session session = sessionFactory.openSession(); ...

    java利用hibernate连接数据库

    - 更新:`session.update()`或`session.merge()`方法。 - 删除:`session.delete()`方法。 5. 提交事务:`session.getTransaction().commit()`提交事务,确保数据持久化。 6. 关闭资源:记得关闭Session和...

    Hibernate之API初识及增删改查实现案例hibernate003

    而游离态的对象,如果希望重新与Session关联,可以使用`Session.merge()`。 6. **CRUD操作**: - **创建(Create)**:`Session.save()`或`Session.persist()`方法用于将对象保存到数据库,生成新的主键。 - **...

    Hibernate merge、update与saveOrUpdate方法的区别

    - 使用`merge`方法,Hibernate首先会查询数据库中是否存在相同的ID,如果存在则更新该记录;如果不存在,则插入一条新记录。 - 使用`update`方法,Hibernate会直接更新对应ID的记录,假设ID存在的情况下。 - 使用...

    Hibernate的Session的javadoc

    - **merge()**:将游离或自由状态的对象合并到当前Session,创建一个新的持久化实例。 - **replicate()**:复制对象到数据库,可以用于复制现有记录或创建新记录。 - **persist()**:与save()类似,但不适用于已...

    merge的注意事项

    在Hibernate框架中,`merge()`是一个非常重要的方法,用于将一个对象的状态合并到当前的Session中。当调用`merge()`方法时,Hibernate会检查传入的对象是否已经在当前Session中存在。如果不存在,它将作为一个新对象...

    Hibernate入门

    调用`Session.update()`或`Session.merge()`方法更新对象状态,Hibernate会在事务提交时自动执行UPDATE语句。 #### - 删除(Delete) 使用`Session.delete()`方法移除对象,对应的数据库记录会被DELETE。 ### 6. ...

    Hibernate增删改查

    2. **更新(Update)**:当对象的状态发生改变,调用`Session.update()`或`Session.merge()`方法,Hibernate会检测变化并更新数据库记录。 3. **删除(Delete)**:调用`Session.delete()`方法,Hibernate会从...

    Hibernate中的merge使用详情解说.docx

    在第二个会话中,`merge(str1)`将游离态的`str1`对象的状态合并到由`session2.get()`获取的持久化对象`str2`中。这导致`str2.getName()`的值改变,而`str1.getName()`的值不变,因为`str1`仍然是游离态。 综上所述...

    Hibernate:不容易理解的 lock 和 merge.docx

    因此,如果尝试获取该对象的最新版本,需要再次使用 `session.get()` 方法。 ```java session.lock(user, LockMode.NONE); // 为了测试执行 lock 后实例是否变为持久化状态。 user = (User) session.get(User.class...

    Hibernate Part 2:单表CRUD

    此外,`Session`的`flush()`方法用于将内存中的改变同步到数据库,而`clear()`则可以清除当前Session中的对象。事务管理在Hibernate中非常重要,通常使用`Transaction`对象来包裹一组操作,确保其原子性。 对于更...

    Hibernate中get和load方法的区别以及close(),clear()、evict()等的区别

    游离状态的对象可以通过`merge`或`update`方法重新与Session关联,以同步其状态。 了解这些概念和方法的区别对于高效地使用Hibernate进行数据库操作至关重要,可以根据具体场景选择合适的方法来优化应用程序的性能...

    test-hibernate:了解一级缓存的工作原理

    示例 4a - 使用session.merge(..)更新非 Hibernate 托管实体。 示例 5 - 删除会话中已存在具有相同标识符的实体的非 Hibernate 受管实体。 示例 5a - 在删除非 Hibernate 受管实体之前首先使用session.merge(..) 。...

    SessionFactory.getCurrentSession与openSession的区别

    当在一个已开始的事务中调用此方法时,它会返回当前线程中已经存在的Session,如果不存在,则创建一个新的Session并将其绑定到线程。这种方式有助于减少不必要的Session创建,提高性能,并且自动管理事务的边界。 2...

Global site tag (gtag.js) - Google Analytics