遇见的问题
在以下代码中,并没有调用update方法,但是该方法的执行过程中却打印出了一条update语句,并且数据库中的age字段也更新了。并且日志打印中并没有打印出具体是哪个类执行了该条语句。
protected void setupRender() {
super.setupRender();
this.age = 16;
user= (USER) this.xzsjFacade.getBasePO(new USER(user_id));
user.setAge(age );
if (StringUtils.isEmpty(this.filepath)) {
this.filepath = FileUtil.getPathFile() + "/" + this.xzsjFacade.queryForStringByPO("name", new USER(user_id));
}
}
经过排查和询问同事,这是因为hibernate的三种状态导致的,改语句是hibernate自己执行的,所以没有明确打印出具体的类名。说具体的原因之前先了解一下hibernate的三种状态。
Hibernate的三种状态
先看三种状态的图片吧。
完全说明这三种状态比较复杂,这里只针对我遇见的问题来简单的说明一下。首先简单的将临时状态总结为new出来的对象,既没有放到session里也没有存到数据库里的。持久化状态就是已经存到数据库里面的通过hibernate的查询查询出来对象,那么游离状态就是把查询出来的对象又对其进行操作过还没有执行保存方法保存到数据库里的。所以我遇到的问题就是user对象已经变成了游离状态。然后下面又进行了一次查询,hibernate的机制是当查询的po的时候会检查该po的状态,如果处于游离状态会自动将其持久化,保证你查到的数据永远是持久化之后的最新数据。这就是为什么会有一条update语句,并且数据库也已经更新过了。
另外,jdbc并没有此机制,没有执行提交之前,再次查询也永远是数据库中没有更新过的数据。再拿代码分析一下,当执行hibernate的查询获取对象之后,对其进行了修改,然后立刻再对其进行查询,举个例子,hibernate就当做你忘了操作更新,为保持数据最新性自动为你保存。所以在执行数据库操作的时候,不要混合使用jdbc和hibernate,尤其是涉及到插入、更新、删除的操作,有可能会导致事务的不一致。