JPA 继承类型的@PrimaryKeyJoinColumn在 COUNT 查询中无法正常工作



有一些这样的类:

@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_idemployee_id将用作personemployee表中的列名):
@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 为您做链接(personIdemployee_id将用作personemployee表中的列名):
@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将在personemployee表中用作列名):
@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 {
}

这是一个演示项目,演示了第一个选项。

最新更新