返回

JPA/Hibernate 中 `@MappedSuperclass` 对象作为成员的最佳实践

java

在 JPA/Hibernate 中将 @MappedSuperclass 对象作为成员

问题:

在 JPA/Hibernate 中,@MappedSuperclass 允许我们创建父类,其属性可以被子类继承,但它本身不映射到数据库表。有时,我们希望将 @MappedSuperclass 对象作为成员变量,但这可能会带来一些挑战,包括:

  • 无法使用 AttributeConverters
  • InheritanceType.TABLE_PER_CLASS 导致大型 SQL 语句

解决方案:

以下是一些解决这些问题的潜在解决方案:

1. 事件监听器:
在加载实体时使用事件监听器加载引用对象。此方法依赖于 EntityPersister,但可能很复杂,并且不适用于需要频繁加载引用对象的情况。

2. 代理类:
创建一个代理类来加载引用对象。此方法使用 @Embedded 注解,但可能降低性能,并且难以维护。

3. 自定义数据类型:
创建一个自定义数据类型来存储引用对象的类名。这种方法需要大量的编码,并且不符合 JPA 规范。

4. 嵌套映射:
将引用对象作为嵌套映射的一部分进行映射。此方法需要仔细设计数据库模式,但可以提供良好的性能。

推荐方法:嵌套映射

对于大多数情况,我们推荐使用嵌套映射,因为它符合 JPA 规范并提供良好的性能。以下是如何实现它的步骤:

  1. 创建一个 @MappedSuperclass 类来表示父类。
  2. 创建一个 @Entity 类来表示子类。
  3. 在子类中创建一个 @Embedded 字段来存储引用对象。
  4. 在父类中创建一个 @OneToMany 字段来引用子类。

结论:

在 JPA/Hibernate 中将 @MappedSuperclass 对象作为成员变量可能会具有挑战性,但通过使用合适的解决方案,我们可以克服这些挑战。嵌套映射是一种符合 JPA 规范的推荐方法,可提供良好的性能。

常见问题解答:

  1. 什么是 @MappedSuperclass

@MappedSuperclass 允许创建父类,其属性可以被子类继承,但它本身不映射到数据库表。

  1. 为什么我无法在 @MappedSuperclass 上使用 AttributeConverters?

AttributeConverters 需要访问事务来加载更多数据,而这在 @MappedSuperclass 中不可用。

  1. 什么是嵌套映射?

嵌套映射将引用对象作为映射的一部分进行映射。这需要仔细设计数据库模式,但可以提供良好的性能。

  1. 我应该始终使用嵌套映射吗?

嵌套映射并不是在所有情况下都适用。对于需要频繁加载引用对象的情况,事件监听器或代理类可能是更好的选择。

  1. 在何时使用 InheritanceType.TABLE_PER_CLASS

InheritanceType.TABLE_PER_CLASS 用于每个子类创建单独的数据库表。这可以提高性能,但会导致大型 SQL 语句,对于大型数据库来说可能是一个问题。