【问题标题】:Hibernate - Foreign and primary keys in inheritanceHibernate - 继承中的外键和主键
【发布时间】:2015-11-16 09:36:39
【问题描述】:

我想知道,有没有可能有这样的东西。假设我有一张名为material 的表:

+-------+---------------+------+-----+---------+-------+
| Field | Type          | Null | Key | Default | Extra |
+-------+---------------+------+-----+---------+-------+
| id    | int(11)       | NO   | PRI | NULL    |       |
| name  | varchar(255)  | YES  |     | NULL    |       |
| price | decimal(19,2) | YES  |     | NULL    |       |
+-------+---------------+------+-----+---------+-------+

在 Java 端实体是:

@Entity
@DiscriminatorValue("M")
public class Material extends Expense {

    private String name;

    private BigDecimal price;

    // Getters and setters
}

和名为occupation的表:

+--------------+---------------+------+-----+---------+-------+
| Field        | Type          | Null | Key | Default | Extra |
+--------------+---------------+------+-----+---------+-------+
| id           | int(11)       | NO   | PRI | NULL    |       |
| name         | varchar(255)  | YES  |     | NULL    |       |
| payment_type | varchar(255)  | YES  |     | NULL    |       |
| price        | decimal(19,2) | YES  |     | NULL    |       |
+--------------+---------------+------+-----+---------+-------+

在 Java 端实体是:

@Entity
@DiscriminatorValue("O")
public class Occupation extends Expense {

    private String name;

    private BigDecimal price;

    @Enumerated(EnumType.STRING)
    private PaymentType paymentType;

    // Getters and setters

}

现在假设我想在 Java 端为 OccupationMaterial 创建一个名为 Expense 的通用类,代表材料和职业的费用。看起来像这样:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "expense_type", discriminatorType = DiscriminatorType.STRING)
public class Expense {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    // Getters and setters

}

在 SQL 方面:

+--------------+-------------+------+-----+---------+----------------+
| Field        | Type        | Null | Key | Default | Extra          |
+--------------+-------------+------+-----+---------+----------------+
| expense_type | varchar(31) | NO   |     | NULL    |                |
| id           | int(11)     | NO   | PRI | NULL    | auto_increment |
+--------------+-------------+------+-----+---------+----------------+

但是,问题是我们引入继承时,费用的主键是材料和职业表中的外键。费用表是否有可能有自己的主键,并以某种方式保存材料和职业的 id 和鉴别器类型,以便材料和职业表可以有具有相同 id 的行(如材料中的34 id 和职业中的34 id桌子)?我的意思是,在 SQL 端它可以很容易地完成,但是在 Java 端呢?

【问题讨论】:

    标签: java mysql hibernate


    【解决方案1】:

    根据休眠文档,尝试:

    @PrimaryKeyJoinColumn 和 @PrimaryKeyJoinColumns 注释 定义连接子类表的主键:

    @Entity
    @Inheritance(strategy=InheritanceType.JOINED)
    public class Boat implements Serializable { ... }
    
    @Entity
    @PrimaryKeyJoinColumn(name="BOAT_ID")
    public class AmericaCupClass  extends Boat { ... }    
    

    https://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#d0e1168

    另请查看 PrimaryKeyJoinColumn javadoc,它有:

    (可选) 表的主键列名 加入到。默认与主键列同名 超类的主表(JOINED 映射 战略);与primary的主键列同名 表(SecondaryTable 映射);或与 引用实体的表的主键列 (OneToOne 映射)。

    字符串引用列名()

    我认为这是你需要的

    【讨论】:

    • 不。那没有解决问题。它基本上是重命名子类中的 id 列。
    • 根据PrimaryKeyJoinColumn javadoc,它有: referencedColumnName:被连接的表的主键列的名称。 - 尝试使用它
    • 这是我使用的解决方案,这确实是正确的:)
    【解决方案2】:

    这是不可能的,因为根据 JPA 2.0 规范。它在第 2.4 节(主键和实体身份)中说:

    主键必须定义在作为实体层次结构根的实体类或 映射的超类,它是实体层次结构中所有实体类的(直接或间接)超类。这 主键必须在实体层次结构中只定义一次。

    【讨论】:

    • 虽然这在理论上可以回答这个问题,it would be preferable 在此处包含答案的基本部分,并提供链接以供参考。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-09
    • 1970-01-01
    • 1970-01-01
    • 2010-11-10
    • 2020-02-19
    • 2014-08-13
    相关资源
    最近更新 更多