9

我有以下映射:

@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 {
}

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

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

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

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

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

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

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

有人可以帮我吗?

谢谢

4

1 回答 1

5

你说,

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

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

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

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

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

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

你接着说,

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

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

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

你也说,

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

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

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

If you are unwilling to change any of those then you'll have to rely on an extension. And in that case you're in luck: Hibernate supports polymorphic queries where the polymorphic type is not mapped as an entity. Thus, if you're willing to make your application explicitly dependent on Hibernate, you can probably get where you want to be.

Specifically, to do this in Hibernate you would rely on "implicit polymorphism". To do this, you would avoid mapping the superclass as an entity, and from your experience, I guess it should not be a mapped superclass, either. It can be an ordinary class, though its properties would not be persistent, or you could use an interface instead. If your Vehicle class has properties that you want to make persistent, then you could change it to an embeddable class. You would furthermore annotate each of the vehicle entities to specify implicit polymorphism, for example:

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

The Hibernate docs claim that implicit polymorphism is the default, but I recommend applying the @Polymorphism annotation anyway, for clarity.

于 2018-01-16T16:58:29.180 回答