具有不同Id名称的每类继承的JPA表

时间:2018-01-16 15:10:09

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

我有以下映射:

@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用于Car字段似乎不起作用。

我想指出的是,如果Bus@Id实体对@Id具有相同的映射,那么它将完美地运作(但它不是案例:&#34; car_id&#34;和&#34; bus_id&#34;)

此外,我已尝试将Vehicle字段从@Entity类移至子类,但事实证明每个@Id应包含@MappedSuperclass。< / p>

我要提及的另一件事是,我尝试使用@Inheritance代替abstact Vehicle,但在这种情况下,我无法使用{查询{ {1}}输入。

有人可以帮我吗?

由于

1 个答案:

答案 0 :(得分:3)

你说,

  

我想要实现的是查询不同的表以检索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中执行此操作,您将依赖于&#34;隐式多态性&#34;。要做到这一点,你应该避免将超类映射为一个实体,根据你的经验,我猜它也不应该是一个映射的超类。它可以是一个普通的类,虽然它的属性不会持久,或者你可以使用一个接口。如果您的Vehicle类具有要保持持久性的属性,则可以将其更改为可嵌入类。您还需要注释每个车辆实体以指定隐式多态性,例如:

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

Hibernate文档声称隐式多态是默认值,但为了清楚起见,我建议无论如何应用@Polymorphism注释。