我继承了一个使用Hibernate的应用程序,这是我之前从未使用过的。这个应用程序中的“标准”编码实践(这些人在很多方面都是可怕的程序员)是为每个查询/更新创建一个会话,执行查询/更新,然后刷新()和关闭()会话。直到现在我都没有这个问题,但现在我。情况是这样的:
2是新片段 - 之前的代码保存了一些单独的UserObject属性值,或者在用户点击某些内容后的每个操作中每次查询数据库。但是现在我将UserObject存储/保存在内存中,此表/对象上的其他查询会导致数据库挂起Hibernate在查询后的flush()期间执行的更新失败。为什么在简单查询对象时Hibernate会执行数据库更新?
我知道我是一名老派程序员,数据库事务很小(开放,读/写,提交/关闭),并且从未在内部进行过用户交互,因为这会升级行,表和表空间锁。所以也许我不了解Hibernate持久性如何工作以及如何编码。查询后是否应该使用flush()?每个用户webapp登录会话应该只有一个“会话”对象吗? Hibernate持久性是否应该消除实际编码'更新'的原因,因为它会自动发生在封面下?这意味着编码模型是查询hibernate / db / Java对象,让用户修改字段,是否有更新Java对象的代码,然后一个flush()+ commit()方法调用更新数据库中的所有内容?
**更新**
以下是我继承的代码示例。每个数据库对象的代码中都有100多个这样的方法。
public static List<BeanObject> GetObjectList() {
List<BeanObjec> list = null;
Session session = factory.openSession();
try {
list = (List<BeanObject>) session.createQuery("from BeanObject").list();
} catch (Exception e) {
// System.out.println("========="+e.getMessage());
} finally {
session.flush();
session.close();
}
return clist;
}
直到最近,当我试图“抓住”其中一个返回的对象时,这已经好几个月了。一旦将该单个对象保存在web-session-memeory中,对该方法的另一次调用就会使.list()调用创建3个对象,这很好,但是flush()调用会为所有3个对象创建SQL UPDATES!为什么hibernate UPDATING一个未被修改的对象?
答案 0 :(得分:1)
默认情况下,flush
之前的commit
是多余的,因为它无论如何都会发生;
默认情况下,Hibernate不会SELECT FOR UPDATE
;
你是对的,单个Hibernate会话应该跨越整个请求处理。但是,从每个请求的单个事务的业务级语义来看,这应该是显而易见的。其他任何事情都会非常不寻常,但所有交易都会在同一个会话中进行,最接近一个租用的数据库连接(尽管不是100%)。
答案 1 :(得分:0)
要了解Hibernate持久性模型,您需要将您的思维方式从手动DML语句更改为entity state transitions。
Hibernate将所有实体状态转换排队,仅归propagate them during a Session flush。在HQL / JPQL和Criteria查询执行之前,AUTO刷新将刷新,但它might not trigger a flush for native SQL queries。
默认的flush-before-query很有用,因为SQL查询应针对当前运行的事务期间发出的最新更改运行。在本机查询之前,您可能只需要手动刷新,但对于实体查询,如果您坚持使用默认的AUTO刷新模式,Hibernate应该处理它。