深入解析 JPA Joined Subclass 继承策略的实现与应用

在 Java 持久化领域,JPA(Java Persistence API)提供了多种强大的功能来帮助开发者高效地管理数据库操作。其中,继承策略是 JPA 中一个非常重要的概念,它允许我们将类的继承关系映射到数据库表结构中。今天,我们就来深入探讨一下 JPA 中的 Joined Subclass 继承策略,并通过一个完整的实例来展示它的实现和应用。
一、Joined Subclass 继承策略概述
Joined Subclass 继承策略是一种将类继承层次结构中的每个类都映射到单独的数据库表中的策略。具体来说,父类和子类分别对应不同的表,子类表中不包含父类的字段,除了作为主键的 @Id 字段。子类表的主键列同时作为外键,指向父类表的主键列。这种策略通过注解 @Inheritance(strategy = InheritanceType.JOINED) 在根实体类上指定。
二、关键注解及其作用
@Inheritance
用于指定继承策略,必须在继承层次结构的根实体类上使用。
在 Joined Subclass 策略中,strategy 属性被设置为 InheritanceType.JOINED。
@DiscriminatorColumn
用于定义区分不同子类的字段(判别器列)。
在根实体类上指定,用于存储表示子类类型的值。
@DiscriminatorValue
用于为每个具体的子类指定一个唯一的判别器值。
如果未指定,JPA 提供者会根据子类的类名生成默认值。
三、实例演示
为了更好地理解 Joined Subclass 继承策略,我们通过一个简单的员工管理系统来展示其应用。在这个系统中,我们定义了一个 Employee 父类和两个子类:FullTimeEmployee 和 PartTimeEmployee。

  1. 实体类定义
    java复制
    @Entity
    @Inheritance(strategy = InheritanceType.JOINED)
    @DiscriminatorColumn(name = “EMP_TYPE”)
    public class Employee {
    @Id
    @GeneratedValue
    private long id;
    private String name;

    // 省略 getter 和 setter 方法
    }

@Entity
@DiscriminatorValue(“F”)
@Table(name = “FULL_TIME_EMP”)
public class FullTimeEmployee extends Employee {
private int salary;

// 省略 getter 和 setter 方法

}

@Entity
@DiscriminatorValue(“P”)
@Table(name = “PART_TIME_EMP”)
public class PartTimeEmployee extends Employee {
private int hourlyRate;

// 省略 getter 和 setter 方法

}
2. 数据库表结构
在 Joined Subclass 策略下,JPA 会为每个实体类生成一个独立的表。具体表结构如下:
EMPLOYEE 表
EMP_TYPE: VARCHAR(31)(判别器列)
ID: BIGINT(主键)
NAME: VARCHAR(255)
FULL_TIME_EMP 表
SALARY: INTEGER
ID: BIGINT(主键,同时作为外键指向 EMPLOYEE 表的 ID)
PART_TIME_EMP 表
HOURLYRATE: INTEGER
ID: BIGINT(主键,同时作为外键指向 EMPLOYEE 表的 ID)
3. 数据持久化与查询
接下来,我们通过一个简单的示例程序来演示如何持久化和查询数据。
java复制
public class ExampleMain {
public static void main(String[] args) throws Exception {
EntityManagerFactory emf =
Persistence.createEntityManagerFactory(“example-unit”);
try {
persistEntities(emf);
runNativeQueries(emf);
loadEntities(emf);
} finally {
emf.close();
}
}

private static void persistEntities(EntityManagerFactory emf) throws Exception {
    System.out.println("-- Persisting entities --");
    EntityManager em = emf.createEntityManager();
    FullTimeEmployee e1 = new FullTimeEmployee();
    e1.setName("Sara");
    e1.setSalary(100000);
    System.out.println(e1);

    PartTimeEmployee e2 = new PartTimeEmployee();
    e2.setName("Robert");
    e2.setHourlyRate(60);
    System.out.println(e2);

    em.getTransaction().begin();
    em.persist(e1);
    em.persist(e2);
    em.getTransaction().commit();
    em.close();
}

private static void runNativeQueries(EntityManagerFactory emf) {
    System.out.println("-- Native queries --");
    EntityManager em = emf.createEntityManager();
    nativeQuery(em, "SELECT * FROM Employee");
    nativeQuery(em, "SELECT * FROM FULL_TIME_EMP");
    nativeQuery(em, "SELECT * FROM PART_TIME_EMP");
}

private static void loadEntities(EntityManagerFactory emf) {
    System.out.println("-- Loading entities --");
    EntityManager em = emf.createEntityManager();
    List entityAList = em.createQuery("SELECT t FROM Employee t")
                                   .getResultList();
    entityAList.forEach(System.out::println);
    em.close();
}

private static void nativeQuery(EntityManager em, String sql) {
    List results = em.createNativeQuery(sql).getResultList();
    results.forEach(System.out::println);
}

}
4. 输出结果
运行程序后,我们得到了以下输出结果:
复制
– Persisting entities –
FullTimeEmployee{id=0, name=‘Sara’, salary=100000}
PartTimeEmployee{id=0, name=‘Robert’, hourlyRate=‘60’}
– Native queries –
SELECT * FROM Employee
[F, 1, Sara]
[P, 2, Robert]
SELECT * FROM FULL_TIME_EMP
[100000, 1]
SELECT * FROM PART_TIME_EMP
[60, 2]
– Loading entities –
FullTimeEmployee{id=1, name=‘Sara’, salary=100000}
PartTimeEmployee{id=2, name=‘Robert’, hourlyRate=‘60’}
四、总结
通过上述示例,我们可以看到 Joined Subclass 继承策略在 JPA 中的实现和应用。它通过将父类和子类分别映射到不同的表中,避免了字段冗余,同时保持了数据的完整性。然而,这种策略也有其缺点,例如在深度继承层次结构中可能导致查询性能下降。因此,在实际开发中,我们需要根据具体需求选择合适的继承策略。
希望这篇文章能帮助你更好地理解和应用 JPA 的 Joined Subclass 继承策略。如果你有任何问题或建议,欢迎在评论区留言讨论!

你可能感兴趣的:(数据库,java,oracle,个人开发)