Java 与 table 相关的实体建模

Java entity modeling with table that relates to several others

我对我的实体的建模方式有疑问。来吧,我在数据库中有一个 table 用于从我的系统保存文档,这个 table 有列 id,fk_id(元素外键),fk_table (实体名称)和 file_name(存储我的文件的名称).

我在这里发布我的问题之前做了很多研究,但我没有找到任何相关的东西,我的实体、用户、患者和医生会是什么?

数据库:

id fk_id fk_table file_name
1 21 user test1.jpg
2 32 doctor test2.pdf
3 61 user test10.pdf
4 100 patient test5.jpg

Class:

public class User{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String firstName;
private String LastName;
// What would a one-to-many relationship look like?
}
public class patient{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String firstName;
private String lastName;
// What would a one-to-many relationship look like?
}

您可以使用 @Where。但请注意 @Where 是一个 Hibernate 注释。它不在 JPA 标准中。

例如在 User 实体中:(我假设您的 table 映射到名为 Document 的实体)

@Where( clause = "fk_table = 'user'")
@JoinColumn(name = "fk_id")
@OneToMany
private List<Document> documents = new ArrayList<>( );

以下仅基于标准 JPA 注释。这个想法是为文档 table 创建一个继承层次结构。基数是:

@Entity
@Table(name = "XX_DOCUMENT")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "fk_table")
public abstract class BaseDocument {
    @Id
    @GeneratedValue(strategy=SEQUENCE)
    private Long id;

    @Column(name = "file_name")
    private String fileName;
}

这里我们定义所有扩展这个的实体都会去同一个table,用fk_table列来区分。扩展它的实体定义如下:

@Entity
@DiscriminatorValue("doctor")
public class DoctorDocument extends BaseDocument {
    @ManyToOne
    @JoinColumn(name = "fk_id")
    private Doctor doctor;
}

@Entity
@DiscriminatorValue("patient")
public class PatientDocument extends BaseDocument {
    @ManyToOne
    @JoinColumn(name = "fk_id")
    private Patient patient;
}

// and so on

有趣的是,我们正在重用列 fk_id 以指向右侧 table。从一个小实验来看,Hibernate 似乎没有问题。为了安全起见,我建议您以另一种方式管理数据库创建。

DoctorPatient等不需要有共同的基础class,例如:

@Entity
@Table(name = "XX_DOCTOR")
public class Doctor {
    @Id
    @GeneratedValue(strategy=SEQUENCE)
    private Long id;

    @OneToMany(mappedBy = "doctor")
    private Collection<DoctorDocument> documents = new ArrayList<>();

    // any doctor-specific fields
}

@Entity
@Table(name = "XX_PATIENT")
public class Patient {
    @Id
    @GeneratedValue(strategy=SEQUENCE)
    private Long id;

    @OneToMany(mappedBy = "patient")
    private Collection<PatientDocument> documents = new ArrayList<>();

    // any patient-specific fields
}

// and so on

您可以从相关集合中阅读(医生,患者,...)的文档。您甚至可以根据任何条件查询 BaseDocument 个实例。

您甚至可以继续使用 Java 代码来做更多有趣的事情。例如。定义接口 HasDocuments:

public interface HasDocuments<D extends BaseDocument> {
    Collection<D> getDocuments();
}

Doctor, Patient, ..., 实现了这个,所以他们都可以以同样的方式对待。