上篇博客写到了,实体之间的关系有很多种,这次主要来说一下其中的一种一对多关联映射,因为个人觉得一对多的关联映射是比较常见的,例如我们常用的继承关系也是一对多的关联关系。从上篇博客我们也知道,关联关系有单双向之分,先来说单向的一对多关联关系:
一、单向一对多关联
单向一对多关联实体类需要使用集合属性,因为一的一端需要访问N个关联实体,所以N端需要以Set形式出现,set属性记录了它的多个关联实体,需要使用@OneToMany来修饰set属性,使用@OneToMany时可指定的属性与上篇博客介绍到的属性一致,这里就不再赘述了。下面从实例的角度来全面的了解一下单向的一对多关联。
拿一个公司对应多个员工,公司实体中使用了set属性记录它所关联的多个员工实体,实体代码如下:
@Entity
@Table(name="Compony")
public class Compony {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
/**
* 公司名称
*/
@Column(name="name", length=20)
private String name;
/**
* 公司所有的员工
*/
@OneToMany(cascade=CascadeType.ALL,fetch=FetchType.LAZY,targetEntity=Employee.class)
@JoinColumn(name="employeeId",nullable=false)
private Set<Employee> employee;
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 Set<Employee> getEmployee() {
return employee;
}
public void setEmployee(Set<Employee> employee) {
this.employee = employee;
}
}
由于是单向的一的一端不用维护关系,所以实体代码如下:
@Entity
@Table(name="Employee")
public class Employee {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
/**
* 员工姓名
*/
@Column(name="name" ,length=20)
private String name;
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 class test {
static final EntityManagerFactory emf=Persistence.createEntityManagerFactory("qs");
public static void main(String[] args){
EntityManager em=emf.createEntityManager();
Compony compony=new Compony();
compony.setName("信息技术提高班");
try{
//开启事务
em.getTransaction().begin();
compony.getEmployee().add(new Employee("陈丽娜"));
compony.getEmployee().add(new Employee("杨政"));
em.persist(compony);
em.getTransaction().commit();
}finally{
em.close();
}
}
}
二、双向的一对多关联
对于一对多关联,在jpa中应该尽量映射成双向关联而不是单向,而且尽量不要让1的一端来控制关联关系,而应该使用多的一端来控制关联关系,双向的1-N和N-1是完全相同的两种关联关系,两端都需要增加对关联属性的访问,N的一端增加应用到关联实体的属性,1的一端增加结合属性,该集合记录了它所关联的全部实体。
下面通过代码实例说明双向的一对多关联
1的一端(公司)的实体类代码:
@Entity
@Table(name="Employee")
public class Employee {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
/**
* 员工姓名
*/
@Column(name="name" ,length=20)
private String name;
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 Compony getCompony() {
return compony;
}
public void setCompony(Compony compony) {
this.compony = compony;
}
}
代码中使用了mappedBy属性,表示不应该通过员工(Employee)实体控制关系。
下面是N端(员工)的代码:
@Entity
@Table(name="Employee")
public class Employee {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
/**
* 员工姓名
*/
@Column(name="name" ,length=20)
private String name;
@ManyToOne(fetch=FetchType.EAGER,targetEntity=Employee.class,cascade=CascadeType.ALL)
@JoinColumn(name="componyId",nullable=true)
private Compony compony;
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 class test {
static final EntityManagerFactory emf=Persistence.createEntityManagerFactory("qs");
public static void main(String[] args){
EntityManager em=emf.createEntityManager();
Employee em1=new Employee();
em1.setName("陈丽娜");
Employee em2=new Employee();
em2.setName("杨政");
Compony compony=new Compony();
compony.setName("信息技术提高班");
try{
//开启事务
em.getTransaction().begin();
//为公司添加两个关联实体
//由于公司不控制关联关系
em1.setCompony(compony);
em2.setCompony(compony);
em.persist(em1);
em.persist(em2);
em.getTransaction().commit();
}finally{
em.close();
}
}
}
其实这么看来 JPA 也没有什么陌生的,不过就是在操作实体的时候要时刻保持清醒知道实体是处于什么状态的。