`

如何删除detached instance?

阅读更多
问题描述
应用实例环境:Spring jpa hibernate3
常用数据库表的删除办法,一般都会在DAO类中提供delete.如下例:
public class UnitDAO implements IUnitDAO {
        private EntityManager entityManager;
        
        @PersistenceContext
        public void setEntityManager(EntityManager entityManager) {
                this.entityManager = entityManager;
        }
        
        private EntityManager getEntityManager() {
                return this.entityManager;
        }
        
        public void delete(Unit persistentInstance) {
                try {
                        getEntityManager().remove(persistentInstance);
                } catch (RuntimeException re) {
                        throw re;
                }
        }

        public List<Unit> findAll() {
                try {
                        String queryString = "select model from Unit model";
                        return getEntityManager().createQuery(queryString).getResultList();
                } catch (RuntimeException re) {
                        throw re;
                }
        }
}

看上去,没有任何问题,这也是在MyEclipse中自动产生的代码。但是,在实际运行过程中,界面会调用findAll()获得全部的unit记录显示在界面层,根据业务需求,用户选择一个unit进行删除,当调用delete方法时,出现异常:
        java.lang.IllegalArgumentException: Removing a detached instance com.gotop.rbac.model.Unit#1
   意思就是说,在删除一个detached instance出错。

    解决办法:
看看Hibernate是如何处理对象的.Chapter 10. Working with objects. http://www.hibernate.org/hib_docs/reference/en/html/objectstate.html
    说的很清楚。Hibernate object states有三种状态:Transient、Persistent、Detached。关于Detached,是这么说的:
        Detached - a detached instance is an object that has been persistent, but its Session has been closed. The reference to the object is still valid, of course, and the detached instance might even be modified in this state. A detached instance can be reattached to a new Session at a later point in time, making it (and all the modifications) persistent again.
        一个detached instance是一个已经持久化的对象,但是它的Session已经关闭了,它的引用依然有效,当然,detached instance可能被修改。detached instance能够在以后可以重新附属到一个新的Session,使之能重新序列化。
   
        好了,找到解决办法了,在删除之前把这个Detached instance绑定到当前的Sesssion,在用当前Sesssion删除此instance。getEntityManager()提供merge方法实现。
修改后的delete代码:
        public void delete(Unit persistentInstance) {
                try {
                        getEntityManager().remove(getEntityManager().merge(persistentInstance));
                } catch (RuntimeException re) {
                        throw re;
                }
        }
       千万不要写成:
        try {
                getEntityManager().merge(persistentInstance);
                getEntityManager().remove(persistentInstance);
        }               
       执行完merge后persistentInstance还是detached, merge后返回的新对象才是允许删除的。 


文章出处:DIY部落(http://www.diybl.com/course/3_program/java/javashl/2007123/89631.html)
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics