java - 不使用 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 关系。 而且,My 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);
}
但这似乎不是这样做的方法!
当我尝试这种方式时:我收到了这个错误
警告] 2021-08-12 13:20:13.091 [restartedMain] TemplateRenderer - HHH000174:函数模板预期有 4 个参数,但遇到 1 个参数 [错误] 2021-08-12 13:20:13.123 [restartedMain] ErrorTracker - 第 1 行: 51:意外令牌:)[ERROR] 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] at 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] 在 org.hibernate.hql.internal.antlr.HqlBaseParser.newExpression(HqlBaseParser.java:1434) ~[hibernate-core-5.3.7.Final.jar:5.3.7 .Final] 在 org.hibernate.hql.internal.antlr.HqlBaseParser.selectClause(HqlBaseParser.java:1306) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final] 在 org.hibernate.hql .internal.antlr.HqlBaseParser.selectFrom(HqlBaseParser.java:1040) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final] 在 org.hibernate.hql.internal.antlr.HqlBaseParser。queryRule(HqlBaseParser.java:748) ~[hibernate-core-5.3.7.Final.jar: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] 在 org.hibernate.hql.internal.antlr.HqlBaseParser.statement(HqlBaseParser.java:198) ~[hibernate-core-5.3.7. Final.jar:5.3.7.Final] 在 org.hibernate.hql.internal.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:289) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final ] 在 org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java: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] at org.hibernate.engine.query.spi.HQLQueryPlan.(HQLQueryPlan.java :119) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final] at org.hibernate.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) ~[hibernate-core-5.3.7.Final.jar:5.3.7 .Final] 在 org.hibernate.internal.AbstractSharedSessionContract.getQueryPlan(AbstractSharedSessionContract.java:595) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final] 在 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] 在 sun.reflect.GeneratedMethodAccessor88.invoke(Unknown Source) ~[?:?] 在 sun.reflect。DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_121] at java.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.java:63) ~[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.JpaQueryFactory.fromQueryAnnotation(JpaQueryFactory.java:56) ~[spring-data-jpa-2.1.4.RELEASE.jar :2.1.4.RELEASE] 在 org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$DeclaredQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:139) ~[spring-data-jpa-2.1.4.RELEASE.jar:2.1. 4.RELEASE] 在 org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateIfNotFoundQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:206) ~[spring-data-jpa-2.1.4.RELEASE.jar:2.1.4.RELEASE ] 在 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) ~[spring-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]...发布] 在 java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) ~[?:1.8.0_121]...发布] 在 java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) ~[?:1.8.0_121]...
如何在不使用休眠 oneToMany 和 ManyToOne 关系连接的情况下获取所有数据?
解决方案
这是不可能的,因为构造函数语法只允许传递单数属性,即在此级别上没有记录聚合之类的东西,因此您必须创建某种类型IntermediateDto
并将其聚合到一个FullDto
自定义代码中,例如 Vlad 的解释米哈尔恰在这里:https ://vladmihalcea.com/one-to-many-dto-projection-hibernate/
我认为这是Blaze-Persistence Entity Views的完美用例,因为它采用了更有效的方法,更易于使用和维护。
我创建了该库以允许在 JPA 模型和自定义接口或抽象类定义模型之间轻松映射,例如 Spring Data Projections on steroids。这个想法是您以您喜欢的方式定义您的目标结构(域模型),并通过 JPQL 表达式将属性(getter)映射到实体模型。
使用 Blaze-Persistence Entity-Views 的用例的 DTO 模型可能如下所示:
@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 Data 集成允许您几乎像 Spring Data Projections 一样使用它:https ://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features
Page<FullDto> findAll(Pageable pageable);
最好的部分是,它只会获取实际需要的状态!
推荐阅读
- javascript - “字符串”类型上不存在 Typescript 属性“标签”
- aws-lambda - 如何在 CodeBuild 中为 Lambda 函数添加 Python 库依赖项
- java - Spring Boot JPA 获取列表并向其中添加项目会引发错误
- spotfire - TIBCO Spotfire:错误消息:无法在 Spotfire.Dxp.Data 创建 DataTable ImportException:无法创建 DataTable(HRESULT:80131500)
- c# - CSVHelper - 将名称从 CSV 导入具有相同名称属性的对象
- python - 如何从不同的文件调用方法而不在python中导入它
- python - 通过循环的 kafka 消费者获取消息和手动调用 poll 有什么区别?
- java - 绘制/绘制数学函数时 drawPolyLine() 与 drawLine()
- angular - 在 Angular Web App 中添加数据连接器列表,就像 Power BI 中的“获取数据”一样
- java - 如何从地图中获取偶数值,然后将值键添加到列表中?