Hibernate composite key which are foreigen key to another table
I have two table Part and SubPart. Part table has general fields like id, name, desc etc. The SubPart table has part_id, sub_part_id as composite key. Both of these columns are referring to Part table and has a one to many mapping for each of them, like for each part_id in the Part table there can be multiple entries in SubPart table for both the columns. I'm having problem defining the composite key for the SubPart table. I tried the Embedded tag but its not working. How can I address this problem. Thanks a lot.
Part table like this.
@Entity
@Table(name="Part")
public class Part {
@Id
@GeneratedValue
@Column(name="Part_Id")
private int id;
@Column(name="Part_Number")
private String partNumber;
@Column(name="Part_Name")
private String partName;
}
Sub Part Table
@Entity
@Table(name="SubPart")
public class SubPart {
//开发者_JAVA技巧 part and subPart combination is the compound key here.
@ManyToOne
@JoinColumn(name="Part_Id")
private Part part;
@ManyToOne
@JoinColumn(name="Sub_Part_Id")
private Part subPart;
@Column(name="Quantity")
private Integer quantity;
}
You said
I'm having problem defining the composite key for the SubPart table
When you have a compound primary key, you must define a class (Usually a static inner class) which defines your compound primery key (Just an advice: because Hibernate makes use of proxies, prefer to put your annotated mapping on the getter's instead of field members)
/**
* When both entity class and target table SHARE the same name
* You do not need @Table annotation
*/
@Entity
public class SubPart implements Serializable {
@EmbeddedId
private SubPartId subPartId;
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="PART_ID", insertable=false, updateable=false)
private Part part;
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="SUP_PART_ID", insertable=false, updateable=false)
private SubPart subPart;
/**
* required no-arg constructor
*/
public SubPart() {}
public SubPart(SubPartId subPartId) {
this.subPartId = subPartId;
}
// getter's and setter's
/**
* It MUST implements Serializable
* It MUST overrides equals and hashCode method
* It MUST has a no-arg constructor
*
* Hibernate/JPA 1.0 does not support automatic generation of compound primary key
* You SHOULD set up manually
*/
@Embeddable
public static class SubPartId implements Serializable {
@Column(name="PART_ID", updateable=false, nullable=false)
private Integer partId;
@Column(name="SUB_PART_ID", updateable=false, nullable=false)
private Integer subPartId;
/**
* required no-arg constructor
*/
public SubPartId() {}
public SubPartId(Integer partId, Integer subPartId) {
this.partId = partId;
this.subPartId = subPartId;
}
// getter's and setter's
@Override
public boolean equals(Object o) {
if(!(o instanceof SubPartId))
return null;
final SubPartId other = (SubPartId) o;
return new EqualsBuilder().append(getPartId(), other.getPartId())
.append(getSubPartId(), other.getSubPartId())
.isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder().append(getPartId())
.append(getSubPartId())
.toHashCode();
}
}
}
Notice Part and SubPart mapping has been marked as insertable=false, updateable=false Because the mapping has been defined in the compound primary key. Hibernate does not allow you mapping two properties WITH THE SAME COLUMN unless you mark insertable=false, updateable=false. Otherwise you will see this nice exception
Should be marked with insertable=false, updateable=false
I think I would declare a field of type Map<Part,SubPart> in class Part and declare it as @OneToMany.
Actually, in this particular case, it could event be a Map<Part,Integer> because the only other field is the quantity. The SubPart class is not needed.
精彩评论