【问题标题】:Hibernate @Formula which return collectionHibernate @Formula 返回集合
【发布时间】:2021-11-25 13:48:26
【问题描述】:

我正在使用旧数据库。在我的示例中,我们检索具有某些特征的产品。在数据库中,我们可以找到多对多关联的产品表、特征表和可连接对象。

我需要的唯一字段是特征的标签。因此,我的 Product 实体将包含一个特征列表,如 String。为了不使我的源代码超载,我不想创建许多实体。让我们看看例子:

@Entity
@Table(name = "product")
public class Product implements Serializable {

    @Id
    @Column(name = "id")
    private Long id;

    // all field of Product entity

    @ElementCollection(targetClass = String.class)
    @Formula(value = "(SELECT characteristic.label FROM a jointable JOIN b characteristic ON jointable.characteristic_id = characteristic.id WHERE jointable.product_id = id)")
    private Set<String> characteristics = new HashSet<>();

    // Getter / setter
}

为了代表我的特点,我尝试使用@Formula@ElementCollection 的关联。如您所见,表的名称(查询中的ab)与我对这些数据的表示不匹配。

但是,当我尝试加载产品时,我收到类似“PRODUCT_CHARACTERISTICS table not found”的错误

这里是hibernate执行的生成的SQL查询:

SELECT product0_.id AS id1_14_0_,
       -- Other fields
       characteri10_.product_id AS product_1_15_1__,
       (SELECT characteristic.label 
          FROM a jointable JOIN b characteristic ON jointable.characteristic_id = characteristic.id 
          WHERE jointable.product_id = id) AS formula6_1__,
FROM product product0_
  -- Other Joins
  LEFT OUTER JOIN product_characteristics characteri10_ ON product0_.cdprd = characteri10_.product_cdprd
WHERE product0_.id = ?;

FROM部分,我们可以重新找到product_characteristics表的调用(数据库中不存在)。

所以,我的主要问题如下:如何将特征列表作为实体属性?我可以用@Formula 达到这个结果吗?


编辑

换句话说,我只想从多对多映射加载一个属性。我找到了an example here,但它只适用于 id(可以在可连接件中找到)

【问题讨论】:

  • 我只是找到一些谈论这个的帖子。一个 no solution 表示需要创建实体 B(在我的示例中)。 Another post 有经过验证的答案,但我没有得到正确的结果。

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


【解决方案1】:

我假设您在这里想要实现的是减少为用例获取的数据量。您可以保持多对多映射不变,因为您将需要 DTO,我认为这是 Blaze-Persistence Entity Views 的完美用例。

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

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

@EntityView(Product.class)
public interface ProductDto {
    @IdMapping
    Long getId();
    String getName();
    @Mapping("characteristics.label")
    Set<String> getCharacteristicLabels();
}

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

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

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

Page<ProductDto> findAll(Pageable pageable);

最好的部分是,它只会获取实际需要的状态!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多