Hibernate中用注解配置一对多双向关联和多对一单向关联
Hibernate提供了Hibernate Annotations扩展包,使用注解完成映射。在Hibernate3.3之前,需单独下载注解开发包
配置持久化类
配置关联关系
下面我们先从多对一单向关联关系讲起,多对一单向关联就是在多的一方植入一的一方的主键作为外键,下面我们先进行初始配置,
在配置的过程中我们会遇到一个问题 就是无论用load还是get都不会出现延迟加载,那么我们应该如何设置为要延迟加载,这样做的好处是可以在用的时候才加载对应的信息,节约内存
hibernate中,延迟加载大致可以分为两类,一类是延迟属性加载,另一类是延迟关联实体加载。
普通属性:分两种情况,一种是集合属性,一种是非集合属性(如String、Integer......)
集合属性的延迟加载通过PersistentSet、 PersistentList、PersistentBag、PersistentMap、PersistentSortedMap、 PersistentSortedSet作为代理类来实现,代理类中保存了session以及owner属性,owner属性表示了集合属性所属的one 侧的实体。
非集合类属性的延迟加载相对比较复杂。仅通过@Basic(fetch = FetchType.LAZY)注解是无法实现延迟加载的。需要让实体实现FieldHandled接口,声明FieldHandler属性,通过拦截器 原理注入对应的FieldHandler属性,起到类似于上述代理类的作用,FieldHandler同样也保持了session,以及需要延迟加载的属 性。
我们发现对非集合属性即时设置了@Basic(fetch = FetchType.LAZY)仍无法实现延迟加载,可以看生成的sql语句
接下来 我们会对一对多单向关联进行测试,验证对集合类属性,是否可以起到延迟加载的功能
注意:不可以对有关联关系的属性设置@Transient
配置多对一的单向关联关系 示例
1 package cn.happy.entity; 2 3 import javax.persistence.Basic; 4 import javax.persistence.Column; 5 import javax.persistence.Entity; 6 import javax.persistence.FetchType; 7 import javax.persistence.GeneratedValue; 8 import javax.persistence.GenerationType; 9 import javax.persistence.Id; 10 import javax.persistence.JoinColumn; 11 import javax.persistence.ManyToOne; 12 import javax.persistence.SequenceGenerator; 13 import javax.persistence.Table; 14 import javax.persistence.Transient; 15 16 @Entity 17 @Table(name = "EMP") 18 public class Emp { 19 @Id 20 @Column(name = "EMPNO") 21 @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "emp_num") 22 @SequenceGenerator(name = "emp_num", sequenceName = "emp_num_id", allocationSize = 1, initialValue = 1) 23 private Integer empNo; 24 25 @Column(name = "EMPNAME") 26 private String empName; 27 28 @ManyToOne() 29 @JoinColumn(name = "DEPTNO") 30 /*@Basic(fetch=FetchType.LAZY)*/ 31 private Dept dept; 32 33 34 public Emp() { 35 super(); 36 } 37 38 public Emp(Integer empNo, String empName) { 39 super(); 40 this.empNo = empNo; 41 this.empName = empName; 42 } 43 44 public Integer getEmpNo() { 45 return empNo; 46 } 47 48 public void setEmpNo(Integer empNo) { 49 this.empNo = empNo; 50 } 51 52 public String getEmpName() { 53 return empName; 54 } 55 56 public void setEmpName(String empName) { 57 this.empName = empName; 58 } 59 60 public Dept getDept() { 61 return dept; 62 } 63 64 public void setDept(Dept dept) { 65 this.dept = dept; 66 } 67 }
1 package cn.happy.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.GeneratedValue; 10 import javax.persistence.GenerationType; 11 import javax.persistence.Id; 12 import javax.persistence.JoinColumn; 13 import javax.persistence.OneToMany; 14 import javax.persistence.SequenceGenerator; 15 import javax.persistence.Table; 16 import javax.persistence.Transient; 17 18 import org.hibernate.annotations.Cascade; 19 20 @Entity 21 @Table(name = "DEPT") 22 public class Dept { 23 @Id 24 @Column(name = "DEPTNO") 25 @GeneratedValue(strategy=GenerationType.SEQUENCE,generator="dept_num") 26 @SequenceGenerator(name="dept_num",sequenceName="dept_num_no",allocationSize=1,initialValue=1) 27 private Integer deptNo; 28 29 @Column(name = "DEPTNAME") 30 private String deptName; 31 32 33 public Integer getDeptNo() { 34 return deptNo; 35 } 36 37 public void setDeptNo(Integer deptNo) { 38 this.deptNo = deptNo; 39 } 40 41 public String getDeptName() { 42 return deptName; 43 } 44 45 public void setDeptName(String deptName) { 46 this.deptName = deptName; 47 } 48 }
1 /** 2 * 注解测试多对一映射 员工表(多)对应部门表(一)的映射,即只在员工表中植入部门表的信息 3 * */ 4 @Test 5 public void manytooneSingle(){ 6 7 /** 8 * 查询操作 9 * **/ 10 /*SessionFactory sf=new AnnotationConfiguration().configure().buildSessionFactory(); 11 Session session = sf.openSession(); 12 13 Emp emp=(Emp)session.load(Emp.class, 4); 14 15 System.out.println(emp.getEmpName()+"\t"+emp.getDept().getDeptName());*/ 16 17 /** 18 * 添加操作 19 * **/ 20 SessionFactory sf=new AnnotationConfiguration().configure().buildSessionFactory(); 21 Session session = sf.openSession(); 22 Transaction tx = session.beginTransaction(); 23 Dept dept = (Dept)session.load(Dept.class, 3); 24 25 Emp emp=new Emp(); 26 emp.setEmpName("户梦艳"); 27 emp.setEmpNo(001); 28 emp.setDept(dept); 29 30 Emp emp2=new Emp(); 31 emp2.setEmpName("户梦艳2"); 32 emp2.setEmpNo(002); 33 emp2.setDept(dept); 34 35 session.save(emp); 36 session.save(emp2); 37 tx.commit(); 38 session.close(); 39 40 41 }
一对多双单向配置
1 package cn.happy.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.GeneratedValue; 10 import javax.persistence.GenerationType; 11 import javax.persistence.Id; 12 import javax.persistence.JoinColumn; 13 import javax.persistence.OneToMany; 14 import javax.persistence.SequenceGenerator; 15 import javax.persistence.Table; 16 import javax.persistence.Transient; 17 18 19 @Entity 20 @Table(name="Dept") 21 public class Dept { 22 @Id 23 @GeneratedValue(strategy=GenerationType.SEQUENCE,generator="dept_num") 24 @SequenceGenerator(name="dept_num",sequenceName="dept_num_no",allocationSize=1,initialValue=1) 25 private Integer deptNo; 26 @Column 27 private String deptName; 28 29 30 @OneToMany(cascade={CascadeType.ALL}) 31 @JoinColumn(name="deptno") 32 private Set<Emp> emps=new HashSet<Emp>(); 33 34 public Set<Emp> getEmps() { 35 return emps; 36 } 37 38 public void setEmps(Set<Emp> emps) { 39 this.emps = emps; 40 } 41 42 public Integer getDeptNo() { 43 return deptNo; 44 } 45 46 public void setDeptNo(Integer deptNo) { 47 this.deptNo = deptNo; 48 } 49 50 public String getDeptName() { 51 return deptName; 52 } 53 54 public void setDeptName(String deptName) { 55 this.deptName = deptName; 56 } 57 }
1 package cn.happy.entity; 2 3 import javax.persistence.Basic; 4 import javax.persistence.Column; 5 import javax.persistence.Entity; 6 import javax.persistence.FetchType; 7 import javax.persistence.GeneratedValue; 8 import javax.persistence.GenerationType; 9 import javax.persistence.Id; 10 import javax.persistence.JoinColumn; 11 import javax.persistence.ManyToOne; 12 import javax.persistence.SequenceGenerator; 13 import javax.persistence.Table; 14 import javax.persistence.Transient; 15 16 import org.hibernate.bytecode.javassist.FieldHandled; 17 import org.hibernate.bytecode.javassist.FieldHandler; 18 19 20 @Entity 21 @Table(name = "EMP") 22 public class Emp { 23 24 25 26 @Id 27 @GeneratedValue(strategy=GenerationType.SEQUENCE,generator="emp_num") 28 @SequenceGenerator(name="emp_num",sequenceName="emp_num_no",allocationSize=1,initialValue=9) 29 private Integer empNo; 30 31 @Column 32 private String empName; 33 34 35 // @ManyToOne 36 // @JoinColumn(name="deptno") 37 // @Basic(fetch=FetchType.LAZY) 38 // private Dept dept; 39 // 40 // public Dept getDept() { 41 // return dept; 42 // } 43 // 44 // public void setDept(Dept dept) { 45 // this.dept = dept; 46 // } 47 48 public Emp() { 49 super(); 50 } 51 52 public Emp(Integer empNo, String empName) { 53 super(); 54 this.empNo = empNo; 55 this.empName = empName; 56 } 57 58 public Integer getEmpNo() { 59 return empNo; 60 } 61 62 public void setEmpNo(Integer empNo) { 63 this.empNo = empNo; 64 } 65 66 public String getEmpName() { 67 return empName; 68 } 69 70 public void setEmpName(String empName) { 71 this.empName = empName; 72 } 73 74 75 }
1 /** 2 * 测试一对多单向添加操作 3 * */ 4 @Test 5 public void insertOneToManySingle(){ 6 Emp emp=new Emp(); 7 emp.setEmpName("李小鹏"); 8 9 Emp emp2=new Emp(); 10 emp2.setEmpName("王想想"); 11 12 Dept dept=new Dept(); 13 dept.setDeptName("教务部"); 14 //设置级联操作 15 dept.getEmps().add(emp); 16 dept.getEmps().add(emp2); 17 18 session.save(dept); 19 tx.commit(); 20 System.out.println("insert ok"); 21 22 }
1 /** 2 * 测试一对多单向查询操作 3 * */ 4 @Test 5 public void selectOneToManySingle(){ 6 Dept dept = (Dept)session.load(Dept.class, 1); 7 System.out.println("======================"); 8 System.out.println("部门名称:"+dept.getDeptName()); 9 System.out.println("======================="); 10 //体现了延迟加载 11 for (Emp emp : dept.getEmps()) { 12 System.out.println("雇员名称:"+emp.getEmpName()); 13 } 14 //Emp emp = (Emp)session.load(Emp.class, 1); 15 16 17 }
一对多双向配置
1 package cn.happy.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.GeneratedValue; 10 import javax.persistence.GenerationType; 11 import javax.persistence.Id; 12 import javax.persistence.JoinColumn; 13 import javax.persistence.OneToMany; 14 import javax.persistence.SequenceGenerator; 15 import javax.persistence.Table; 16 import javax.persistence.Transient; 17 18 19 @Entity 20 @Table(name="Dept") 21 public class Dept { 22 @Id 23 @GeneratedValue(strategy=GenerationType.SEQUENCE,generator="dept_num") 24 @SequenceGenerator(name="dept_num",sequenceName="dept_num_no",allocationSize=1,initialValue=1) 25 private Integer deptNo; 26 @Column 27 private String deptName; 28 29 30 @OneToMany(mappedBy="dept",cascade={CascadeType.ALL}) 31 32 private Set<Emp> emps=new HashSet<Emp>(); 33 34 public Set<Emp> getEmps() { 35 return emps; 36 } 37 38 public void setEmps(Set<Emp> emps) { 39 this.emps = emps; 40 } 41 42 public Integer getDeptNo() { 43 return deptNo; 44 } 45 46 public void setDeptNo(Integer deptNo) { 47 this.deptNo = deptNo; 48 } 49 50 public String getDeptName() { 51 return deptName; 52 } 53 54 public void setDeptName(String deptName) { 55 this.deptName = deptName; 56 } 57 }
1 package cn.happy.entity; 2 3 import javax.persistence.Basic; 4 import javax.persistence.Column; 5 import javax.persistence.Entity; 6 import javax.persistence.FetchType; 7 import javax.persistence.GeneratedValue; 8 import javax.persistence.GenerationType; 9 import javax.persistence.Id; 10 import javax.persistence.JoinColumn; 11 import javax.persistence.ManyToOne; 12 import javax.persistence.SequenceGenerator; 13 import javax.persistence.Table; 14 import javax.persistence.Transient; 15 16 import org.hibernate.bytecode.javassist.FieldHandled; 17 import org.hibernate.bytecode.javassist.FieldHandler; 18 19 20 @Entity 21 @Table(name = "EMP") 22 public class Emp { 23 24 25 26 @Id 27 @GeneratedValue(strategy=GenerationType.SEQUENCE,generator="emp_num") 28 @SequenceGenerator(name="emp_num",sequenceName="emp_num_no",allocationSize=1,initialValue=9) 29 private Integer empNo; 30 31 @Column 32 private String empName; 33 34 35 @ManyToOne 36 @JoinColumn(name="deptno") 37 @Basic(fetch=FetchType.LAZY) 38 private Dept dept; 39 40 public Dept getDept() { 41 return dept; 42 } 43 44 public void setDept(Dept dept) { 45 this.dept = dept; 46 } 47 48 public Emp() { 49 super(); 50 } 51 52 public Emp(Integer empNo, String empName) { 53 super(); 54 this.empNo = empNo; 55 this.empName = empName; 56 } 57 58 public Integer getEmpNo() { 59 return empNo; 60 } 61 62 public void setEmpNo(Integer empNo) { 63 this.empNo = empNo; 64 } 65 66 public String getEmpName() { 67 return empName; 68 } 69 70 public void setEmpName(String empName) { 71 this.empName = empName; 72 } 73 74 75 }
1 /** 2 * 双向一对多的添加操作 3 * */ 4 @Test 5 public void oneToManyDouble(){ 6 Dept dept=new Dept(); 7 dept.setDeptName("财务部"); 8 9 Emp emp=new Emp(); 10 emp.setEmpName("邹乐"); 11 emp.setDept(dept); 12 13 Emp emp2=new Emp(); 14 emp2.setEmpName("范子阳"); 15 emp2.setDept(dept); 16 17 18 dept.getEmps().add(emp); 19 dept.getEmps().add(emp2); 20 21 session.save(dept); 22 tx.commit(); 23 } 24
1 /** 2 * 双向一对多的查询操作 3 * */ 4 @Test 5 public void selectOneToManyDouble(){ 6 7 Dept dept = (Dept)session.load(Dept.class, 1); 8 System.out.println("部门名称:"+dept.getDeptName()); 9 for (Emp emp : dept.getEmps()) { 10 System.out.println("职工姓名:"+emp.getEmpName()); 11 } 12 13 System.out.println("=================================================="); 14 15 Emp emp = (Emp)session.load(Emp.class, 1); 16 System.out.println("职工姓名:"+emp.getEmpName()+"\t部门名称:"+emp.getDept().getDeptName()); 17 } 18