处理来自 JPA/DAO 实体的结果中的非 DB 映射字段

Posted

技术标签:

【中文标题】处理来自 JPA/DAO 实体的结果中的非 DB 映射字段【英文标题】:Handling non DB mapped fields in results from JPA/DAO Entity 【发布时间】:2020-04-05 19:35:38 【问题描述】:

目前我们的系统上有 3 种 POJO 对象:

@Entity - DO 数据库对象(将映射对象读写到表)

@Entity - 查看对象(只读映射对象到 SELECT 语句)

模型 - 用于演示目的的非 ORM 对象

在某些情况下,我们需要在服务层中手动获取视图对象并添加/编辑几个字段并发送到演示文稿。 是否可以使用视图对象通过添加映射到虚拟列的虚拟字段('' as dummyField 在选择语句中)来做到这一点。

了解 hibernate/jpa 将尝试在事务上下文结束时刷新对象,这将在未找到表时给出错误。我们可以使用@Transactional (readonly=true) 来解决这个问题。

这样做有什么缺点吗?而不是创建一个全新的模型并用它填充视图?

【问题讨论】:

which will give error on table not found 什么?如果您从表中读取,则该表存在。此外,一旦您离开事务,任何更改都不会自动刷新回数据库。您需要手动调用update() 写回任何更改 XtremeBaumer - 你所说的对于第一组对象是正确的,对象映射到数据库表。 View 对象是映射到 SELECT 语句的 @Entity 对象,这些语句可能具有来自多个表的列和计算的列。在这种情况下,没有物理表。 那么用户不应该有可能编辑这些实体。他们应该只能查看它们 澄清我上面的帖子:“手动添加/编辑”是指服务层中的 java 代码向使用 @Entity 检索的视图对象添加附加信息。不是 UI 端的最终用户。 【参考方案1】:

通过添加映射到虚拟列的虚拟字段(作为 select 语句中的 dummyField)

您根本不需要休眠填充字段,可以不理会sql,只需使用@javax.persistence.Transient注释非持久字段

在事务上下文结束时刷新对象

它会在它认为合适的任何时候刷新,例如在任何其他查询之前以获得一致的结果集

这将在找不到表时给出错误

奇怪。但是我想您并不想认真地使用视图模型来阅读。所以@Transactional (readonly=true) 无论如何都是正确的选择。

这样做有什么缺点吗?而不是创建一个全新的模型

除了软件意识形态的争论,你的意思是?这种方法似乎造成了一些混乱,显然休眠特性从服务层泄漏出来。

但是,如果您在技术层面上做对了,您就可以获得您想要的行为,并节省一些来回映射开销。

【讨论】:

使用@javax.persistence.Transient 似乎是更优雅的解决方案。如果您要将这些对象缓存在 redis 或 ehcache 等二级缓存中,这会导致任何问题吗? 看不出为什么会这样。当然,责任除外。

以上是关于处理来自 JPA/DAO 实体的结果中的非 DB 映射字段的主要内容,如果未能解决你的问题,请参考以下文章

Spring/JTA/JPA DAO 集成测试不回滚?

来自批处理脚本的非模态通知框

如何区分来自非匹配记录的null和来自左连接中的非现有记录的null?

如何在实体框架和函数中处理空值

如何使用 CoreML 处理来自相机的非方形帧?

处理来自服务器的 JSON 数据并添加/更新 CoreData 中的对象