带有来自本机查询的参数的 Spring 实体动态计算字段
Posted
技术标签:
【中文标题】带有来自本机查询的参数的 Spring 实体动态计算字段【英文标题】:Spring entity dynamically calculated field with parameter from native query 【发布时间】:2018-10-12 08:23:59 【问题描述】:我有一个有点复杂的实体,如下所示(注意具有更多字段的超类):
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.
【问题讨论】:
你好@isADon,我有同样的问题(使用 mysql 代替)。你找到解决办法了吗? 【参考方案1】:由于您需要额外的参数来计算字段,因此您确实不能使用@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 函数调用或服务方法进行计算。
【讨论】:
从 SQL 查询中检索结果集时,我已经使用 PostGIS 函数调用按距离对列表进行了排序。这意味着每个元素的距离已经从数据库中计算出来。我真的很想找到一种方法,让我的 Spring 应用程序不再进行计算,而是直接从数据库中获取值。 如果我理解正确,问题是您需要一个在持久性期间仅是瞬态的字段。在类似的情况下,我制作了一个信封并将我的查询自定义映射到该信封(即将您的距离字段与问题实体分开并将它们包装在具有2个字段的自定义实体类中:一个问题和一个非瞬态“距离”字段) .之后,您可以使用 SqlResultSetMapping 将您的查询映射到该包装器。然后,您就可以单独保存您的 Question 实体。 请看我的编辑。我是否正确理解了您的建议?以上是关于带有来自本机查询的参数的 Spring 实体动态计算字段的主要内容,如果未能解决你的问题,请参考以下文章
Spring Data JPA 将原生查询结果映射到非实体 POJO