我观察到Hibernate的奇怪行为。
我有JPA/JPQL: Fill a collection/map based on related object's collection/map? (prototype-like)
中描述的实体图然后我查询这个模型:
this.em.createQuery("SELECT rel FROM Release rel "
+ " LEFT JOIN FETCH rel.product pr "
+ " LEFT JOIN FETCH pr.customFields "
+ " LEFT JOIN FETCH rel.customFields "
+ (withDeps ? " LEFT JOIN FETCH rel.deps" : "")
+ " WHERE rel.product.name = ?1 AND rel.version = ?2", Release.class)
.setParameter(1, prodName)
.setParameter(2, version)
.getSingleResult();
Hibernate将此转换为两个查询:
select release0_.id as rel, product1_.id as prod, customfiel2_.id as prodCF, customfiel3_.id as relCF,
release0_.product_id as rel_prod, ...
from `release` release0_
left outer join product product1_ on release0_.product_id=product1_.id
left outer join prod_custField customfiel2_ on product1_.id=customfiel2_.product_id
left outer join rel_custField customfiel3_ on release0_.id=customfiel3_.release_id
cross join product product4_
where release0_.product_id=product4_.id and product4_.name='EAP' and release0_.version='6.0.1.GA'
返回
'1','1','3','2','1','4',......
然后
select productcus0_.id as id59_0_, productcus0_.label as label59_0_, productcus0_.name as name59_0_ from prod_custField productcus0_ where productcus0_.id=1;
问题是Hibernate加载了ID为“1”的ProductCustomField,这是一个错误 - 因为没有返回的列引用PCF;有一个ID“1”,对应于ReleaseCustomField。
这是减去不相关文本字段的结果:
{
'rel' : 1,
'prod' : 1,
'prodCF' : 3,
'relCF' : 2,
'rel_prodid' : 1,
'status' : 4,
'prodCFname' : 'jarRpmLic',
'prodCF_prodid' : 1,
'prodCF_id' : 3,
'prodCF_name' : 'jarRpmLic',
'relCF_id' : 1,
'relCF_name' : 'eapCustField1',
'relCF_relid' : 1,
'relCF_val' : 'wdqdwqwdqd',
'relCF_relID' : 1,
'relCF_id' : 2,
'relCF_name' : 'eapCustField1'
}
如您所见,ProductCustomField唯一可用的值是3。
这是一个错误吗?我该如何验证?解决方法是什么?我考虑使用一些特定于Hibernate的@Fetch策略,或部分保护实体并通过另一个DAO调用手动加载其他集合。
堆栈跟踪:
javax.persistence.EntityNotFoundException: Unable to find org.jboss.essc.web.model.ProductCustomField with id 1
at org.hibernate.ejb.Ejb3Configuration$Ejb3EntityNotFoundDelegate.handleEntityNotFound(Ejb3Configuration.java:155)
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:210)
at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:260)
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:148)
at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1079)
at org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:1006)
at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:613)
at org.hibernate.type.EntityType.resolve(EntityType.java:441)
at org.hibernate.engine.internal.TwoPhaseLoad.doInitializeEntity(TwoPhaseLoad.java:168)
at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:134)
at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:999)
at org.hibernate.loader.Loader.doQuery(Loader.java:878)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:293)
at org.hibernate.loader.Loader.doList(Loader.java:2382)
at org.hibernate.loader.Loader.doList(Loader.java:2368)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2198)
at org.hibernate.loader.Loader.list(Loader.java:2193)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:470)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:355)
at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:195)
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1248)
at org.hibernate.internal.QueryImpl.list(QueryImpl.java:101)
at org.hibernate.ejb.QueryImpl.getSingleResult(QueryImpl.java:285)
答案 0 :(得分:0)
原来是由HHH-6361和HHH-7928引起的,我忽略了不一致的数据。 我依靠FK约束会警告我,但特定的约会不见了。
HHH-6361
将分离的实体合并到persistencecontext
后,集合事件可能包含错误的存储快照