JPA Table 每个 Class 具有不同 Id 名称的继承
JPA Table per Class Inheritance with different Id names
我有以下映射:
@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 数据存储库
public interface VehicleRepository extends CrudRepository<Vehicle, Long> {
}
并尝试像这样使用它:vehicleRepository.findAll();
然而,在这种情况下,我得到 java.sql.SQLSyntaxErrorException: ORA-00904: "KEY": invalid identifier
。似乎将 @Inheritance
与 @AttributeOverride
一起用于 @Id
字段不起作用。
我想指出的是,如果 Car
和 Bus
实体对 @Id
具有相同的映射,它将完美地工作(但事实并非如此:"car_id" 和 "bus_id")
此外,我尝试将 @Id
字段从 Vehicle
class 移动到 subclasses,但结果是每个 @Entity
应该包含 @Id
.
我想提的另一件事是我尝试使用 @MappedSuperclass
而不是 @Inheritance
但在这种情况下我无法使用 abstact Vehicle
进行查询类型。
有人可以帮我吗?
谢谢
你说,
And what I'm trying to achieve is to query different tables for retrieving both Car and Bus entities.
,但作为第一个考虑,你应该评估你是否真的想这样做。想想这个:
单table 继承策略对于您想象的整个层次结构查询通常是最快的。它可以通过单个查询执行整个层次结构和具体实体操作,无需连接或联合。
单table和联合继承策略确保层次结构中的所有实体都有不同的键,table-per-[不一定如此。 =82=]策略。
单table和联合继承策略促进了涉及抽象超class的关系; table-per-class 策略没有很好地支持这些。
对 table-per-class 策略的支持是 可选。 JPA 提供者不需要支持它,实际上 GlassFish 参考实现中的默认提供者不支持它。因此,不能保证依赖 table-per-class 的应用程序是 portable。 (您的提供商 Hibernate 确实支持它。)
你接着说,
However, in this case I get java.sql.SQLSyntaxErrorException:
ORA-00904: "KEY": invalid identifier
. Seems like using @Inheritance
together with @AttributeOverride
for @Id
field doesn't work.
@AttributeOverride
仅指定用于覆盖映射的超classes 的属性以及嵌入式classes 的字段和属性。如果 属性出现在这些上下文中,它 对 @Id
属性有效。对于从实体 superclass 继承的持久字段和属性,它没有指定工作(虽然也没有指定 not 工作),但请注意它 不能使用单table或联合继承策略来处理此类属性。
如果 @AttributeOverride
确实对您有用,那么该用途将是非 table。另一方面,JPA 没有别的东西可以完成你想要的。一个特定的持久性提供者可以有一个支持它的扩展,但 Hibernate 历史上没有这样做——从实体 superclass 继承的所有属性都映射为相同的名称。
你还说,
One more thing I'd like to mention is that I've tried using
@MappedSuperclass
instead of @Inheritance
but in this case I'm not
able to query with abstact Vehicle
type.
JPA 不为您的特定需求组合提供解决方案:
- 将每个具体实体 class 映射到单独的 table、
- 将 ID 命名为每个实体中的不同列名称 table,并且
- 支持抽象超类型的多态查询。
如果您不愿意更改其中任何一个,那么您将不得不依赖于扩展。在这种情况下,您很幸运:Hibernate 支持 polymorphic queries,其中多态类型未映射为实体。因此,如果您愿意让您的应用程序明确依赖于 Hibernate,您可能会达到您想要的效果。
具体来说,要在 Hibernate 中执行此操作,您将依赖 "implicit polymorphism"。为此,您将避免将 superclass 映射为实体,根据您的经验,我猜它也不应该是映射的 superclass。它可以是一个普通的 class,尽管它的属性不会持久,或者您可以使用一个接口来代替。如果您的 Vehicle
class 具有您想要持久化的属性,那么您可以将其更改为可嵌入的 class。您还可以注释每个车辆实体以指定隐式多态性,例如:
@Entity
@Polymorphism(type = PolymorphismType.IMPLICIT)
// ...
public class Car implements Vehicle {
// ...
}
Hibernate 文档声称隐式多态性是默认设置,但为了清楚起见,我还是建议应用 @Polymorphism
注释。
我有以下映射:
@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 数据存储库
public interface VehicleRepository extends CrudRepository<Vehicle, Long> {
}
并尝试像这样使用它:vehicleRepository.findAll();
然而,在这种情况下,我得到 java.sql.SQLSyntaxErrorException: ORA-00904: "KEY": invalid identifier
。似乎将 @Inheritance
与 @AttributeOverride
一起用于 @Id
字段不起作用。
我想指出的是,如果 Car
和 Bus
实体对 @Id
具有相同的映射,它将完美地工作(但事实并非如此:"car_id" 和 "bus_id")
此外,我尝试将 @Id
字段从 Vehicle
class 移动到 subclasses,但结果是每个 @Entity
应该包含 @Id
.
我想提的另一件事是我尝试使用 @MappedSuperclass
而不是 @Inheritance
但在这种情况下我无法使用 abstact Vehicle
进行查询类型。
有人可以帮我吗?
谢谢
你说,
And what I'm trying to achieve is to query different tables for retrieving both Car and Bus entities.
,但作为第一个考虑,你应该评估你是否真的想这样做。想想这个:
单table 继承策略对于您想象的整个层次结构查询通常是最快的。它可以通过单个查询执行整个层次结构和具体实体操作,无需连接或联合。
单table和联合继承策略确保层次结构中的所有实体都有不同的键,table-per-[不一定如此。 =82=]策略。
单table和联合继承策略促进了涉及抽象超class的关系; table-per-class 策略没有很好地支持这些。
对 table-per-class 策略的支持是 可选。 JPA 提供者不需要支持它,实际上 GlassFish 参考实现中的默认提供者不支持它。因此,不能保证依赖 table-per-class 的应用程序是 portable。 (您的提供商 Hibernate 确实支持它。)
你接着说,
However, in this case I get
java.sql.SQLSyntaxErrorException: ORA-00904: "KEY": invalid identifier
. Seems like using@Inheritance
together with@AttributeOverride
for@Id
field doesn't work.
@AttributeOverride
仅指定用于覆盖映射的超classes 的属性以及嵌入式classes 的字段和属性。如果 属性出现在这些上下文中,它 对 @Id
属性有效。对于从实体 superclass 继承的持久字段和属性,它没有指定工作(虽然也没有指定 not 工作),但请注意它 不能使用单table或联合继承策略来处理此类属性。
如果 @AttributeOverride
确实对您有用,那么该用途将是非 table。另一方面,JPA 没有别的东西可以完成你想要的。一个特定的持久性提供者可以有一个支持它的扩展,但 Hibernate 历史上没有这样做——从实体 superclass 继承的所有属性都映射为相同的名称。
你还说,
One more thing I'd like to mention is that I've tried using
@MappedSuperclass
instead of@Inheritance
but in this case I'm not able to query with abstactVehicle
type.
JPA 不为您的特定需求组合提供解决方案:
- 将每个具体实体 class 映射到单独的 table、
- 将 ID 命名为每个实体中的不同列名称 table,并且
- 支持抽象超类型的多态查询。
如果您不愿意更改其中任何一个,那么您将不得不依赖于扩展。在这种情况下,您很幸运:Hibernate 支持 polymorphic queries,其中多态类型未映射为实体。因此,如果您愿意让您的应用程序明确依赖于 Hibernate,您可能会达到您想要的效果。
具体来说,要在 Hibernate 中执行此操作,您将依赖 "implicit polymorphism"。为此,您将避免将 superclass 映射为实体,根据您的经验,我猜它也不应该是映射的 superclass。它可以是一个普通的 class,尽管它的属性不会持久,或者您可以使用一个接口来代替。如果您的 Vehicle
class 具有您想要持久化的属性,那么您可以将其更改为可嵌入的 class。您还可以注释每个车辆实体以指定隐式多态性,例如:
@Entity
@Polymorphism(type = PolymorphismType.IMPLICIT)
// ...
public class Car implements Vehicle {
// ...
}
Hibernate 文档声称隐式多态性是默认设置,但为了清楚起见,我还是建议应用 @Polymorphism
注释。