【问题标题】:Only return partial list of objects in entity based on query results - spring boot hibernate仅根据查询结果返回实体中的部分对象列表-spring boot hibernate
【发布时间】:2021-02-03 10:05:40
【问题描述】:

我有一个 Event 实体,如下所示。每个事件可能有一个 EventDetails 列表,如下所示。 (为了便于说明,我尽量简化了这些对象)

@Entity(name = "event")
data class Event(

    @Id
    @GeneratedValue
    @Type(type = "uuid-char")
    val id: UUID = UUID.randomUUID(),

    @OneToMany(
        cascade = [CascadeType.ALL],
        orphanRemoval = true
    )
    @JoinColumn(
        name = "event_id",
        nullable = false
    )
    val eventDetails: List<EventDetails>
)
@Entity(name = "event_details")
data class EventDetails(

    @Id
    @GeneratedValue
    @Type(type = "uuid-char")
    val id: UUID = UUID.randomUUID(),

    val type: String
)

我有一个查询,我想返回所有具有特定类型详细信息的事件,但更重要的是,对于每个事件,我只想返回具有所提供类型的详细信息列表 - 在这种情况下,hibernate 返回不是我想要的完整列表。

所以我基本上想根据传递给查询的内容返回事件详细信息的部分列表,但每次都会返回完整的实体列表。这似乎是因为休眠获取与查询匹配的事件,然后根据我设置的内容对所有 EventDetails 进行 Eager / Lazy 获取,而不考虑查询不想返回列表的所有值.

这是突出显示问题的查询 -

@Repository
interface EventRepository : CrudRepository<Event, UUID> {
    @Query(
        """
            select e.* from event e
            join event_details ed on e.id = ed.event_id
            where ed.type in :types
        """, nativeQuery = true
    )
    fun findEventsByDetails(
        @Param("types") types: List<String>
    ): List<AwardEvent>
}

这是一个突出问题的示例。如果我有这样的活动-

Event(eventDetails = listOf(EventDetails(type = "TEST"), EventDetails("OTHER")))

然后我运行以下命令 -

eventRepository.findEventsByDetails(listOf("TEST"))

那么它应该返回一个事件列表 -

Event(eventDetails = listOf(EventDetails(type = "TEST")))

没有包括类型“OTHER_TEST”在内的详细信息

如果有人有任何想法,那将不胜感激

【问题讨论】:

    标签: hibernate spring-data-jpa spring-repositories


    【解决方案1】:

    这就是它的工作原理。在您的特定情况下,该集合是延迟加载的,即您的加入无关紧要。通常,实体总是在映射时反映数据库状态。如果您从集合中过滤掉元素,这可能会导致您可能不想要的元素被删除。解决方案是使用 DTO。

    我认为这是Blaze-Persistence Entity Views 的完美用例。

    我创建了该库以允许在 JPA 模型和自定义接口或抽象类定义模型之间轻松映射,例如 Spring Data Projections on steroids。这个想法是您按照自己喜欢的方式定义目标结构(域模型),并通过 JPQL 表达式将属性(getter)映射到实体模型。

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

    @EntityView(Event.class)
    public interface AwardEvent {
        @IdMapping
        UUID getId();
        String getName();
        @Mapping("eventDetails[type IN :types]")
        Set<EventDetailsDto> getEventDetails();
    
        @EntityView(EventDetails.class)
        interface EventDetailsDto {
            @IdMapping
            UUID getId();
            String getType();
        }
    }
    

    查询是将实体视图应用于查询的问题,最简单的就是通过 id 进行查询。

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

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

    @Repository
    interface EventRepository : CrudRepository<Event, UUID> {
        fun findAllEvents(
            @OptionalParam("types") types: List<String>
        ): List<AwardEvent>
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-24
      • 2013-05-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多