0

Hibernate の奇妙な動作を観察します。

JPA/JPQL: Fill a collection/map based on related object's collection/map?で説明されているエンティティ グラフがあります。(プロトタイプのような)

次に、このモデルにクエリを実行します。

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 はこれを 2 つのクエリに変換します。

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 を参照していないためです。ReleaseCustomField に対応する ID「1」が 1 つあります。

無関係なテキスト フィールドを除いた結果は次のとおりです。

{
    '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)
4

1 に答える 1

0

HHH-6361 と HHH-7928 が原因であることが判明し、矛盾したデータを見落としていました。FK 制約が警告してくれると信じていましたが、特定の制約がありませんでした。

HHH-6361

デタッチされたエンティティを永続化コンテキストにマージした後、コレクション イベントに間違った保存されたスナップショットが含まれる場合がある

于 2013-03-22T09:40:47.263 に答える