五、关系
1. 1-m 一对多双向关联
多的一方为关系维护端,关系维护端负责外键记录的维护,关系被维护端没有权力更新外键记录。
package cn.itcast.bean.order; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne;
@Entity public class OrderItem { private Integer id; private String productName; private Float sellPrice = 0f; private Order order; @Id @GeneratedValue public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @Column(length=40,nullable=false) public String getProductName() { return productName; } public void setProductName(String productName) { this.productName = productName; } @Column(nullable=false) public Float getSellPrice() { return sellPrice; } public void setSellPrice(Float sellPrice) { this.sellPrice = sellPrice; } @ManyToOne(cascade={CascadeType.REFRESH,CascadeType.MERGE}, fetch=FetchType.EAGER,//XXXOne默认是EAGER,立即加载Order optional=false)//optional为true,就是允许Order这个字段为空,false不允许这个字段为null @JoinColumn(name="orderId")//设置外键名称 public Order getOrder() { return order; } public void setOrder(Order order) { this.order = order; } }
|
/********************************************************************/
package cn.itcast.bean.order;
import java.util.HashSet; import java.util.Set;
import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.OneToMany; import javax.persistence.Table;
@Entity @Table(name="t_order")//order与数据库关系字冲突,改数据库名称 public class Order { private Integer orderId; private Float amount = 0f; private Set<OrderItem> items = new HashSet<OrderItem>(); @Id @GeneratedValue public Integer getOrderId() { return orderId; } public void setOrderId(Integer orderId) { this.orderId = orderId; } @Column(nullable=false) public Float getAmount() { return amount; } public void setAmount(Float amount) { this.amount = amount; } @OneToMany(cascade={CascadeType.REFRESH, CascadeType.PERSIST, CascadeType.REMOVE, CascadeType.MERGE}, fetch=FetchType.LAZY, mappedBy="order")//xxxMany后面是Many的话默认都是延迟加载,保证EntityManager未关闭,XXXOne是EAGER立即加载; //如果类中有mappedBy那就是关系被维护端,应该是少的一方。"order"指明关系维护由下面OrderItem类中的order这个属性来维护 public Set<OrderItem> getItems() { return items; } public void setItems(Set<OrderItem> items) { this.items = items; } public void addOrderItem(OrderItem orderItem) { orderItem.setOrder(this);//OrderItem是外键维护端,要建立关系 this.items.add(orderItem); }
}
|
2.m:n 双向多对多
双方面是对等的关系,自行决定关系维护端。采用中间表(关联表)来存在它们之间的关系定义。
学生A,老师B
假如我们选定学生为关系维护端,那么如何在中间表中插入一条数据呢?
学生A.getTeachers().add(老师B), 在数据库就会执行insert into ……
如果学生如果要删除这个老师
学生A.getTeachers().remove(老师B),在数据库就会执行delete from ……
package cn.itcast.bean; import java.util.HashSet; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany;
@Entity public class Student { private Integer id; private String name; private Set<Teacher> teachers = new HashSet<Teacher>(); @Id @GeneratedValue public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @Column(nullable=false,length=30) public String getName() { return name; } public void setName(String name) { this.name = name; } @ManyToMany(cascade=CascadeType.REFRESH) @JoinTable(name="student_teacher1", inverseJoinColumns=@JoinColumn(name="teacherId"), joinColumns=@JoinColumn(name="studentId")) //@JoinTable定义中间表,name表名称,inverseJoinColumns是被维护端老师,joinColumns是维护端学生, //在中间表中默认名称XXX_id,可以更改名称 public Set<Teacher> getTeachers() { return teachers; } public void setTeachers(Set<Teacher> teachers) { this.teachers = teachers; } }
|
/*****************************************************/
package cn.itcast.bean; import java.util.HashSet; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.ManyToMany;
@Entity public class Teacher { private Integer id; private String name; private Set<Student> students = new HashSet<Student>(); @Id @GeneratedValue public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @Column(nullable=false, length=30) public String getName() { return name; } public void setName(String name) { this.name = name; } @ManyToMany(cascade=CascadeType.REFRESH,mappedBy="teachers") //老师是被维护端,由学生的teachers属性来维护,级联操作只能有更新,其它的出问题。 //如果有级联删除,那么在删除老师的时候会删除他的学生 public Set<Student> getStudents() { return students; } public void setStudents(Set<Student> students) { this.students = students; } }
|
3.复合主键:
比如说航线,主键就是由出发点和终点定义的
复合主键我们一般要把它放到一个复合主键类中,这个类必须要遵守的JPA规范:
·要实现Serializable 序列化接口
·要重写hashCode()和equals()方法:用ctrl+shift+s h 自动生成,选择包括的主键
·要保证有无参的构造方法
package cn.itcast.bean;
import java.io.Serializable;
import javax.persistence.Column; import javax.persistence.Embeddable;
@Embeddable public class AirLinePK implements Serializable { private String start; private String end;
public AirLinePK() {} public AirLinePK(String start, String end) { this.start = start; this.end = end; } @Column(length=3) public String getStart() { return start; } public void setStart(String start) { this.start = start; } @Column(length=3) public String getEnd() { return end; } public void setEnd(String end) { this.end = end; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((end == null) ? 0 : end.hashCode()); result = prime * result + ((start == null) ? 0 : start.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; final AirLinePK other = (AirLinePK) obj; if (end == null) { if (other.end != null) return false; } else if (!end.equals(other.end)) return false; if (start == null) { if (other.start != null) return false; } else if (!start.equals(other.start)) return false; return true; } }
|
package cn.itcast.bean;
import javax.persistence.Column; import javax.persistence.EmbeddedId; import javax.persistence.Entity;
@Entity public class AireLine { private AirLinePK id; private String name; //要保证有一个无参数的构造方法 public AireLine(){} //为了方便保存数据我们添加这个构造方法 public AireLine(String start, String end, String name) { this.id = new AirLinePK(start, end); this.name = name; }
@EmbeddedId public AirLinePK getId() { return id; } public void setId(AirLinePK id) { this.id = id; } @Column(length=20) public String getName() { return name; } public void setName(String name) { this.name = name; } }
|