【问题标题】:JPA Table per Class Inheritance with different Id names具有不同 Id 名称的每个类继承的 JPA 表
【发布时间】:2018-06-25 08:14:10
【问题描述】:

我有以下映射:

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Vehicle {
    @Id
    @GeneratedValue
    Long id;
}

@Entity
@Table(name = "car")
@AttributeOverride(name = "id", column = @Column(name = "car_id"))
public class Car extends Vehicle {
}

@Entity
@Table(name = "bus")
@AttributeOverride(name = "id", column = @Column(name = "bus_id"))
public class Bus extends Vehicle {
}

我想要实现的是查询不同的表以检索CarBus 实体。为此,我创建了以下 Spring Data 存储库

public interface VehicleRepository extends CrudRepository<Vehicle, Long> {
}

并尝试像这样使用它:vehicleRepository.findAll();

但是,在这种情况下,我得到了java.sql.SQLSyntaxErrorException: ORA-00904: "KEY": invalid identifier。似乎将@Inheritance@AttributeOverride 一起用于@Id 字段不起作用。

我想指出的是,如果CarBus 实体对@Id 具有相同的映射,它将完美地工作(但情况并非如此:“car_id”和“bus_id”)

另外,我尝试将@Id 字段从Vehicle 类移动到子类,但结果发现每个@Entity 都应该包含一个@Id

我还想提一提的是,我尝试使用 @MappedSuperclass 而不是 @Inheritance,但在这种情况下,我无法使用 abstact Vehicle 类型进行查询。

谁能帮我解决这个问题?

谢谢

【问题讨论】:

  • 由于您已接受以下答案,能否请您在此处更新您的工作解决方案。我遇到了与您提到的完全相同的问题,但是通过阅读下面接受的答案,我无法前进。我一定错过了一些东西,所以请帮助我。谢谢。

标签: java hibernate jpa spring-data-jpa table-per-class


【解决方案1】:

你说,

我想要实现的是查询不同的表以检索 Car 和 Bus 实体。

,但作为首要考虑,您应该评估您是否真的想这样做。想一想:

  • 单表继承策略通常对于您想象执行的整个层次结构查询是最快的。它可以通过单个查询执行整个层次结构和具体实体的操作,无需连接或联合。

  • 单表和联合继承策略确保层次结构中的所有实体都具有不同的键,而表每类策略则不一定如此。

  • 单表和联合继承策略有助于涉及抽象超类的关系;每类表策略不能很好地支持这些。

  • 对每类表策略的支持是可选的。 JPA 提供者不需要支持它,GlassFish 参考实现中的默认提供者实际上并不支持它。因此,不能保证依赖于每类表的应用程序是可移植的。 (您的提供商 Hibernate 确实支持它。)

你接着说,

但是,在这种情况下,我得到了java.sql.SQLSyntaxErrorException: ORA-00904: "KEY": invalid identifier。好像使用@Inheritance@AttributeOverride 一起为@Id 字段不起作用。

@AttributeOverride 仅指定用于覆盖映射超类的属性以及嵌入类的字段和属性。如果@Id 属性出现在这些上下文中,它确实 工作。对于从实体超类继承的持久字段和属性,它没有被指定为工作(尽管它也没有被指定为工作),但请注意它不能在这样的情况下工作具有单表或联合继承策略的属性。

如果@AttributeOverride 确实对您有用,那么这种使用将是不可移植的。另一方面,JPA 没有其他东西可以完成您想要的。一个特定的持久性提供者可能有一个支持它的扩展,但 Hibernate 历史上并没有这样做——从实体超类继承的所有属性都映射为相同的名称。

你也说,

我还想提一提的是,我尝试过使用 @MappedSuperclass 而不是 @Inheritance 但在这种情况下我不是 可以用抽象Vehicle 类型查询。

JPA 不为您的特定需求组合提供解决方案:

  • 将每个具体实体类映射到单独的表中,
  • 在每个实体表中将 ID 命名为不同的列名,并且
  • 支持对抽象超类型的多态查询。

如果您不愿意更改其中的任何一个,那么您将不得不依赖扩展。在这种情况下,你很幸运:Hibernate 支持polymorphic queries,其中多态类型未映射为实体。因此,如果您愿意让您的应用程序显式地依赖于 Hibernate,那么您可能会得到想要的结果。

具体来说,要在 Hibernate 中执行此操作,您将依赖“隐式多态性”。为此,您将避免将超类映射为实体,并且根据您的经验,我猜它也不应该是映射的超类。它可以是一个普通的类,尽管它的属性不会是持久的,或者你可以使用一个接口来代替。如果您的 Vehicle 类具有您想要持久化的属性,那么您可以将其更改为可嵌入类。您还可以注释每个车辆实体以指定隐式多态性,例如:

@Entity
@Polymorphism(type = PolymorphismType.IMPLICIT)
// ...
public class Car implements Vehicle {
    // ...
}

Hibernate 文档声称隐式多态是默认设置,但为了清楚起见,我还是建议应用 @Polymorphism 注释。

【讨论】:

    猜你喜欢
    • 2021-07-27
    • 2011-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-12
    • 1970-01-01
    • 2016-08-06
    相关资源
    最近更新 更多