Hibernate中用注解配置一对多双向关联和多对一单向关联
Hibernate提供了Hibernate Annotations扩展包,使用注解完成映射。在Hibernate3.3之前,需单独下载注解开发包
配置持久化类
配置关联关系
下面我们先从多对一单向关联关系讲起,多对一单向关联就是在多的一方植入一的一方的主键作为外键,下面我们先进行初始配置,
在配置的过程中我们会遇到一个问题 就是无论用load还是get都不会出现延迟加载,那么我们应该如何设置为要延迟加载,这样做的好处是可以在用的时候才加载对应的信息,节约内存
中,延迟加载大致可以分为两类,一类是延迟属性加载,另一类是延迟关联实体加载。
普通属性:分两种情况,一种是集合属性,一种是非集合属性(如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 @Entity17 @Table(name = "EMP")18 public class Emp {19 @Id20 @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 @Entity21 @Table(name = "DEPT")22 public class Dept {23 @Id24 @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 @Entity20 @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 @Column27 private String deptName;28 29 30 @OneToMany(cascade={CascadeType.ALL})31 @JoinColumn(name="deptno")32 private Setemps=new HashSet ();33 34 public Set getEmps() {35 return emps;36 }37 38 public void setEmps(Set 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 @Entity21 @Table(name = "EMP")22 public class Emp {23 24 25 26 @Id27 @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 @Column32 private String empName;33 34 35 // @ManyToOne36 // @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 @Entity20 @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 @Column27 private String deptName;28 29 30 @OneToMany(mappedBy="dept",cascade={CascadeType.ALL})31 32 private Setemps=new HashSet ();33 34 public Set getEmps() {35 return emps;36 }37 38 public void setEmps(Set 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 @Entity21 @Table(name = "EMP")22 public class Emp {23 24 25 26 @Id27 @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 @Column32 private String empName;33 34 35 @ManyToOne36 @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