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

标签 java jpa eclipselink

取下面两个表格:

  1. 对象,包含列 objIdobjTaxonId
  2. Taxa 包含列 taxIdtaxValidSynonymIdtaxName(注意 Taxa 是 Taxon 的复数形式)

如果一个Taxon有效,它的id和validSynonymId是相同的,否则它们是不同的。要查找某个分类单元的所有同义词,您“只需”查找 taxValidSynonymId 填充有有效分类单元的 taxId 的所有分类单元

我如何获得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'
    )
)

我能够计算出内部部分,其中我获得了分类单元及其同义词的列表。现在我需要将此查询转换为子查询...

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();

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

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

最佳答案

我想出了如何将子查询“转换”为查询,但Eclipselink给我带来了两个错误

当我尝试输入 TaxonImpl 的结果时,第一个被禁止通过字段访问(我首先尝试过,因为在我的映射文件中 Taxon 被映射作为实体

因此,在此之后,我尝试将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)
)

这对我来说似乎很奇怪,但它正在工作 - 并且它比我的替代查询更快,其中包括内部联接

注意:Eclipselink 会忽略 JoinType。无论您传递什么,它都需要一个左外连接。 (文档另有说明!)

最后我提供了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;
}

关于java - EclipseLink - 带条件查询的子查询 (JPA),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43846627/

相关文章:

java - Eclipselink 更新现有表

jaxb - Eclipselink 和 @XmlRef 的问题

java - 使用tomcat部署后如何调试maven应用程序?

java - OpenSessionInView 与 PersistenceContext(扩展)

java - 在java中比较两个日期的最佳方法

sql - Postgres : get min and max rows count in many to many relation table

java - SELECT 子句中带有子查询的 JPQL/Hibernate 查询

java - JPA多对多持久连接表

java - 从运行的应用程序中恢复Jar

java - 如何向上一页传递参数?