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;
    }
}

image

image

参考文章:http://www.4ucode.com/Study/Topic/1070774

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;
    }
}
原文地址:https://www.cnblogs.com/syxchina/p/2439280.html