有一些这样的类:
@Entity
@Table(name="person")
@Inheritance(strategy=InheritanceType.JOINED)
public class Person {
@Id
@GeneratedValue
private int personId;
它的子类是:
@Entity
@Table(name="employee")
@PrimaryKeyJoinColumn(name="employee_id")
public class Employee extends Person {
[Something else fields]
有必要提到的是,还有一些其他对象是从具有自己的 Fk 字段(例如 student_id)的 Person 实体的 Person 扩展的 Student。
生成的查询如下 HQL:
select count(e)
from Employee e
是:
select count(e.id)
from employee e
inner join person p
on e.employee_id = p.id
而正确生成的查询必须是:
select count(e.employee_id)
from employee e
inner join person p
on e.employee_id = p.id
因此,提出了invalid identifier
异常。
哪里出了问题,我必须做些什么来解决这个问题?
更新
这些实体的表是:
人:
id and others files
------------------------------------
员工表为:
employee_id[fk to person table] others fields
----------------------------------------------------
虽然Hibernate允许这种继承,但通常会避免,因为结果/行为不太容易被开发人员控制。
相反,通过我以前的经验和恕我直言,我建议遵循以下做法,这将使您更好地控制自 JPA 2.0 以来的@JoinColumn来实现预期结果:
@Entity
@Table(name="person")
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="person_id")
private Long personId;
}
@Entity
@Table(name="employee")
public class Employee{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="employee_id")
private Long employeeId;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn (name="person_id")
private Person person;
}
更新 1
如果使用@PrimaryKeyJoinColumn更可取,那么在原始代码中需要纠正一件事(至少需要为 PK 分配一个名称以给你更多的控制:
@Entity
@Table(name="person")
@Inheritance(strategy=InheritanceType.JOINED)
public class Person {
@Id
@GeneratedValue
@Column(name="person_id")
private int personId;
}
@Entity
@Table(name="employee")
@PrimaryKeyJoinColumn(name="person_id")
public class Employee extends Person {
@GeneratedValue
@Column(name="employee_id")
private int employeeId;
}
这是因为@PrimaryKeyJoinColumn
应该让当前的辅助表知道它需要引用主表的哪个主键。
您可以参考 JPA 2.0 规范的以下部分:
11.1.40 主键连接列注释
PrimaryKeyJoinColumn
批注指定一个主键列,该列用作外键以联接到另一个表。
PrimaryKeyJoinColumn
注释用于联接主表JOINED
将策略映射到主类中的实体子类 其超类表;它在SecondaryTable
注释中使用 将辅助表连接到主表;它可以用于OneToOne
引用实体的主键为 用作引用实体的外键[108]。
要扩展garykwwong的答案,您可以:
- 使用显式
personId
列名(person_id
和employee_id
将用作person
和employee
表中的列名):
@Entity
@Table(name="person")
@Inheritance(strategy=InheritanceType.JOINED)
public class Person {
@Id
@GeneratedValue
@Column(name="person_id")
private int personId;
}
@Entity
@Table(name="employee")
@PrimaryKeyJoinColumn(name = "employee_id", referencedColumnName = "person_id")
public class Employee extends Person {
// Explicit employeeId field is NOT required in the class
}
- 根本不使用
personId
列名,让 JPA 为您做链接(personId
和employee_id
将用作person
和employee
表中的列名):
@Entity
@Table(name="person")
@Inheritance(strategy=InheritanceType.JOINED)
public class Person {
@Id
@GeneratedValue
private int personId;
}
@Entity
@Table(name="employee")
@PrimaryKeyJoinColumn(name = "employee_id")
public class Employee extends Person {
// Explicit employeeId field is NOT required in the class
}
- 根本不使用显式名称(
personId
将在person
和employee
表中用作列名):
@Entity
@Table(name="person")
@Inheritance(strategy=InheritanceType.JOINED)
public class Person {
@Id
@GeneratedValue
private int personId;
}
@Entity
@Table(name="employee")
@PrimaryKeyJoinColumn
public class Employee extends Person {
}
这是一个演示项目,演示了第一个选项。