nested exception is org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [com.nstc.fts.domain.BcmAccountGroup#49]
saveOrUpdate(po)做下面的事:
如果该po对象已经在本session中持久化了,在本session中执行saveOrUpdate不做任何事
如果savaOrUpdate(新po)与另一个与本session关联的po对象拥有相同的持久化标识(identifier),抛出一个异常
org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [com.nstc.fts.domain.BcmAccountGroup#49]
saveOrUpdate如果对象没有持久化标识(identifier)属性,对其调用save() ,否则update() 这个对象。
解决办法
使用clear完整的清除session缓存
this.getHibernateTemplate().clear();
this.getHibernateTemplate().update(bcmAccountGroup);
evict()、clear()和flush()方法是Hibernate缓存的3种基本操作方法
1.Clear 方法:无论是Load 还是 Get 都会首先查找缓存(一级缓存) 如果没有,才会去数据库查找,调用Clear() 方法,可以强制清除Session缓存。
session.clear(),把缓冲区内的全部对象清除,但不包括操作中的对象。
2.Flush方法:可以强制进行从内存到数据库的同步。
session.flush()的作用是将数据库与缓存中的数据同步 当session.clear()后才会引起缓存数据变化。
3. Evict 方法:
session.evict(obj),会把指定的缓冲对象进行清除。
POJO类所处的状态有三种:
瞬时态(Transient):
对象保存在内存之中,并没有在数据库之中进行存储。那么就有可能被GC回收。
持久态(Persistent):
将内存中的对象保存在数据库中,或者某一个对象通过数据库读取,此时的Session如果没有关闭,那么就是持久态。
持久态的最大特征是属性的变化将引起数据库的变化。如果某一个对象处于持久态的状态下,只需要调用setter方法就可以更新了。
游离态(Detached):
如果Session关闭了,那么读取出来的数据就变为了游离态,这个时候对象保存在内存之中,如果长时间不使用将被GC回收。
与瞬时态最大的区别只有一点:此时数据库有对应数据。
实际上在Session里面存在有get()和load()两个操作方法,这两个方法都是根据ID进行数据查询,使用ID查询也会使对象处于持久态(不关闭Session)。
瞬时态 ----> 持久态:save()方法、update()方法
持久态 ----> 游离态:关闭Session
游离态 ----> 瞬时态:使用delete()删除
hibernate执行的顺序
(1)生成一个事务的对象,并标记当前的Session处于事务状态,此时并未启动数据库级事务。
(2)应用使用 session.save(obj)保存对象,这个时候Session将这个对象放入entityEntries,用来标记对象已经和当前的会话建立了关联,由于应用对对象做了保存的操作,
Session还要在insertions中登记应用的这个插入行为(行为包括:对象引用、对象id、Session、持久化处理类)。
(3)session.evict(obj)将对象从session会话中拆离,这时session会从entityEntries中将这个对象移出。
(4)事务提交,需要将所有缓存flush入数据库,Session启动一个事务,并按照insert,update,……,delete的顺序提交所有之前登记的操作。