Projection in Hibernate/JPA in Spring Boot to pull data from multiple OneToMany and manyToOne relationships

huangapple go评论81阅读模式
英文:

Projection in Hibernate/JPA in Spring Boot to pull data from multiple OneToMany and manyToOne relationships

问题

我需要创建一个JPA投影,从Entity1中获取所有记录,并包括来自Entity4的记录计数。

以下是映射的四个实体及其关系:

Entity1(ManyToOne)Entity2(OneToMany)Entity3(OneToMany)Entity4

在SQL中,这可以通过一个简单的内联选择语句轻松解决。在JPA投影中,我正在尝试执行以下操作。

@Value("#{target.getEntity2().getEntity3().getEntity4().size()}")
String getEntity4Count();

在上面的代码中,投影位于Entity1上。当我添加Entity4时,它会引发异常。以下代码有效。

@Value("#{target.getEntity2().getEntity3().size()}")
String getEntity3Count();

这甚至是提取此数据的正确方法吗?所有的示例似乎都指向两个实体之间的关系,这对于非常简单的应用程序很有帮助,但是在业务应用程序中的SQL往往非常复杂。

是否有一种通过另一种方法(如JPQL)完成上述操作的方法?对于需要在一组实体上执行的大量复杂SQL,什么是最佳处理方法?

英文:

I need to create a JPA projection that will pull all the records from Entity1 and include a record count from Entity4.

Here are the four entities that are mapped and their relationships:

Entity1 (ManyToOne) Entity2 (OneToMany) Entity3 (OneToMany) Entity4

In SQL, this could easily be solved with a simple inline select statement. In the JPA projection, I am trying to do the following.

@Value("#{target.getEntity2().getEntity3().getEntity4().size()}")
String  getEntity4Count();	

In this code above, the projection is on Entity1. It throws the exceptions when I add in Entity4. The below code works.

@Value("#{target.getEntity2().getEntity3().size()}")
String  getEntity3Count();

Is this even the correct method to pull this data? All the examples seemed to point to relationships between two entities which is great for really simple applications but the SQL in business applications tends to be very complex.

Is there a way to complete the above with another method such as JPQL? What is the best method for handling large numbers of complex SQL that need to be executed about a set of Entities?

答案1

得分: 1

Spring Data Projections并不是为这种类型的映射而设计的,因为它将获取实体并在@Value注解中执行您的“映射”,作为SPEL(Spring表达式语言)代码。我想您可能更喜欢使用更高效的SQL?

这是Blaze-Persistence Entity Views的一个完美用例。

我创建了这个库,以便在JPA模型和自定义接口或抽象类定义的模型之间实现轻松映射,类似于功能强化版的Spring Data Projections。想法是您可以根据自己的喜好定义目标结构(领域模型),并通过JPQL表达式将属性(getter)映射到实体模型。

对于您的用例,使用Blaze-Persistence Entity Views,DTO模型可能如下所示:

@EntityView(Entity1.class)
public interface Entity1Dto {
    @IdMapping
    Long getId();
    @Mapping("COUNT(entity2.entity3.entity4)")
    Long getCount();
}

查询只需将实体视图应用于查询,最简单的方法只是按id查询。

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

Spring Data集成允许您几乎像使用Spring Data Projections一样使用它:https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features

英文:

Spring Data Projections is not really made for this kind of mapping as it will fetch entities and execute your "mappings" in the @Value annotation as SPEL(Spring Expression Language) code. I suppose you would rather like to use more efficient SQL?

This is a perfect use case for 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. 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.

A DTO model for your use case could look like the following with Blaze-Persistence Entity-Views:

@EntityView(Entity1.class)
public interface Entity1Dto {
    @IdMapping
    Long getId();
    @Mapping("COUNT(entity2.entity3.entity4)")
    Long getCount();
}

Querying is a matter of applying the entity view to a query, the simplest being just a query by id.

Entity1Dto a = entityViewManager.find(entityManager, Entity1Dto.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

huangapple
  • 本文由 发表于 2020年9月18日 23:00:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/63958210.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定