简体   繁体   English

左连接不使用 Hibernate 连接关系

[英]Left join without using Hibernate join relation

Suppose I have one hibernate jpa entity-A:假设我有一个 hibernate jpa 实体-A:

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

Another Enitity-B:另一个实体-B:

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

Here to note that entity A and B don't have implicit relation among them, a_id in B table is handled manually and hence- the relation is like one to many(A-->B) but not the jpa-hibernate relation.这里要注意实体 A 和 B 之间没有隐式关系,B 表中的 a_id 是手动处理的,因此 - 这种关系就像一对多(A--> B)而不是 jpa-hibernate 关系。 And, My FullDto has all the A's properties and List of B:而且,我的 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

}

Now, I want to pull everything(both A and B tables in one go) from repository interface of A like this:现在,我想像这样从 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);
}

But this seems not the way to do this!但这似乎不是这样做的方法!

When I tried this way: I got this error当我尝试这种方式时:我收到了这个错误

WARN ] 2021-08-12 13:20:13.091 [restartedMain] TemplateRenderer - HHH000174: Function template anticipated 4 arguments, but 1 arguments encountered [ERROR] 2021-08-12 13:20:13.123 [restartedMain] ErrorTracker - line 1:51: unexpected token: ) [ERROR] 2021-08-12 13:20:13.123 [restartedMain] ErrorTracker - line 1:51: unexpected token: ) antlr.NoViableAltException: unexpected token: ) at 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] at org.hibernate.hql.internal.antlr.HqlBaseParser.logicalOrExpression(HqlBaseParser.java:2403) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final] at org.hibernate.hql.internal.antlr.HqlBaseParser.expression(HqlBaseParser.java:2116) 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.7.Final.jar:5.3.7.Final] at org.hibernate.hql.internal.antlr.HqlBaseParser.selectedPropertiesList(HqlBaseParser.java:1390) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final] at org.hibernate.hql.internal.antlr.HqlBaseParser.newExpression(HqlBaseParser.java:1434) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final] at org.hibernate.hql.internal.antlr.HqlBaseParser.selectClause(HqlBaseParser.java:1306) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final] at org.hibernate.hql.internal.antlr.HqlBaseParser.selectFrom(HqlBaseParser.java:1040) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final] at org.hibernate.hql.internal.antlr.HqlBaseParser.queryRule(HqlBaseParser.java:748) ~[hibernate-core-5.3.7.Final.8 ~[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] at org.hibernate.hql.internal.antlr.HqlBaseParser.selectStatement(HqlBaseParser.java:319) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final] at org.hibernate.hql.internal.antlr.HqlBaseParser.statement(HqlBaseParser.java:198) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final] at org.hibernate.hql.internal.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:289) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final] at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:188) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final] at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:143) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final] at org.hibernate.engine.query.spi.HQLQueryPlan.(HQLQueryPlan.java:119) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final] at org.8839837993068 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] at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:153) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final] at org.hibernate.internal.AbstractSharedSessionContract.getQueryPlan(AbstractSharedSessionContract.java:595) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final] at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:704) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final] at org.hibernate.internal.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:23) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final] at sun.reflect.GeneratedMethodAccessor88.invoke(Unknown Source) ~[?:?] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_121] at 88213246 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] at org.springframework.data.jpa.repository.query.SimpleJpaQuery.(SimpleJpaQuery.java:63) ~[spring-data-jpa-2.1.4.RELEASE.jar:2.1.4.RELEASE] at org.springframework.data.jpa.repository.query.JpaQueryFactory.fromMethodWithQueryString(JpaQueryFactory.java:76) ~[spring-data-jpa-2.1.4.RELEASE.jar:2.1.4.RELEASE] at org.springframework.data.jpa.repository.query.J 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] at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$DeclaredQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:139) ~[spring-data-jpa-2.1.4.RELEASE.jar:2.1.4.RELEASE] at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateIfNotFoundQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.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] at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.lookupQuery(RepositoryFactorySupport.java:566) ~[spring- 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] at 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] at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) ~[?:1.8.0_121]... 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

How to get all the data without using hibernate oneToMany and ManyToOne relational join?如何在不使用 hibernate oneToMany 和 ManyToOne 关系连接的情况下获取所有数据?

This is not possible as the constructor syntax only allows to pass singular attributes ie there is no such thing as aggregation of records on this level, so you would have to create some kind of IntermediateDto and aggregate this into a FullDto through some custom code like explain by Vlad Mihalcea here: https://vladmihalcea.com/one-to-many-dto-projection-hibernate/这是不可能的,因为构造函数语法只允许传递单一属性,即在这个级别上没有记录聚合这样的东西,所以你必须创建某种IntermediateDto并通过一些自定义代码将其聚合到FullDto中,例如 explain作者:Vlad Mihalcea: https://vladmihalcea.com/one-to-many-dto-projection-hibernate/

I think this is a perfect use case forBlaze-Persistence Entity Views though as it employs a more efficient approach that is easier to use and maintain.我认为这是Blaze-Persistence Entity Views的一个完美用例,因为它采用了更高效的方法,更易于使用和维护。

I created the library to allow easy mapping between JPA models and custom interface or abstract class defined models, something like Spring Data Projections on steroids.我创建了这个库,以允许在 JPA 模型和自定义接口之间轻松映射或抽象 class 定义的模型,类似于类固醇上的 Spring 数据投影。 The idea is that you define your target structure(domain model) the way you like and map attributes(getters) via JPQL expressions to the entity model.这个想法是,您按照自己喜欢的方式定义目标结构(域模型),并通过 JPQL 表达式将 map 属性(getter)定义为实体 model。

A DTO model for your use case could look like the following with Blaze-Persistence Entity-Views:对于您的用例,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();
    }
}

Querying is a matter of applying the entity view to a query, the simplest being just a query by id.查询是将实体视图应用于查询的问题,最简单的就是通过 id 进行查询。

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

The Spring Data integration allows you to use it almost like Spring Data Projections: https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features Spring 数据集成允许您几乎像 Spring 数据投影一样使用它: https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features

Page<FullDto> findAll(Pageable pageable);

The best part is, it will only fetch the state that is actually necessary!最好的部分是,它只会获取实际需要的 state!

FullDto must have a constructor that matches the projection in your query. FullDto 必须具有与查询中的投影相匹配的构造函数。 And you must provide the fully qualified name of FullDto in the query:并且您必须在查询中提供 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);

The DTO projection needs to use an constructor expression to fill-up the DTO. DTO 投影需要使用构造函数表达式来填充 DTO。

Further the DTO class name shall be fully qualified.此外,DTO class 名称应完全合格。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM