英文:
JPA direct vs soft (ID) references - what's best?
问题
我们有一个中等大小的Java应用程序,它广泛地使用Hibernate/JPA将数据存储在后端到MS SQL Server中。我们正在寻求关于使用JPA“直接”引用还是“软”引用的建议。什么是最好的选择以及为什么呢?
我在正确的JPA术语方面仍然不是很好,所以我可能在使用错误的术语,但以下示例说明了我所指的内容。
// 直接引用示例
@Entity
public class Org {
String name;
}
@Entity
public class Employee {
@ManyToOne
Org org;
@Basic
String nameLast;
}
// 软引用示例
@Entity
public class Org {
@Basic
String ID;
@Basic
String name;
}
@Entity
public class Employee {
@Basic
String nameLast;
@Basic
String orgID; // 对应 Org.ID 的值
}
我们的代码最初几乎全部使用了直接引用。在不同代码部分中仔细处理引用实体的更新花费了大量时间,结果因为意外的实体更改导致了Hibernate异常。我记不清楚具体的异常了。在处理过程中出现了痛苦的Hibernate“过时实体”异常。当删除其他实体引用的实体时也会出现问题。
最终,代码库达到了一个通常工作的状态,但只是在经过了大量的测试和调试之后。尽管如此,代码仍然非常脆弱。当我们添加新的@Entity类或更改引用时,情况变得非常糟糕。
最终,我们受够了,并切换到了软引用模型。经过一些转换的痛苦,我们达到了稳定的状态。代码更加健壮,我们很少遇到与数据库相关的错误。
软引用的缺点(对我们来说)包括:
- 我们有时会有悬挂引用。在上面的示例中,如果Employee条目的orgID = “ABC123”,而Org “ABC123” 被删除,则Employee条目不会被更新。对我们来说,这并不是非常严重的问题,但也不是理想的情况。
- 对于具有软引用的复杂实体,我们无法执行排序/连接操作。如果我们想通过Criteria对Employee表进行排序,我们无法基于Org.name的值进行排序。这限制了前端GUI按照这样的复杂实体进行排序的能力。我们在数据库和前端之间使用惰性加载,所以前端对数据进行排序是不可行的。
我们希望听到最佳实践以及那些在中等到大型JPA应用程序上工作的人的建议。
英文:
We have a medium sized Java application which uses Hibernate/JPA extensively to store data in the back-end to MS SQL Server. We are looking for advice on using JPA "direct" references or "soft" references. What's best and why?
I'm still not great at the proper JPA terminology so I probably am using the wrong terms, but the examples below illustrate what I'm referring to.
// 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
}
Our code originally used almost all direct references. This took tremendous amounts of time to carefully handle referenced entities being updated in different parts of the code resulting in hibernate exceptions due to unexpected entity changes. I can't remember the exact exceptions. There where painful cases of hibernate "stale entity" exceptions. There where problems when deleting entities referenced by other entities.
Eventually the code base reached a point where it usually worked, but only after extensive testing and debug. The code was very fragile though. When we added new @Entity classes or changed references, things got ugly fast.
Eventually we had enough and switched to the soft reference model. After some conversion pain we have reached a point of stability. The code is much more robust and we see few db related bugs.
The downside to soft references (for us) are:
- We sometimes have dangling references. In the above example, if an Employee entry has an orgID = "ABC123" and Org "ABC123" is deleted, the Employee entry is not updated. For us this isn't terribly bad, just not ideal.
- We can't do sort/joins on complex entities with soft references. If we want to sort the Employee table via Criteria we can't sort based on the Org.name value. This limits the ability of our frontend GUI to sort on such complex entities. We use lazy-loading between the db and the front-end so its not feasible to have the front-end sort the data.
We would love to hear what the best practices are and any advice from those of you who work on medium to large JPA based applications.
答案1
得分: 1
如果您遵循领域驱动设计(DDD),那么经验法则就是在聚合根内部使用直接引用,而在一个聚合引用另一个聚合时使用您所称的软引用。
这种推荐方法的原因当然是:
- 聚合根将一起变化的领域对象分组在一起,使用直接引用更容易强制保持完整性
- 相反,使用“软引用”将聚合根彼此隔离更加方便,防止代码“越界”到另一个聚合。
英文:
If you follow DDD, then the rule of thumb would be to use direct references within aggregate roots, and what you call soft references whenever one aggregate references another.
The reason why this is the recommended approach is, of course, that:
- Aggregate roots group domain objects that change together, and enforcing integrity is easier with direct references
- Conversely, isolating aggregate roots from one another is more convenient with 'soft references', preventing code from 'reaching over' to another aggregate
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论