当前位置: 首页 > 知识库问答 >
问题:

InheritanceType.Joint、@PrimaryKeyJoinColumn和嵌套子类

孙光临
2023-03-14

我正在开始使用Hibernate,有一个关于InheritanceType.Jointed和@PrimaryKeyJoinColumn的问题。

create table person (person_id int(10) auto_increment, 
                     name varchar(100),
                     primary key (person_id));

create table employee (employee_id int(10) auto_increment,
                       person_id int(10),
                       salary int(10),
                       primary key (employee_id));

create table manager (manager_id int(10) auto_increment,
                      employee_id int(10),
                      shares int(10),
                      primary key (manager_id));
@Entity
@Table(name="person")
@Inheritance(strategy=InheritanceType.JOINED)
public class Person {

    @Id
    @GeneratedValue
    @Column(name="person_id")
    private int personId;

    @Column(name="name")
    private String name;
}


@Entity
@Table(name="employee")
@PrimaryKeyJoinColumn(name="person_id")
public class Employee extends Person {

    @GeneratedValue
    @Column(name="employee_id")
    private int employeeId;

    @Column(name="salary")
    private int salary;
}

谈到Manager类时,我不确定要为@PrimaryKeyJoinColumn使用哪个值。通过阅读JPA规范,我应该在整个Superclass/Subclass/Subclass层次结构中只使用一个id,我怀疑它应该是person_id。

我是否应该从manager表中删除employee_id列并将其替换为Person_id?我问的原因是,在数据库中有“级联”主键似乎很自然(即manager不直接引用person),但我相信Hibernate要求所有子类(无论多么“深”)都包含返回到超类的外键。对我的断言进行一些证实会非常有用。

共有1个答案

凌昕
2023-03-14

您可以使用任何您想要的列名。@PrimaryKeyJoinColumn注释用于告诉hibernate联接表中的外键列的名称是什么。

@Entity
@Table(name = "manager")
@PrimaryKeyJoinColumn(name = "employee_id")
public class Manager extends Employee{
    private String branch;
}

这段代码意味着在manager表中有一个名为employee_id的列,它是employee表的外键。

这个注释是可选的,所以如果您不提供它,那么外键列名将与基类中的键名相同(如果是多级继承,则为超级基),在您的情况下,如果您不提供,那么任何子类都将使用person_id作为外键。

如果您希望在manager表中将字段名保留为employee_id,那么您必须这样提供。

@PrimaryKeyJoinColumn(Name=“Employee_ID”)

如果您根本不提供此注释,那么将有一个列名称person_id用作employee表的外键。

文件是这么说的。

此批注指定一个主键列,该列用作连接到另一个表的外键。

用于将联接映射策略中实体子类的主表联接到其超类的主表;它在SecondaryTable注释中用于将辅助表连接到主表;并且可以在其中引用实体的主键用作到被引用实体的外键的OneToOne映射中使用。

如果在联接映射策略中未为子类指定PrimaryKeyJoinColumn注释,则假定外键列具有与超类的主表的主键列相同的名称

编辑

当我尝试按ID检索manager时,Hibernate正在执行的查询。

select
            manager0_.id as id1_4_0_,
            manager0_2_.name as name2_4_0_,
            manager0_1_.employee_id as employee1_1_0_,
            manager0_1_.salary as salary2_1_0_,
            manager0_.branch as branch1_2_0_ 
        from
            manager manager0_ 
        inner join
            employee manager0_1_ 
                on manager0_.id=manager0_1_.id 
        inner join
            person manager0_2_ 
                on manager0_.id=manager0_2_.id 
        where
            manager0_.id=?

这意味着Hibernate本身只使用级联主键而不是超级父键来创建表。

我理解你的困惑,即使我在hibernate文档中找不到任何东西。它只是说FK将指向超类主键。它不指定即时超类或顶级超类。虽然我检查了其他JPA实现,即OpenJPA。它确实特别指出FK指向即时超类。

 类似资料:
  • 使用Laravel 5.6,我试图从MySQL类别表中显示子类别的子类别。我想传递这个名字,并获得它的所有子类,而不管父类是什么。 类别表 期望结果 return App\Category::where('name','Child-1-P-2'))-

  • 我有一个相当典型的场景,其中有一个main@实体,他内部的所有内容都是可嵌入的(因此,没有父实体,内部的所有内容都没有意义)。现在JPA 2.0阻止我在另一个@ElementCollection中定义的@Embeddeble中嵌套一个@ElementCollection: JSR-317 2.6可嵌入类和基本类型的集合包含在元素集合中的可嵌入类(包括另一个可嵌入类中的可嵌入类)不得包含元素集合,也

  • 问题内容: 和之间的确切区别是什么? 您使用的列是外键的一部分。典型的列可能看起来像(例如,在具有附加属性的联接表中): 如果我也将列也提升为a / PK(又称为识别关系)会怎样?由于该列现在是PK,因此我必须用标记: 现在的问题是: 是+ 上面一样? 如果没有,那有什么用? 问题答案: 如果我也将列也提升为a / PK(又称为识别关系)会怎样?由于该列现在是PK,因此必须使用@Id(…)对其进行

  • 我在当前项目中使用Sass(.scss)。 以下示例: HTML SCSS 这个很管用。 我可以处理多个类,同时使用嵌套样式。 在上面的示例中,我讨论了以下内容: CSS 在这种情况下,所有通常为,但为蓝色。 我如何在中与Sass嵌套?

  • Oracle留档(在下面的链接)说: 非静态嵌套类(内部类)可以访问封闭类的其他成员,即使它们被声明为私有的。 但在下面的示例中,我创建了一个对象(内部类),它无法访问其封闭外部类的任何方法或变量。下面是代码,你能解释一下吗? http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html 使用Main方法初始化 对于对象,我无法访问其

  • 问题内容: 在SQL Server中, 您可以这样编写嵌套的SQL: 这样,我可以获得一个可以嵌套到其他查询中的临时表T。 但是我不能在oracle SQL中做同样的事情 它给我 选择*有效,但这不是我想要的。有人知道该怎么做吗? 问题答案: 无论我显式指定别名还是指定,您发布的查询都对我有效。收到异常后,您可以发布正在运行的确切查询吗? 我的猜测是您要选择不带双引号的内容。如果在Oracle中使