hibernate和其他ORM框架混合使用的异常情况

来源:互联网 发布:c 语言中cost 编辑:程序博客网 时间:2024/06/05 10:16

版本:hibernate-3.3.1.GA  (http://www.findjar.com/index.x网站提供下载)

org.hibernate.Session session;//query未设置查询缓存,即便如此hibernate还是会利用session级别的缓存。Query query = session.createQuery("from "+XoooPo.class.getName()<span style="white-space:pre"></span>+" a where a.property1Value = 'value1' ");query.list();</span>

上面是一个伪代码,我们一定期望返回结果中,所有的XoooPo对象的属性property1Value都是"value1"。实际上,如果返回的XoooPo实例A如果之前已经被hibernate当前session非lazy加载了、加载时A.property1Value是“value000"、之后并未对对象A做任何修改、之后使用ibatis对数据库中对象A的字段修改成了value1,这个时间再去做上面代码里面的hibernate查询,很遗憾返回结果中包含了对象A,但是对象A的property1Value又真的不是"value1",仍然是"value000"。这就是一种非常异常的情况了。

跟hibernate代码,行走的堆栈如下

Daemon Thread [http-7002-Processor11] (Suspended)SessionImpl.getEntityUsingInterceptor(EntityKey) line: 514QueryLoader(Loader).getRow(ResultSet, Loadable[], EntityKey[], Object, EntityKey, LockMode[], List, SessionImplementor) line: 1216QueryLoader(Loader).getRowFromResultSet(ResultSet, SessionImplementor, QueryParameters, LockMode[], EntityKey, List, EntityKey[], boolean) line: 603QueryLoader(Loader).doQuery(SessionImplementor, QueryParameters, boolean) line: 724QueryLoader(Loader).doQueryAndInitializeNonLazyCollections(SessionImplementor, QueryParameters, boolean) line: 259QueryLoader(Loader).doList(SessionImplementor, QueryParameters) line: 2228QueryLoader(Loader).listIgnoreQueryCache(SessionImplementor, QueryParameters) line: 2125QueryLoader(Loader).list(SessionImplementor, QueryParameters, Set, Type[]) line: 2120QueryLoader.list(SessionImplementor, QueryParameters) line: 401QueryTranslatorImpl.list(SessionImplementor, QueryParameters) line: 361HQLQueryPlan.performList(QueryParameters, SessionImplementor) line: 196SessionImpl.list(String, QueryParameters) line: 1148QueryImpl.list() line: 102


可以看到其中核心的就是2个类org.hibernate.impl.SessionImpl、org.hibernate.loader.hql.QueryLoader。
简单说明:
hibernate使用query.list()时,将会自动执行session.flush()方法, 将sessin中对象脏数据sql发到数据库,
即便如此,
QueryLoader(Loader).doQuery(SessionImplementor, QueryParameters, boolean) line: 724
去数据库中查询返回结果java.sql.ResultSet后,并没有根据结果马上去组装新的java对象,
而是先从java.sql.ResultSet数据库中组装Hibernate配置java类的主键的序列化对象,之后通过
SessionImpl.getEntityUsingInterceptor(EntityKey) line: 514
取得session中的已经加载过的对象实例(hibernate中通过map<key,object>判断主键是否存在,这就是为什么主键如果是复合主键,要重写equals、hashCode的原因)。


总结hibernate跟其他ORM混合使用的不足:
1,如果session中已经加载过一个对象A,之后不通过session去修改数据库中的属性内容,那么下一此hibernate的查询结果如果主键是对象A的主键,
那么hibernate不会将查询结果数据去更新session中对象A,而是直接使用内存中已有的对象A放到返回结果中。

2,如果hibernate对一个hibernate管理对象做了修改,并且使用了save、saveOrUpdate等之类的持久话语句,但是没有触发session.flush(),那么其他ORM框架直接从数据库中的的DML语句都是跟hibernate有着冲突的。



0 0
原创粉丝点击