Spring实体使用来自本地查询的参数动态计算字段

时间:2018-10-12 08:23:59

标签: spring hibernate jdbc

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

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

我如何将SQL查询结果中的字段distance映射到我的实体字段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.

1 个答案:

答案 0 :(得分:0)

由于需要额外的参数来计算字段,因此您实际上不能使用@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函数调用或服务方法进行计算。