[英]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.