簡體   English   中英

左連接不使用 Hibernate 連接關系

[英]Left join without using Hibernate join relation

假設我有一個 hibernate jpa 實體-A:

public class A{
   id ,//pk
   name,
   age
   //getters and setters
}

另一個實體-B:

public class B{
   id, //pk
   a_id, //pk id of A
   degree,
   institute
   //getters and setters
}

這里要注意實體 A 和 B 之間沒有隱式關系,B 表中的 a_id 是手動處理的,因此 - 這種關系就像一對多(A--> B)而不是 jpa-hibernate 關系。 而且,我的 FullDto 具有 A 的所有屬性和 B 的列表:

public class FullDto{
      id ,//pk
      name,
      age,
     List<B> bList;

    public class FullDto(id, age, name, bList)
     {
        this.id.id;
        this.age=age;
        this.name=name;
        this.bList=bList;
     }
    //getters and setters

}

現在,我想像這樣從 A 的存儲庫界面中提取所有內容(一次性包括 A 和 B 表):

public interface ARepository extends JpaRepository<A, Long> {
@Query("select " +
            "new packageName.FullDto(a.id, a.name, a.age, b) " +
            "from" +
            "   A a " +
            " left join B  b "+
            " on a.id=b.a_id "+
            "where " +
            "   a.id=:id ")
      FullDto getFullDetails(@Param("id") Long id);
}

但這似乎不是這樣做的方法!

當我嘗試這種方式時:我收到了這個錯誤

WARN] 2021-08-12 13:20:13.091 [restartedMain] TemplateRenderer - HHH000174: Function 模板預計 4 arguments,但遇到 1 arguments [錯誤] 2021-08-12 13:13:13:20 錯誤] 2021-08-12 13:120 51:意外令牌:)[錯誤] 2021-08-12 13:20:13.123 [restartedMain] ErrorTracker - 第 1:51 行:意外令牌:)antlr.NoViableAltException:意外令牌:)在 org.hibernate.hql.internal。 antlr.HqlBaseParser.negatedExpression(HqlBaseParser.java:2534) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final] at org.hibernate.hql.internal.antlr.HqlBaseParser.logicalAndExpression(HqlBaseParser.java :2438) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final] 在 org.hibernate.hql.internal.antlr.HqlBaseParser.logicalOrExpression(HqlBaseParser.java:2403) ~[hibernate-core 5.3.7.Final.jar:5.3.7.Final] 在 org.hibernate.hql.internal.antlr.HqlBaseParser.expression(HqlBaseParser.java:2116) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final] at org.hibernate.hql.internal.antlr.HqlBaseParser.aliasedExpression(HqlBaseParser.java:2357)~[hibernate-core-5.3. .Final.jar:5.3.7.Final] 在 org.hibernate.hql.internal.antlr.HqlBaseParser.selectedPropertiesList(HqlBaseParser.java:1390) ~[hibernate-core-5.3.7.Final.892030878:892030878 Final] 在 org.hibernate.hql.internal.antlr.HqlBaseParser.newExpression(HqlBaseParser.java:1434) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final] 在 org.883hql.5.3.7.Final] internal.antlr.HqlBaseParser.selectClause(HqlBaseParser.java:1306) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final] 在 org.hibernate.hql.internal.antlr.HqlBaseParser.HqlBaseParser( .java:1040) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final] 在 org.hibernate.hql.internal.antlr.HqlBaseParser.queryRule(HqlBaseParser.8821324:7488)8核心-5.3.7.Final.8 8202878901088:5.3.7.Final] 在 org.hibernate.hql.internal.antlr.HqlBaseParser.selectStatement(HqlBaseParser.java:319) ~[hibernate-core-5.3.7.Final.88202878903.1087.8:5] org.hibernate.hql.internal.antlr.HqlBaseParser.statement(HqlBaseParser.java:198) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final] 在org.8839837.hastql.688 .QueryTranslatorImpl.parse(QueryTranslatorImpl.java:289)~[hibernate-core-5.3.7.Final.jar:5.3.7.Final] 在 org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.848421 188) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final] 在 org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:143) ~[hibernate-core-5.3 .7.Final.jar:5.3.7.Final] 在 org.hibernate.engine.query.spi.HQLQueryPlan.(HQLQueryPlan.java:119) ~[hibernate-core-5.3.7.Final.88202878901087:5.3.3.878 .Final] 在 org.8839837993068 8.engine.query.spi.HQLQueryPlan.(HQLQueryPlan.java:80) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final] 在 org.hibernate.engine.query.spi.QueryPlanCache。 gethqlqueryplan(QueryPlancache.java:153) -5.3.7.Final.jar:5.3.7.Final] 在 org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:704) ~[hibernate-core-5.3.7.Final.892020878:882020878 Final] 在 org.hibernate.internal.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:23) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final] 在 sun.reflect.GeneratedMethodAccessor88.invo(Unknown Source.invo ) ~[?:?] 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_121] 在 88213246 945888.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_121] at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:350) ~[spring-orm-5.1 .4.RELEASE.jar:5.1.4.RELEASE] at com.sun.proxy.$Proxy155.createQuery(Unknown Source) ~[?:?] at org.springframework.data.jpa.repository.query.SimpleJpaQuery.validateQuery (SimpleJpaQuery.java:87) ~[spring-data-jpa-2.1.4.RELEASE.jar:2.1.4.RELEASE] 在 org.springframework.data.jpa.repository.query.SimpleJpaQuery.(SimpleJpaQuery.88213288:96458 ) ~[spring-data-jpa-2.1.4.RELEASE.jar:2.1.4.RELEASE] 在 org.springframework.data.jpa.repository.query.JpaQueryFactory.fromMethodWithQueryString(JpaQueryFactory.java:76) ~[spring- data-jpa-2.1.4.RELEASE.jar:2.1.4.RELEASE] 在 org.springframework.data.jpa.repository.query.J paQueryFactory.fromQueryAnnotation(JpaQueryFactory.java:56) ~[spring-data-jpa-2.1.4.RELEASE.jar:2.1.4.RELEASE] 在 org.springframework.data.jpa.repository.query.JpaQueryLookup.LL QueryStrategyQueryStrategy$Declared (JpaQueryLookupStrategy.java:139) ~[spring-data-jpa-2.1.4.RELEASE.jar:2.1.4.RELEASE] 在 org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateIfNotStrategyQueryLogyLookup java:206) ~[spring-data-jpa-2.1.4.RELEASE.jar:2.1.4.RELEASE] at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$AbstractQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:79 ) ~[spring-data-jpa-2.1.4.RELEASE.jar:2.1.4.RELEASE] 在 org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.lookupQuery(RepositoryFactorySupport.java:566) ~[春天- data-commons-2.1.4.RELEASE.jar:2.1.4.RELEASE] 在 org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.lambda$mapMethodsToQuery$1(RepositoryFactorySupport.java:559)~[spring- data-commons-2.1.4.RELEASE.jar:2.1.4.RELEASE] 在 java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)~[?:1.18].0_1218

如何在不使用 hibernate oneToMany 和 ManyToOne 關系連接的情況下獲取所有數據?

這是不可能的,因為構造函數語法只允許傳遞單一屬性,即在這個級別上沒有記錄聚合這樣的東西,所以你必須創建某種IntermediateDto並通過一些自定義代碼將其聚合到FullDto中,例如 explain作者:Vlad Mihalcea: https://vladmihalcea.com/one-to-many-dto-projection-hibernate/

我認為這是Blaze-Persistence Entity Views的一個完美用例,因為它采用了更高效的方法,更易於使用和維護。

我創建了這個庫,以允許在 JPA 模型和自定義接口之間輕松映射或抽象 class 定義的模型,類似於類固醇上的 Spring 數據投影。 這個想法是,您按照自己喜歡的方式定義目標結構(域模型),並通過 JPQL 表達式將 map 屬性(getter)定義為實體 model。

對於您的用例,DTO model 對於 Blaze-Persistence 實體視圖可能如下所示:

@EntityView(A.class)
public interface FullDto {
    @IdMapping
    Long getId();
    String getName();
    Long getAge();
    @Mapping("B[aId = VIEW(id)]")
    Set<BDto> getBList();

    @EntityView(B.class)
    interface BDto {
        @IdMapping
        Long getId();
        String getName();
    }
}

查詢是將實體視圖應用於查詢的問題,最簡單的就是通過 id 進行查詢。

FullDto a = entityViewManager.find(entityManager, FullDto.class, id);

Spring 數據集成允許您幾乎像 Spring 數據投影一樣使用它: https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features

Page<FullDto> findAll(Pageable pageable);

最好的部分是,它只會獲取實際需要的 state!

FullDto 必須具有與查詢中的投影相匹配的構造函數。 並且您必須在查詢中提供 FullDto 的完全限定名稱:

 @Query("select " +
        "   new packagename.FullDto(a.id, a.name, a.age)" +
        " from A a " +
        " left join B b on a.id = b.a_id "+
        " where a.id=:id ")
  FullDto getFullDetails(@Param("id") Long id);

DTO 投影需要使用構造函數表達式來填充 DTO。

此外,DTO class 名稱應完全合格。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM