hibernate操作实体引发的惨案

今天接到测试反馈的一个bug,他在系统上点击详情页面的时候,关掉详情页面,然后再点击一次进入详情页面,发现页面中有两个字段的值被更改了。我检查后发现是由于有个新来的同事不够细心引起的bug。代码如下所示

/**
     * add ljk 20160822
     * @return
     * @throws Exception
     */
    public String toView() throws Exception{
        String clueId=request.getParameter("clueId");
        ClueInfo entity = new ClueInfo();
        ClueInfo clueInfo=clueInfoService.findById(clueId); 
        //避免clueInfo执行更新操作
        BeanUtils.copyProperties(clueInfo, entity);
        SystemDictionary ldqk=systemDictionaryService.findById(entity.getLuoDiQingKuang());
        SystemDictionary czqk=systemDictionaryService.findById(entity.getChuzhi_qingkuang());
        if(null!=ldqk){
            entity.setLuoDiQingKuang(ldqk.getInfo());
        }else{
            entity.setLuoDiQingKuang("");
        }
        if(null!=czqk){
            entity.setChuzhi_qingkuang(czqk.getInfo());
        }else{
            entity.setChuzhi_qingkuang("");
        }
        @SuppressWarnings("unchecked")
        List<Map<String,Object>> receiveUserList = clueInfoReceiveUserService.findReceiveUserNameByClueId(clueId);

新来的同事可能不太熟悉hibernate的一些特性,hibernate查询返回实体后,如果不希望对实体执行更新操作,就不应该更改实体里的属性值,否则如果更改实体属性值后,然后接着执行对数据库的任何操作,hibernate都会触发对实体的更新操作。在上面的代码片段中可以看出,实体的两个属性值被更改了: entity.setLuoDiQingKuang(ldqk.getInfo());
entity.setChuzhi_qingkuang(czqk.getInfo());
任何后面又执行了一条查询语句:
clueInfoReceiveUserService.findReceiveUserNameByClueId(clueId);
所以ClueInfo 里面的两个属性值就被更新了。这里新手很容易掉进这个坑里,而且会感到莫名其妙,我以前刚学hibernate的时候也碰到过这种问题,一步一步debug进去发现在执行完某条查询语句之后后台打印出了更新的sql语句。但是明明自己没有调用任何更新的接口。

这里顺便提一下hibernate的get和load的区别:
1、get()和load()都会使用缓存,都是首先从一级缓存Session中查找,当找不到的时候再去二级缓存中查找,当查询不到的时候get()返回的是null,而load()则返回代理对象。

2、get()在调用的时候就立即发出SQL语句查询。

3、load()利用到了延时加载机制,而且返回的是一个代理对象,只有当访问到了代理对象的非ID属性时才会发出SQL语句查询。

4、load()查询不到数据返回的是代理对象,然后当我们使用代理对象qu去访问被代 理对象时由于找不到真实的对象而抛出ObjectNotFoundException异常。
如果在load()在缓存中能找到数据,则返回真实的对象而不是代理对象。

5、load()返回的代理对象依赖产生这个代理对象的那个Session,如果这个Session被关闭后还要访问这个代理对象,会抛出LazyInitializationException异常。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值