hibernate先删除数据,紧接着执行插入时的异常解决之道——中间不能调用flush()、clear()等方法

hibernate先删除数据,紧接着执行插入时的异常解决之道——中间不能调用flush()、clear()等方法

 

  项目中包含这样一个寻常的业务:为某一个用户指定用户群。一个用户可以被分配到多个用户群中,后台管理者可以为该用户分配用户群,并可更新这种分配。在做更新的时候,将所有的用户群都以checkBod的形式显示出来,页面初始化的时候,那些用户已经关联的群的checkBox会被勾选,然后管理员可以重新勾选,重新为该用户指定用户群。

  好了,问题出现了:在重新指定用户群的时候,首先需要删除数据库中原有的一张关系表(该表中储存用户ID和用户群ID)中所有该用户ID的记录,然后再重新将管理员所指定的新的用户群保存进这种关系表中。于是这里至少需要两条sql文——delete()和save()。由于担心在插入数据的时候系统难免会因为某些特殊的偶然的原因而出现故障而导致无法插入,此时就需要保证出现这种情况时,delete()语句执行无效,即delete()之后,不能调用flushu()、clear()、commit()等方法(这些方法会迫使原先对内存中的备份数据的删除操作进一步作用于持久层)。但是这样又会出现新的问题:持久层中的数据不真正删除掉,就无法再插入新的数据,否则会抛出诸如“存在一个与该对象完全相同的另一个对象”之类的异常。这还真是一问题,不过思考了许久之后,还是想出一条锦囊妙计,那就是:先用一个hashmap来保存每一个被删除掉的关系对象和该对象中的用户群的ID(因为用户表语用户群表的关系是一对多的关系),然后在执行插入数据的时候,先判断管理员所勾选的用户群是否也存在于该map中(通过用户群ID来判断),如果是存在,那么也就是该用户群是用户原本就被分配在其中的,那么在开始执行删除的时候,该关系对象已经在内存中被删除掉了,但是真正的持久层中尚未被删除(因为没有调用flush()等方法来强迫执行),那么这时就从map中取出该关系对象,直接执行savaOrUpdate()方法;而如果不存在,则new一个关系对象,然后设置该对象的用户ID和用户群ID属性,然后执行save()方法。OK,一个难题就这样被解决了。

  下面是项目中的该业务部分的代码,以形象地解释上面的萝莉啰唆的文字:

  //保存用户与其所关联的用户群关系(先删除全部记录,再分布保存)
        
        //该哈希表键为用户群ID,值为用户与其所关联的用户群关系对象(UsrGroup)
        HashMap<Long, UsrGroup> map = new HashMap<Long, UsrGroup>();
        
        //先删除该用户所关联的所有用户群记录,并将用户群ID与关系对象保存入哈希表中
        //这是因为执行delete()方法时,未调用flush()方法,故数据库中并未真正删除记录;
        //因此在接下来插入数据时便会报出“对象已存在”之类的异常
        List<UsrGroup> list = usrGroupDao.findByUsrId(HibernateSessionFactory.getSession(), usrId);
        for(int i = 0; i < list.size(); i++){
            usrGroupDao.delete(HibernateSessionFactory.getSession(), list.get(i));
            map.put(list.get(i).getUsrGroupId(), list.get(i));
        }
        
        //再保存被该主题所关联的版块链接
        String[] selectedLinkList = selectedLinkStr.split(",");//这里的selectedLinkStr是管理员为用户所指定的多个用户群ID,ID之间以逗号分隔
        
        for(int i = 0; i < selectedLinkList .length; i++){
            Boolean bool = false;
            long groupId = Long.valueOf(selectedLinkList [i]);
            
            //如果主题关联的链接ID与刚才被删除的关系对象中的链接ID相同,则执行saveOrUpdate()方法
            //这里只能执行这个方法,别的方法都会报出异常
            if (map.containsKey(groupId )) {
                usrGroupDao.save(HibernateSessionFactory.getSession(), map.get(groupId ));
                bool = true;
            }
            
            //如果用户为当前主题关联了之前所未关联的新的版块链接,则new一个关系对象并保持
            if(!bool){
                try{
                    UsrGroup usrGroup= new UsrGroup();
                    usrGroup.setUsrId(topicId);
                    usrGroup.setUsrGroupId(groupId );
                    
                    usrGroupDao.save(HibernateSessionFactory.getSession(), usrGroup);
                } catch(Exception e){
                    e.printStackTrace();
                }
            }
        }

posted @ 2009-06-19 14:48  弹着钢琴设计  阅读(1361)  评论(0编辑  收藏  举报