hibernate多對多對映拆成2個一對多對映(註解)
hibernate的many to many確實很是方便我們處理實體和集合間的關係,並可以通過級聯的方法處理集合,但有的時候many to many不能滿足我們的需要,比如 使用者<--->選課,典型的多對多關係,一般情況下,會生成
course_user(course_id,user_id);
但使用者選課的時候最好加入稽核功能,所以我們希望在中間自動生成的表中加入一個boolean欄位,類似這種結構:
course_user(course_id,user_id,accessable);
這個時候我們可以把many to many拆分成2個many to one ,自己手動添加個中間表,這樣擴充套件就好很多了。
程式碼如下:
@Embeddable
public class CourseUserPK implements Serializable{
private static final long serialVersionUID = 1L;
private Course course;
private User user;
@ManyToOne
@JoinColumn(name = "course_id", nullable = false)
public Course getCourse() {
return course;
}
public void setCourse(Course course) {
this.course = course;
}
@ManyToOne
@JoinColumn(name = "user_id", nullable = false)
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public boolean equals(Object object) {
if (this == object)
return true;
if (!(object instanceof CourseUserPK))
return false;
final CourseUserPK other = (CourseUserPK) object;
if (this.course != null && other.getCourse() != null) {
if(course.getId() == other.course.getId()) {
if(user!=null&&other.getUser()!=null&&user.getId()==other.getUser().getId()) {
return true;
} else {
return false;
}
} else {
return true;
}
} else
return false;
}
public int hashCode() {
return super.hashCode()+
(course!=null?course.hashCode():0)+
(user!=null?user.hashCode():0);
}
}
@Entity
@IdClass(CourseUserPK.class)
public class CourseTeacher {
private Course course;
private User user;
private Boolean accessable;//true user is in course, otherwise not
public CourseTeacher(Course course, User user, Boolean accessable) {
this.course = course;
this.user = user;
this.accessable = accessable;
}
@Id
public Course getCourse() {
return course;
}
public void setCourse(Course course) {
this.course = course;
}
@Id
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Boolean getAccessable() {
return accessable;
}
public void setAccessable(Boolean accessable) {
this.accessable = accessable;
}
}
@Entity
@IdClass(CourseUserPK.class)
public class CourseStudent {
private Course course;
private User user;
private Boolean accessable;//true user is in course, otherwise not
public CourseStudent(Course course, User user, Boolean accessable) {
this.course = course;
this.user = user;
this.accessable = accessable;
}
@Id
public Course getCourse() {
return course;
}
public void setCourse(Course course) {
this.course = course;
}
@Id
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Boolean getAccessable() {
return accessable;
}
public void setAccessable(Boolean accessable) {
this.accessable = accessable;
}
}
@Entity
public class Course extends BaseEntity {
private static final long serialVersionUID = 8768227695335084711L;
private Set<CourseTeacher> teachers;
private Set<CourseStudent> students;
@OneToMany(mappedBy="course",cascade=CascadeType.ALL)
public Set<CourseTeacher> getTeachers() {
return teachers;
}
public void setTeachers(Set<CourseTeacher> teachers) {
this.teachers = teachers;
}
@OneToMany(mappedBy="course")
public Set<CourseStudent> getStudents() {
return students;
}
public void setStudents(Set<CourseStudent> students) {
this.students = students;
}
}
Hibernate可以通過*.hbm.xml配置檔案能很好地把多對多關係拆分成兩個一對多的關係,但Hibernate Annotation的文件中沒有說到這個點上來。下面通過例項說明用註解來實現多對多拆分成兩個一對多。
下面以商品Product和訂單Order之間的多對多關係來說明。
Product的屬性包括:
- id
- name
- price
Order的屬性包括:
- id
- date(下訂單的時間)
為什麼要把多對多關係拆分成兩個一對多?
因為多對多關係不能儲存兩個實體之間共有的屬性。比如,如何記錄訂單A中購買的商品B的數量呢?如果以多對多對映就不能實現了。
中間實體----用來記錄兩個多對多實體之間共有關係
在Product和Order之間的關係中,可以用一個OrderItem實體來表示兩者多對多中的眾多關係中的一個關係。即Product與OrderItem,Order與OrderItem之間的關係為一對多的關係。
OrderItem的屬性包括:
- product(假如當前記錄的是商品C)
- order(假如當前記錄的是訂單D)
- quantity(這裡記錄的是訂單D中商品C的數量)
例項程式碼(省略了類包引用):
複合主鍵類:
@Embeddable public class OrderItemPK implements Serializable{ private Product product; private Order order; @ManyToOne @JoinColumn(name="product_id",referencedColumnName="id") public Product getProduct(){ return product; } public void setProduct(Product product){ this.product=product; } @ManyToOne @JoinColumn(name="order_id",referencedColumnName="id") public Order getOrder(){ return order; } public void setOrder(Order order){ this.order=order; } public boolean equals(Object object){...} public int hashCode(){...} }
OrderItem類:
@Entity @org.hibernate.annotation.Entity(dynamicInsert=true,dynamicUpdate=true) @Table(name="order_item") @IdClass(OrderItemPK.class) public class OrderItem implements Serializable{ private Product product; private Order order; private int quantity; @Id public Product getProduct(){ return product; } public void setProduct(Product product){ this.product=product; } @Id public Order getOrder(){ return order; } public void setOrder(Order order){ this.order=order; } @Column(name="quantity") public int getQuantity(){ return quantity; } public void setQuantity(int quantity){ this.quantity=quantity; } }
Product類:
@Entity @org.hibernate.annotation.Entity(dynamicInsert=true,dynamicUpdate=true) @Table(name="product") public class Product implements Serializable{ private int id; private String name; private double price; private Set<OrderItem> orderItems; @Id @GenericGenerator(name="g_id",strategy="increment") @GeneratedValue(generator="g_id") public int getId(){ return id; } public void setId(int id){ this.id=id; } public String getName(){ return name; } public void setName(String name){ this.name=name; } public double getPrice(){ return price; } public void setPrice(double price){ this.price=price; } @OneToMany(mappedBy="product") public Set<OrderItem> getOrderItems(){ return orderItems; } public void setOrderItems(Set<OrderItem> orderItems){ this.orderItems=orderItems; } }
Order類:
@Entity @org.hibernate.annotation.Entity(dynamicInsert=true,dynamicUpdate=true) @Table(name="tbl_order") public class Order implements Serializable{ private int id; private Calendar date; private Set<OrderItem> orderItems; @Id @GenericGenerator(name="g_id",strategy="increment") @GeneratedValue(generator="g_id") public int getId(){ return id; } public void setId(int id){ this.id=id; } public Calendar getDate(){ return date; } public void setDate(Calendar date){ this.date=date; } @OneToMany(mappedBy="order") public Set<OrderItem> getOrderItems(){ return orderItems; } public void setOrderItems(Set<OrderItem> orderItems){ this.orderItems=orderItems; } }