首页 > 解决方案 > 尝试在 JPA 实体之间实现低耦合

问题描述

我遇到的一个问题是一种使用 JPA / Hibernate 映射一对多关系的好方法,同时又不牺牲 SOLID 原则。这是我正在处理的当前项目中有关此问题的示例:

给定以下定义单向一对多关系的代码:

@Entity
@Table(name = "users")
public class User extends AggregateEntity<User> implements HasRoles, HasContactInfo, HasContacts, HasDeals {

    @OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.LAZY)
    @JoinColumn(name = "fk_hasContacts")
    private Set<Contact> contacts;}

我的理解是,这会在“联系人”表中创建一个“fk_hasContacts”列,而“联系人”类不知道或关心它是从哪个对象引用的。另外,请注意“User”如何实现“hasContacts”接口,这会在两个实体之间产生解耦效果。如果明天我想再增加一堂课;说也有联系人的“BusinessEntity”,在当前代码中没有什么需要改变的。但是,在阅读了该主题后,从数据库性能的角度来看,这种方法似乎效率低下。

映射@OneToMany 关联的最佳方式是依靠@ManyToOne 端来传播所有实体状态更改 - 如此所述。

似乎是流行的智慧。如果我这样设计,“用户”类现在看起来像这样:

@Entity
@Table(name = "users")
public class User extends AggregateEntity<User> implements HasRoles, HasContactInfo, HasContacts, HasDeals {

    @OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
    private Set<Contact> contacts;

并且(以前解耦的)“Contact”类现在必须如下所示:

@Entity
@Table(name = "contacts")
public class Contact extends StandardEntity<Contact> {

    @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinColumn(name = "fk_user")
    private User user;

关键问题是,从这里看来,JPA 不支持将接口定义为实体属性。所以这段代码:

@Entity
@Table(name = "contacts")
public class Contact extends StandardEntity<Contact> {

    @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinColumn(name = "fk_user")
    private HasContacts hasContacts;//some class which implements the "HasUser" interface

不是一个选项。似乎必须在 SOLID OOP 和有效的 ORM 实体之间进行选择。经过大量阅读后,我仍然不知道对数据库性能的影响是否足以证明编写相当于紧耦合、僵化和最终糟糕的代码的合理性。

对于这种看似矛盾的设计原则,是否有任何变通方法/解决方案?

标签: oopjpa

解决方案


推荐阅读