[英]JPA fetching value from Many to One relationship
我在将多对一关系中的单个值嵌入JPA中时遇到问题。 下面有一些代码用于初始化测试模式以及测试实体。
这个想法是,有一个表EMPLOYEE引用了表RANK。 表RANK依次包含RANK的名称。 每个员工都参照其职级。
当我尝试运行代码时,出现以下异常:
Caused by: org.hibernate.AnnotationException: SecondaryTable JoinColumn cannot reference a non primary key
at org.hibernate.cfg.annotations.TableBinder.bindFk(TableBinder.java:623)
at org.hibernate.cfg.annotations.EntityBinder.bindJoinToPersistentClass(EntityBinder.java:764)
at org.hibernate.cfg.annotations.EntityBinder.createPrimaryColumnsToSecondaryTable(EntityBinder.java:756)
at org.hibernate.cfg.annotations.EntityBinder.finalSecondaryTableBinding(EntityBinder.java:684)
at org.hibernate.cfg.SecondaryTableSecondPass.doSecondPass(SecondaryTableSecondPass.java:29)
这是一个数据库模式
CREATE TABLE RANK (
ID INT NOT NULL,
NAME VARCHAR
);
ALTER TABLE RANK ADD PRIMARY KEY (ID);
INSERT INTO RANK (ID, NAME) VALUES (1, 'WORKER')
CREATE TABLE EMPLOYEE(
ID INT NOT NULL,
NAME VARCHAR,
RANK_ID INT NOT NULL
);
ALTER TABLE EMPLOYEE ADD PRIMARY KEY (ID);
INSERT INTO EMPLOYEE (ID, NAME, RANK_ID) VALUES (1, 'Bobby', 1);
最后,唯一的实体:
@Entity
@Table(name = "EMPLOYEE")
@SecondaryTable(name = "RANK", pkJoinColumns=@PrimaryKeyJoinColumn(name="ID", referencedColumnName = "RANK_ID"))
public class Employee {
@Id
@Column(name = "id")
@GeneratedValue(generator = "increment")
@GenericGenerator(name = "increment", strategy = "increment")
private int id;
@Column(name = "NAME")
private String name;
@Column(name = "RANK_ID")
private int rankId;
@Column(name = "name", table = "RANK")
private String rank;
public Employee() {
}
}
对于如何解决此问题的任何提示,我将不胜感激。 假定使用JPA无法做到这一点很普遍。
使用辅助表批注时,请引用Employee ID并删除rank_id
。 您说的是通过使用该注释将数据分布在多个表中,因此基本上两者的主键是相同的。 实际上,由于两个PK具有相同的标识符,因此甚至不必定义@PrimaryKeyJoinColumn
。
请参考这里: https : //docs.jboss.org/hibernate/jpa/2.1/api/javax/persistence/SecondaryTable.html
在另一方面,如果你只是想许多人,你可以使用一个关系@ManyToOne
注释和@JoinColumn
在rank_id
。
如果您阅读Java Persistence Wikibook的这一部分,将会看到JPA规范未涵盖您想要的内容,因此底层提供程序可能不支持您想要的内容:
JPA规范并未直接涵盖这一点,因此,如果您具有这种情况,那么,如果您有灵活性,首先要考虑的是更改数据模型,使其不超出规范的范围。
@SecondaryTable
主要用于将一对一表链接到一个实体。
实现所需目标的“标准”方法是为Rank
创建一个单独的实体,而EAGER在Employee
获取它。 然后,您可以在Employee
有一个名为getRankName()
的方法,该方法返回this.rank.getName()
。 因此,您的Employee
类如下所示:
@Entity
@Table(name = "EMPLOYEE")
public class Employee {
@Id
@Column(name = "id")
@GeneratedValue(generator = "increment")
@GenericGenerator(name = "increment", strategy = "increment")
private int id;
@Column(name = "NAME")
private String name;
@ManyToOne(fetch = FetchType.EAGER, optional = false)
@JoinColumn(name = "RANK_ID", referencedColumnName = "ID")
private Rank rank;
public Employee() {
}
public String getRankName() {
if (this.rank == null) {
return null;
}
return this.rank.getName();
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.