实体Company:公司。
实体Employee:雇员。
Company和Employee是一对多关系。那么在JPA中,如何表示一对多的双向关联呢?
JPA使用@OneToMany和@ManyToOne来标识一对多的双向关联。一端(Company)使用@OneToMany,多端(Employee)使用@ManyToOne。
在JPA规范中,一对多的双向关系由多端(Employee)来维护。就是说多端(Employee)为关系维护端,负责关系的增删改查。一端(Company)则为关系被维护端,不能维护关系。
一端(Company)使用@OneToMany注释的mappedBy="company"属性表明Company是关系被维护端。
多端(Employee)使用@ManyToOne和@JoinColumn来注释属性company,@ManyToOne表明Employee是多端,@JoinColumn设置在employee表中的关联字段(外键)。
Company.java如下:
1 package com.cndatacom.jpa.entity; 2 3 import java.util.HashSet; 4 import java.util.Set; 5 6 import javax.persistence.CascadeType; 7 import javax.persistence.Column; 8 import javax.persistence.Entity; 9 import javax.persistence.FetchType; 10 import javax.persistence.GeneratedValue; 11 import javax.persistence.Id; 12 import javax.persistence.OneToMany; 13 import javax.persistence.Table; 14 15 16 /** 17 * 公司 18 * @author Luxh 19 */ 20 @Entity 21 @Table(name="company") 22 public class Company { 23 24 @Id 25 @GeneratedValue 26 private Long id; 27 28 /**公司名称*/ 29 @Column(name="name",length=32) 30 private String name; 31 32 /**拥有的员工*/ 33 @OneToMany(mappedBy="company",cascade=CascadeType.ALL,fetch=FetchType.LAZY) 34 //拥有mappedBy注解的实体类为关系被维护端 35 //mappedBy="company"中的company是Employee中的company属性 36 private Set<Employee> employees = new HashSet<Employee>(); 37 38 39 public Long getId() { 40 return id; 41 } 42 43 public void setId(Long id) { 44 this.id = id; 45 } 46 47 public String getName() { 48 return name; 49 } 50 51 public void setName(String name) { 52 this.name = name; 53 } 54 55 public Set<Employee> getEmployees() { 56 return employees; 57 } 58 59 public void setEmployees(Set<Employee> employees) { 60 this.employees = employees; 61 } 62 63 }
Employee.java如下:
1 package com.cndatacom.jpa.entity; 2 3 import javax.persistence.CascadeType; 4 import javax.persistence.Column; 5 import javax.persistence.Entity; 6 import javax.persistence.GeneratedValue; 7 import javax.persistence.Id; 8 import javax.persistence.JoinColumn; 9 import javax.persistence.ManyToOne; 10 import javax.persistence.Table; 11 12 13 /** 14 * 雇员 15 * @author Luxh 16 */ 17 @Entity 18 @Table(name="employee") 19 public class Employee { 20 21 @Id 22 @GeneratedValue 23 private Long id; 24 25 /**雇员姓名*/ 26 @Column(name="name") 27 private String name; 28 29 /**所属公司*/ 30 @ManyToOne(cascade={CascadeType.MERGE,CascadeType.REFRESH},optional=false)//可选属性optional=false,表示company不能为空 31 @JoinColumn(name="company_id")//设置在employee表中的关联字段(外键) 32 private Company company; 33 34 public Company getCompany() { 35 return company; 36 } 37 38 public void setCompany(Company company) { 39 this.company = company; 40 } 41 42 public Long getId() { 43 return id; 44 } 45 46 public void setId(Long id) { 47 this.id = id; 48 } 49 50 public String getName() { 51 return name; 52 } 53 54 public void setName(String name) { 55 this.name = name; 56 } 57 }
简单的测试用例:
1 package com.cndatacom.jpa.test; 2 3 import java.util.HashSet; 4 import java.util.Set; 5 6 import javax.persistence.EntityManager; 7 import javax.persistence.EntityManagerFactory; 8 import javax.persistence.Persistence; 9 10 import org.junit.After; 11 import org.junit.Before; 12 import org.junit.Test; 13 14 import com.cndatacom.jpa.entity.Author; 15 import com.cndatacom.jpa.entity.Book; 16 import com.cndatacom.jpa.entity.Company; 17 import com.cndatacom.jpa.entity.Employee; 18 19 20 public class TestOneToMany { 21 22 EntityManagerFactory emf = null; 23 24 @Before 25 public void before() { 26 //根据在persistence.xml中配置的persistence-unit name 创建EntityManagerFactory 27 emf = Persistence.createEntityManagerFactory("myJPA"); 28 } 29 30 @After 31 public void after() { 32 //关闭EntityManagerFactory 33 if(null != emf) { 34 emf.close(); 35 } 36 } 37 38 39 40 @Test 41 public void testAddCompany() { 42 EntityManager em = emf.createEntityManager(); 43 em.getTransaction().begin(); 44 45 //new 一个公司 46 Company c = new Company(); 47 c.setName("Sun"); 48 49 //new 一个雇员 50 Employee e1 = new Employee(); 51 e1.setName("陆小凤"); 52 //设置所属的公司,必须要设置(实体属性注解使用了optional=false,雇员必须要属于公司,所以公司属性不能为空) 53 e1.setCompany(c); 54 55 //new 一个雇员 56 Employee e2 = new Employee(); 57 e2.setName("花满楼"); 58 //设置所属的公司,必须要设置(实体属性注解使用了optional=false,雇员必须要属于公司,所以公司属性不能为空) 59 e2.setCompany(c); 60 61 //把雇员放到集合中 62 Set<Employee> employees = new HashSet<Employee>(); 63 employees.add(e1); 64 employees.add(e2); 65 66 //设置公司拥有的雇员 67 c.setEmployees(employees); 68 69 em.persist(c); 70 em.getTransaction().commit(); 71 em.close(); 72 73 } 74 75 76 }
Employee表的结构:
可以看到Employee表有一个外键字段company_id,就是@JoinColumn(name="company_id")指定的。