java - JPA 直接与软 (ID) 参考 - 什么是最好的?
问题描述
我们有一个中等规模的 Java 应用程序,它广泛使用 Hibernate/JPA 将后端的数据存储到 MS SQL Server。我们正在寻找有关使用 JPA“直接”引用或“软”引用的建议。什么是最好的,为什么?
我仍然不擅长正确的 JPA 术语,所以我可能使用了错误的术语,但下面的示例说明了我所指的内容。
// Direct example
@Entity
public class Org {
String name;
}
@Entity
public class Employee {
@ManyToOne
Org org;
@Basic
String nameLast;
}
// Soft example
@Entity
public class Org {
@Basic
String ID;
@Basic
String name;
}
@Entity
public class Employee {
@Basic
String nameLast;
@Basic
String orgID; // Org.ID value
}
我们的代码最初使用了几乎所有的直接引用。这需要花费大量时间来仔细处理在代码的不同部分中更新的引用实体,从而由于意外的实体更改而导致休眠异常。我不记得确切的例外情况。那里有休眠“陈旧实体”异常的痛苦案例。删除其他实体引用的实体时出现问题。
最终,代码库达到了它通常可以工作的程度,但只有在经过广泛的测试和调试之后。虽然代码非常脆弱。当我们添加新的@Entity 类或更改引用时,事情变得非常糟糕。
最终我们受够了并切换到软参考模型。在经历了一些转换的痛苦之后,我们已经达到了一个稳定点。代码更加健壮,我们发现很少有与数据库相关的错误。
软引用(对我们而言)的缺点是:
- 我们有时会有悬空引用。在上面的示例中,如果 Employee 条目的 orgID = "ABC123" 并且 Org "ABC123" 被删除,则不会更新 Employee 条目。对我们来说,这不是很糟糕,只是不理想。
- 我们不能对带有软引用的复杂实体进行排序/连接。如果我们想通过 Criteria 对 Employee 表进行排序,我们不能根据 Org.name 值进行排序。这限制了我们的前端 GUI 对此类复杂实体进行排序的能力。我们在数据库和前端之间使用延迟加载,因此让前端对数据进行排序是不可行的。
我们很想听听那些从事基于 JPA 的大中型应用程序的人的最佳实践和任何建议。
解决方案
如果您遵循 DDD,那么经验法则是在聚合根中使用直接引用,并且每当一个聚合引用另一个聚合时,您称之为软引用。
当然,这是推荐方法的原因是:
- 聚合根对一起更改的域对象进行分组,使用直接引用更容易实现完整性
- 相反,使用“软引用”将聚合根彼此隔离更方便,防止代码“到达”另一个聚合
推荐阅读
- javascript - 如何从另一个页面触发视觉力页面中的事件
- angularjs - Grunt usemin,获取压缩文件的最终路径以允许预加载
- hyperledger-fabric - Hyperledger Fabric:背书与提案响应/交易提案与背书请求
- sql-server - MS SQL JDBC 驱动程序在 Tomcat 9 上使用 JNDI Hikari 创建内存泄漏
- c# - ASP Net Core 属性路由和双正斜杠
- c# - 如何向箭头添加文本?
- java - 正则表达式 - 使用正则表达式检测数据类型
- javascript - Laravel 验证数组迭代
- excel - 在关闭之前检查用户表单是否已使用 save_click 保存
- android - 在根项目 [Jenkins] 中找不到 Android 任务“干净”