首页 > 解决方案 > 带有来自本机查询的参数的 Spring 实体动态计算字段

问题描述

我有一个有点复杂的实体,如下所示(注意具有更多字段的超类):

public class Question extends Entry {

    @OneToMany(orphanRemoval = true, mappedBy = "question")
    @JsonManagedReference
    private List<Answer> answers = new ArrayList<>();

    private Long viewCount = 0L;

    private Category category;

    @OneToMany(mappedBy = "question", fetch = FetchType.LAZY,
            cascade = CascadeType.ALL, orphanRemoval = true)
    private List<QuestionTranslation> translations = new ArrayList<>();

    @Transient
    private double distance;
}

distance从本地查询检索结果集时,应从数据库计算。例如

SELECT q.*, ST_Distance_Sphere(cast(q.location as geometry), ST_MakePoint(cast(?1 as double precision), cast(?2 as double precision))) as distance from question q

我不能@Formula用来注释我的字段distance,因为查询必须带参数。

如何distance将 SQL 查询结果中的字段映射到我的实体字段distance,同时让所有其他映射由 Hibernate 完成?

编辑

根据@gmotux 的建议,我创建了一个包装实体。

@Entity
@SqlResultSetMapping(
        name="MappingQ",
        entities={
                @EntityResult(
                        entityClass = QuestionWithDistance.class,
                        fields={
                                @FieldResult(name="distance",column="distance"),
                                @FieldResult(name="question",column="question")})})
public class QuestionWithDistance{
    @Id
    @GeneratedValue
    private String id;

    @OneToOne
    private Question question;
    private double distance;
}

询问

Query query = entityManager.createNativeQuery("SELECT q.*, 222.22 as distance from question q", "MappingQ");

但它总是失败

org.postgresql.util.PSQLException: The column name id1_15_0_ was not found in this ResultSet.

标签: springhibernatejdbc

解决方案


由于您需要额外的参数来计算字段,因此您确实不能使用@Formula,甚至不能使用 getter 来计算字段。不幸的是,对于您的情况,唯一想到的事情是,假设您正在为 Hibernate 使用基于 EntityManager 的配置,则利用其 @PostLoad 事件侦听器,您可以使用它在实体加载时计算字段值,例如:

public class Question extends Entry {
    @PostLoad
    private void postLoad() {
        this.distance = DistanceCalculator.calculateDistance(Double param1,Double param2);       
        //other calculations
    }
}

这当然只是一种解决方法,这意味着您必须在某处有一个静态方法来执行本机查询。如果可能的话,我建议在您的要求中将“距离”概念从您的 Question 实体中分离出来,并在需要时使用本机 SQL 函数调用或服务方法进行计算。


推荐阅读