2016-10-24 109 views
0

我已經通過簡單的父子表解釋了我的方案。複合外鍵JPA TypeMismatchException

我的組合主鍵也是引用父表的組合外鍵。創建

create table parent(
code varchar(10) not null, 
id int not null, 
parentcol varchar(10), 
primary key(code,id) 
); 

create table child(
code varchar(10) not null, 
id int not null, 
childcol varchar(10) not null, 
primary key(code, id), 
foreign key(code, id) references parent(code,id) 
); 

實體(這是通過Eclipse的插件JPA)

@Entity 
@Table(name="parent") 
@NamedQuery(name="Parent.findAll", query="SELECT p FROM Parent p") 
public class Parent implements Serializable { 
private static final long serialVersionUID = 1L; 

@EmbeddedId 
private ParentPK id; 

@Column(length=10) 
private String parentcol; 

//bi-directional one-to-one association to Child 
@OneToOne(mappedBy="parent") 
private Child child; 

public Parent() { 
} 

/* getters and setters */ 

} 

@Embeddable 
public class ParentPK implements Serializable { 
//default serial version id, required for serializable classes. 
private static final long serialVersionUID = 1L; 

@Column(unique=true, nullable=false, length=10) 
private String code; 

@Column(unique=true, nullable=false) 
private int id; 

    /* getters and setters */ 

/** Overridden equals and hashcode **/ 
} 



@Entity 
@Table(name="child") 
@NamedQuery(name="Child.findAll", query="SELECT c FROM Child c") 
public class Child implements Serializable { 
private static final long serialVersionUID = 1L; 

@EmbeddedId 
private ChildPK id; 

@Column(nullable=false, length=10) 
private String childcol; 

//bi-directional one-to-one association to Parent 
@OneToOne 
@JoinColumns({ 
    @JoinColumn(name="code", referencedColumnName="code", nullable=false, insertable=false, updatable=false), 
    @JoinColumn(name="id", referencedColumnName="id", nullable=false, insertable=false, updatable=false) 
    }) 
private Parent parent; 

    /* getters and setters */ 

} 

@Embeddable 
public class ChildPK implements Serializable { 
//default serial version id, required for serializable classes. 
private static final long serialVersionUID = 1L; 

@Column(insertable=false, updatable=false, unique=true, nullable=false, length=10) 
private String code; 

@Column(insertable=false, updatable=false, unique=true, nullable=false) 
private int id; 

/* overridden equals and hashcode */ 

我使用Spring數據如下救我的實體。父表格由代碼爲「代碼」並且標識爲1的記錄組成。

Child child = new Child(); 
ChildPK childPK = new ChildPK(); 
childPK.setCode("code"); 
childPK.setId(1); 
child.setId(childPK); 
child.setChildcol("child1"); 
childRepository.save(child); 

它在第一次運行時成功插入新記錄。但問題是當它有更新,讓我們用說,第二次運行,

child.setChildcol("child2"); 

我面臨着一個錯誤

HHH000327: Error performing load command : org.hibernate.TypeMismatchException: Provided id of the wrong type for class com.xebia.eTechLog.entities.Parent. Expected: class com.xebia.eTechLog.entities.ParentPK, got class com.xebia.eTechLog.entities.ChildPK 

萬一我試着給子表作爲ParentPk參考

@Entity 
@Table(name="child") 
@NamedQuery(name="Child.findAll", query="SELECT c FROM Child c") 
public class Child implements Serializable { 
private static final long serialVersionUID = 1L; 

@EmbeddedId 
private ParentPK id; 

@Column(nullable=false, length=10) 
private String childcol; 

//bi-directional one-to-one association to Parent 
@OneToOne 
@JoinColumns({ 
    @JoinColumn(name="code", referencedColumnName="code", nullable=false, insertable=false, updatable=false), 
    @JoinColumn(name="id", referencedColumnName="id", nullable=false, insertable=false, updatable=false) 
    }) 
private Parent parent; 

它可以工作,但它不會在Parent類中有更多的字段,這是我的真實場景。

回答

0

您應該使用派生的身份。這意味着你應該表明,孩子的引用其父映射孩子的ID(用@MapsId註釋):

@Entity 
public class Child implements Serializable { 
    @EmbeddedId 
    private ChildPK id; 

    @Column(nullable=false, length=10) 
    private String childcol; 

    @OneToOne 
    @MapsId // <<< NB 
    @JoinColumns({ 
     @JoinColumn(name="code", referencedColumnName="code"), 
     @JoinColumn(name="id", referencedColumnName="id") 
    }) 
    private Parent parent; 

    ... 
} 

派生身份在JPA 2.1規範第2.4.1節中討論。

+0

謝謝Brian。我之前能夠找出答案,並且與您提到的內容完全一致。您需要爲映射到父表的複合主鍵部分使用@MapsId。 – bitscanbyte