EclipseLink - 带有条件查询的子查询(JPA)

时间:2017-05-08 11:35:13

标签: java jpa eclipselink

按照给出以下两个表:

  1. ObjectsobjIdobjTaxonId
  2. TaxataxIdtaxValidSynonymIdtaxName(注意Taxa是Taxon的复数形式)
  3. 如果Taxon有效,其id和validSynonymId是相同的,否则它们是不同的。要查找分类的所有同义词,您只能'需要查找taxValidSynonymId填充有效分类单元taxId的所有分类单元

    我怎样才能获得Objects具有给定名称(包括其同义词?)的所有Taxon 在SQL中,这是在几行(和分钟)

    完成的
    SELECT * 
    FROM Objects
    WHERE objTaxonId IN (
        SELECT taxId
        FROM Taxa
        WHERE taxName LIKE 'Test Taxon 1'
            OR taxSynIdTaxon IN(
            SELECT taxId 
            FROM Taxa 
            WHERE taxName LIKE 'Test Taxon 1'
        )
    )
    

    我能够找到内部部分,在那里我获得了Taxa及其同义词列表。现在我需要将此Query转换为Subquery ...

    String NAME_LIKE = "Test Taxon 1";
    EntityManager em = EntityManagerProvider.getEntityManager("TestDB"); // get the EntityManager
    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<TaxonImpl> cqObject = cb.createQuery(TaxonImpl.class);//
    Root<TaxonImpl> taxonRoot = cqObject.from(TaxonImpl.class);//
    Expression<String> taxon_name = taxonRoot.<String> get("taxName");
    Predicate where = cb.equal(taxon_name, NAME_LIKE);
    // subquery
    Subquery<Integer> subQuery = cqObject.subquery(Integer.class);
    Root<TaxonImpl> subRoot = subQuery.from(clsImpl);
    subQuery.select(subRoot.<Integer> get("taxId"));
    subQuery.where(cb.equal(subRoot.<String> get("taxName"), NAME_LIKE));
    where = cb.or(where, taxonRoot.get("taxValidSynonymId").in(subQuery));
    cqObject.where(where);
    Query query = em.createQuery(cqObject);
    List<TaxonImpl> result = query.getResultList();
    

    注意:Taxon被映射为多对一关系(目标实体是TaxonImpl)

    在我的实际应用程序中,代码(来自子查询)将是动态的,因此Native Query对我没有帮助。

1 个答案:

答案 0 :(得分:1)

我想出了如何&#34;转换&#34;将subquery改为query,但Eclipselink向我投掷了两个错误

第一个被禁止通过字段访问,当我尝试使用TaxonImpl的结果时(我首先尝试了,因为我的映射文件中Taxon被映射为Entity

所以在此之后我试图将SQL 1:1形成JPA。 但是Eclipselink产生了一些奇怪的东西:

SELECT t0.objIdObject, t0.objAdminCreated, t0.objAdminCreator, t0.objAdminEdited, t0.objAdminEditor, t0.objAdminImport1, t0.objAdminImport2, t0.objAddBool1, t0.objAddBool2, t0.objAddBool3, t0.objAddBool4, t0.objAddBool5, t0.objAddDateTime1, t0.objAddDateTime2, t0.objCommonComments, t0.objCommonDescription, t0.objCommonKeywords, t0.objCommonName, t0.objCommonPublished, t0.objCommonPublishedAs, t0.objCommonStatus, t0.objCommonType, t0.objCommonTypustype, t0.objDetAccuracy, t0.objDetCf, t0.objDetComments, t0.objDetDate, t0.objDetMethod, t0.objDetResult, t0.objAddFloat1, t0.objAddFloat2, t0.objAddFloat3, t0.objAddFloat4, t0.objAddFloat5, t0.objEventAbundance, t0.objEventCollectionMethod, t0.objEventComments, t0.objEventMoreContacts, t0.objEventDateDay1, t0.objEventDate1, t0.objEventDateMonth1, t0.objEventDate2, t0.objEventDateUncertain, t0.objEventDateYear1, t0.objEventEcosystem, t0.objEventHabitat, t0.objEventNumber, t0.objEventPermission, t0.objEventSubstratum, t0.objEventTime1, t0.objEventTime2, t0.objEventWeekNumber, t0.objFlora, t0.objGuidObject, t0.objIOComments, t0.objIODeAccessed, t0.objAddInt1, t0.objAddInt2, t0.objAddInt3, t0.objAddInt4, t0.objAddInt5, t0.objStorageForeignNumber, t0.objStorageNumber, t0.objStorageNumberInCollection, t0.objStorageNumberOld, t0.objStorageNumberPrefix, t0.objAddLkp1, t0.objAddLkp10, t0.objAddLkp2, t0.objAddLkp3, t0.objAddLkp4, t0.objAddLkp5, t0.objAddLkp6, t0.objAddLkp7, t0.objAddLkp8, t0.objAddLkp9, t0.objAddLkpCs1, t0.objAddLkpCs10, t0.objAddLkpCs11, t0.objAddLkpCs12, t0.objAddLkpCs13, t0.objAddLkpCs14, t0.objAddLkpCs15, t0.objAddLkpCs2, t0.objAddLkpCs3, t0.objAddLkpCs4, t0.objAddLkpCs5, t0.objAddLkpCs6, t0.objAddLkpCs7, t0.objAddLkpCs8, t0.objAddLkpCs9, t0.objOriginAccessionDate, t0.objOriginAccessionNumber, t0.objOriginComments, t0.objOriginMoreContacts, t0.objOriginSource, t0.objOriginType, t0.objPreparationComments, t0.objPreparationDate, t0.objPreparationType, t0.objPropAdults, t0.objPropAge, t0.objPropAgeUnit, t0.objPropEggs, t0.objPropFemale, t0.objPropHeight, t0.objPropHeightUnit, t0.objPropJuveniles, t0.objPropLarvae, t0.objPropLength, t0.objPropLengthUnit, t0.objPropMale, t0.objPropObservation, t0.objPropObservationComments, t0.objPropPupae, t0.objPropSex, t0.objPropStadium, t0.objPropWeight, t0.objPropWeightUnit, t0.objPropWidth, t0.objPropWidthUnit, t0.objSiteComments, t0.objStorageComments, t0.objStorageContainerNumber, t0.objStorageContainerPieces, t0.objStorageContainerType, t0.objStorageLevel1, t0.objStorageLevel2, t0.objStorageLevel3, t0.objStorageLevel4, t0.objStorageLevel5, t0.objStorageNumberInContainer, t0.objstoragePieces, t0.objStorageValue, t0.objStorageValueUnit, t0.objAddText1, t0.objAddText10, t0.objAddText2, t0.objAddText3, t0.objAddText4, t0.objAddText5, t0.objAddText6, t0.objAddText7, t0.objAddText8, t0.objAddText9, t0.objIdCollection, t0.objCommonIdReference, t0.objDetIdContact, t0.objDetIdReference, t0.objEventIdContact, t0.objIdExcursion, t0.objOriginIdContact, t0.objPreparationIdContact, t0.objIdProject, t0.objSiteIdSite, t0.objdetIdTaxon 
FROM tObjects t0 
WHERE t0.objdetIdTaxon IN (
    SELECT t1.taxIdTaxon.t1.taxIdTaxon 
    FROM tTaxa t1 
    WHERE (t1.taxTaxonDisplay LIKE 'Test Taxon 1' 
        OR t1.taxSynIdTaxon IN (
        SELECT t2.taxSynIdTaxon 
        FROM tTaxa t2 
        WHERE t2.taxTaxonDisplay LIKE 'Test Taxon 1')))

取出错误:

SELECT t1.taxIdTaxon.t1.taxIdTaxon 

这是完整的垃圾。你不能在int类型上执行函数!

解决此错误(BUG?)引入了一个新构造(仍然返回相同的结果)

SELECT t1.objIdObject, t1.objAdminCreated, t1.objAdminCreator, t1.objAdminEdited, t1.objAdminEditor, t1.objAdminImport1, t1.objAdminImport2, t1.objAddBool1, t1.objAddBool2, t1.objAddBool3, t1.objAddBool4, t1.objAddBool5, t1.objAddDateTime1, t1.objAddDateTime2, t1.objCommonComments, t1.objCommonDescription, t1.objCommonKeywords, t1.objCommonName, t1.objCommonPublished, t1.objCommonPublishedAs, t1.objCommonStatus, t1.objCommonType, t1.objCommonTypustype, t1.objDetAccuracy, t1.objDetCf, t1.objDetComments, t1.objDetDate, t1.objDetMethod, t1.objDetResult, t1.objAddFloat1, t1.objAddFloat2, t1.objAddFloat3, t1.objAddFloat4, t1.objAddFloat5, t1.objEventAbundance, t1.objEventCollectionMethod, t1.objEventComments, t1.objEventMoreContacts, t1.objEventDateDay1, t1.objEventDate1, t1.objEventDateMonth1, t1.objEventDate2, t1.objEventDateUncertain, t1.objEventDateYear1, t1.objEventEcosystem, t1.objEventHabitat, t1.objEventNumber, t1.objEventPermission, t1.objEventSubstratum, t1.objEventTime1, t1.objEventTime2, t1.objEventWeekNumber, t1.objFlora, t1.objGuidObject, t1.objIOComments, t1.objIODeAccessed, t1.objAddInt1, t1.objAddInt2, t1.objAddInt3, t1.objAddInt4, t1.objAddInt5, t1.objStorageForeignNumber, t1.objStorageNumber, t1.objStorageNumberInCollection, t1.objStorageNumberOld, t1.objStorageNumberPrefix, t1.objAddLkp1, t1.objAddLkp10, t1.objAddLkp2, t1.objAddLkp3, t1.objAddLkp4, t1.objAddLkp5, t1.objAddLkp6, t1.objAddLkp7, t1.objAddLkp8, t1.objAddLkp9, t1.objAddLkpCs1, t1.objAddLkpCs10, t1.objAddLkpCs11, t1.objAddLkpCs12, t1.objAddLkpCs13, t1.objAddLkpCs14, t1.objAddLkpCs15, t1.objAddLkpCs2, t1.objAddLkpCs3, t1.objAddLkpCs4, t1.objAddLkpCs5, t1.objAddLkpCs6, t1.objAddLkpCs7, t1.objAddLkpCs8, t1.objAddLkpCs9, t1.objOriginAccessionDate, t1.objOriginAccessionNumber, t1.objOriginComments, t1.objOriginMoreContacts, t1.objOriginSource, t1.objOriginType, t1.objPreparationComments, t1.objPreparationDate, t1.objPreparationType, t1.objPropAdults, t1.objPropAge, t1.objPropAgeUnit, t1.objPropEggs, t1.objPropFemale, t1.objPropHeight, t1.objPropHeightUnit, t1.objPropJuveniles, t1.objPropLarvae, t1.objPropLength, t1.objPropLengthUnit, t1.objPropMale, t1.objPropObservation, t1.objPropObservationComments, t1.objPropPupae, t1.objPropSex, t1.objPropStadium, t1.objPropWeight, t1.objPropWeightUnit, t1.objPropWidth, t1.objPropWidthUnit, t1.objSiteComments, t1.objStorageComments, t1.objStorageContainerNumber, t1.objStorageContainerPieces, t1.objStorageContainerType, t1.objStorageLevel1, t1.objStorageLevel2, t1.objStorageLevel3, t1.objStorageLevel4, t1.objStorageLevel5, t1.objStorageNumberInContainer, t1.objstoragePieces, t1.objStorageValue, t1.objStorageValueUnit, t1.objAddText1, t1.objAddText10, t1.objAddText2, t1.objAddText3, t1.objAddText4, t1.objAddText5, t1.objAddText6, t1.objAddText7, t1.objAddText8, t1.objAddText9, t1.objIdCollection, t1.objCommonIdReference, t1.objDetIdContact, t1.objDetIdReference, t1.objEventIdContact, t1.objIdExcursion, t1.objOriginIdContact, t1.objPreparationIdContact, t1.objIdProject, t1.objSiteIdSite, t1.objdetIdTaxon 
FROM tTaxa t0, tObjects t1 
WHERE (
    t0.taxIdTaxon IN (
        SELECT t2.taxIdTaxon 
        FROM tTaxa t2 
        WHERE (t2.taxTaxonDisplay LIKE 'Test Taxon 1'
            OR t2.taxSynIdTaxon IN (
            SELECT t3.taxSynIdTaxon 
            FROM tTaxa t3 
            WHERE t3.taxTaxonDisplay LIKE 'Test Taxon 1'
            )
        )
    ) AND (t0.taxIdTaxon = t1.objdetIdTaxon)
)

这对我来说很奇怪,但它有效 - 而且它比我的替代查询更快,其中包括inner join

注意:Eclipselink会忽略JoinType。无论你传递什么,都需要left outer join。 (文件说了别的东西!)

最后,我提供了joinjoinless

的两个示例
private static Predicate addSynonymsWithJoins(Root<BioObjectImpl> r, CriteriaBuilder b, CriteriaQuery cq,
        Attribute attr, Path path, Object value) {
    Join taxJoin = r.join(BioObjectEnum.taxon.name(), JoinType.INNER);

    Path<Object> taxValidSynonymId = taxJoin.get(TaxonEnum.validSynonymId.name());
    Subquery<TaxonImpl> innerSubquery = cq.subquery(TaxonImpl.class);
    Root fromSubTax = innerSubquery.from(TaxonImpl.class);
    innerSubquery.select(fromSubTax.<Integer> get(TaxonEnum.id.name()));
    Predicate dynamic1 = cb.like(fromSubTax.get(TaxonEnum.name.name()),
     NAME_LIKE);
    innerSubquery.where(dynamic1);
    Predicate dynamic2 = resolveComparator(b, attr, taxJoin.get(attr.getPropertyName()), attr.getValue());//
    Predicate p = b.or(taxValidSynonymId.in(innerSubquery), dynamic2);

    return p;
}

private static Predicate addSynonymsWithoutJoins(Root<BioObjectImpl> r, CriteriaBuilder b, CriteriaQuery cq,
        Attribute attr, Path path, Object value) {
    cq.select(r);

    Path<Integer> objTaxonId = r.<Integer> get(BioObjectEnum.taxon.name()).get(TaxonEnum.id.name());

    Subquery<Integer> t2 = cq.subquery(Integer.class);
    Root<TaxonImpl> t2fromTaxon = t2.from(TaxonImpl.class);
    Path<Integer> t2taxId = t2fromTaxon.<Integer> get(TaxonEnum.validSynonymId.name());
    t2.select(t2taxId);
    Predicate t2dynamicWhere = resolveComparator(b, attr, t2fromTaxon.get(attr.getPropertyName()), attr.getValue());
    t2.where(t2dynamicWhere);

    Subquery<Integer> t1 = cq.subquery(Integer.class);
    Root<TaxonImpl> t1fromTaxon = t1.from(TaxonImpl.class);
    Predicate t1dynamicWhere = b.like(fromSubTax.get(TaxonEnum.name.name()),
     NAME_LIKE);
    Path<Integer> t1Select = t1fromTaxon.<Integer> get(TaxonEnum.id.name());

    t1.select(t1Select);
    Path<Integer> t1TaxSynonymId = t1fromTaxon.<Integer> get(TaxonEnum.validSynonymId.name());
    t1dynamicWhere = b.or(t1dynamicWhere, t1TaxSynonymId.in(t2));
    t1.where(t1dynamicWhere);

    Predicate where = objTaxonId.in(t1);
    return where;
}