實體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")指定的。