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
配置多对一的单向关联关系 示例
package cn.happy.entity;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Transient;
@Entity
@Table(name = "EMP")
public class Emp {
@Id
@Column(name = "EMPNO")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "emp_num")
@SequenceGenerator(name = "emp_num", sequenceName = "emp_num_id", allocationSize = 1, initialValue = 1)
private Integer empNo;
@Column(name = "EMPNAME")
private String empName;
@ManyToOne()
@JoinColumn(name = "DEPTNO")
/*@Basic(fetch=FetchType.LAZY)*/
private Dept dept;
public Emp() {
super();
}
public Emp(Integer empNo, String empName) {
super();
this.empNo = empNo;
this.empName = empName;
}
public Integer getEmpNo() {
return empNo;
}
public void setEmpNo(Integer empNo) {
this.empNo = empNo;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public Dept getDept() {
return dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
}
package cn.happy.entity;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Transient;
import org.hibernate.annotations.Cascade;
@Entity
@Table(name = "DEPT")
public class Dept {
@Id
@Column(name = "DEPTNO")
@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="dept_num")
@SequenceGenerator(name="dept_num",sequenceName="dept_num_no",allocationSize=1,initialValue=1)
private Integer deptNo;
@Column(name = "DEPTNAME")
private String deptName;
public Integer getDeptNo() {
return deptNo;
}
public void setDeptNo(Integer deptNo) {
this.deptNo = deptNo;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
}
/**
* 注解测试多对一映射 员工表(多)对应部门表(一)的映射,即只在员工表中植入部门表的信息
* */
@Test
public void manytooneSingle(){
/**
* 查询操作
* **/
/*SessionFactory sf=new AnnotationConfiguration().configure().buildSessionFactory();
Session session = sf.openSession();
Emp emp=(Emp)session.load(Emp.class, 4);
System.out.println(emp.getEmpName()+"\t"+emp.getDept().getDeptName());*/
/**
* 添加操作
* **/
SessionFactory sf=new AnnotationConfiguration().configure().buildSessionFactory();
Session session = sf.openSession();
Transaction tx = session.beginTransaction();
Dept dept = (Dept)session.load(Dept.class, 3);
Emp emp=new Emp();
emp.setEmpName("户梦艳");
emp.setEmpNo(001);
emp.setDept(dept);
Emp emp2=new Emp();
emp2.setEmpName("户梦艳2");
emp2.setEmpNo(002);
emp2.setDept(dept);
session.save(emp);
session.save(emp2);
tx.commit();
session.close();
}
一对多双单向配置
package cn.happy.entity;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Transient;
@Entity
@Table(name="Dept")
public class Dept {
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="dept_num")
@SequenceGenerator(name="dept_num",sequenceName="dept_num_no",allocationSize=1,initialValue=1)
private Integer deptNo;
@Column
private String deptName;
@OneToMany(cascade={CascadeType.ALL})
@JoinColumn(name="deptno")
private Set<Emp> emps=new HashSet<Emp>();
public Set<Emp> getEmps() {
return emps;
}
public void setEmps(Set<Emp> emps) {
this.emps = emps;
}
public Integer getDeptNo() {
return deptNo;
}
public void setDeptNo(Integer deptNo) {
this.deptNo = deptNo;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
}
package cn.happy.entity;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Transient;
import org.hibernate.bytecode.javassist.FieldHandled;
import org.hibernate.bytecode.javassist.FieldHandler;
@Entity
@Table(name = "EMP")
public class Emp {
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="emp_num")
@SequenceGenerator(name="emp_num",sequenceName="emp_num_no",allocationSize=1,initialValue=9)
private Integer empNo;
@Column
private String empName;
// @ManyToOne
// @JoinColumn(name="deptno")
// @Basic(fetch=FetchType.LAZY)
// private Dept dept;
//
// public Dept getDept() {
// return dept;
// }
//
// public void setDept(Dept dept) {
// this.dept = dept;
// }
public Emp() {
super();
}
public Emp(Integer empNo, String empName) {
super();
this.empNo = empNo;
this.empName = empName;
}
public Integer getEmpNo() {
return empNo;
}
public void setEmpNo(Integer empNo) {
this.empNo = empNo;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
}
/**
* 测试一对多单向添加操作
* */
@Test
public void insertOneToManySingle(){
Emp emp=new Emp();
emp.setEmpName("李小鹏");
Emp emp2=new Emp();
emp2.setEmpName("王想想");
Dept dept=new Dept();
dept.setDeptName("教务部");
//设置级联操作
dept.getEmps().add(emp);
dept.getEmps().add(emp2);
session.save(dept);
tx.commit();
System.out.println("insert ok");
}
/**
* 测试一对多单向查询操作
* */
@Test
public void selectOneToManySingle(){
Dept dept = (Dept)session.load(Dept.class, 1);
System.out.println("======================");
System.out.println("部门名称:"+dept.getDeptName());
System.out.println("=======================");
//体现了延迟加载
for (Emp emp : dept.getEmps()) {
System.out.println("雇员名称:"+emp.getEmpName());
}
//Emp emp = (Emp)session.load(Emp.class, 1);
}
一对多双向配置
package cn.happy.entity;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Transient;
@Entity
@Table(name="Dept")
public class Dept {
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="dept_num")
@SequenceGenerator(name="dept_num",sequenceName="dept_num_no",allocationSize=1,initialValue=1)
private Integer deptNo;
@Column
private String deptName;
@OneToMany(mappedBy="dept",cascade={CascadeType.ALL})
private Set<Emp> emps=new HashSet<Emp>();
public Set<Emp> getEmps() {
return emps;
}
public void setEmps(Set<Emp> emps) {
this.emps = emps;
}
public Integer getDeptNo() {
return deptNo;
}
public void setDeptNo(Integer deptNo) {
this.deptNo = deptNo;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
}
package cn.happy.entity;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Transient;
import org.hibernate.bytecode.javassist.FieldHandled;
import org.hibernate.bytecode.javassist.FieldHandler;
@Entity
@Table(name = "EMP")
public class Emp {
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="emp_num")
@SequenceGenerator(name="emp_num",sequenceName="emp_num_no",allocationSize=1,initialValue=9)
private Integer empNo;
@Column
private String empName;
@ManyToOne
@JoinColumn(name="deptno")
@Basic(fetch=FetchType.LAZY)
private Dept dept;
public Dept getDept() {
return dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
public Emp() {
super();
}
public Emp(Integer empNo, String empName) {
super();
this.empNo = empNo;
this.empName = empName;
}
public Integer getEmpNo() {
return empNo;
}
public void setEmpNo(Integer empNo) {
this.empNo = empNo;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
}
/**
* 双向一对多的添加操作
* */
@Test
public void oneToManyDouble(){
Dept dept=new Dept();
dept.setDeptName("财务部");
Emp emp=new Emp();
emp.setEmpName("邹乐");
emp.setDept(dept);
Emp emp2=new Emp();
emp2.setEmpName("范子阳");
emp2.setDept(dept);
dept.getEmps().add(emp);
dept.getEmps().add(emp2);
session.save(dept);
tx.commit();
}
/**
* 双向一对多的查询操作
* */
@Test
public void selectOneToManyDouble(){
Dept dept = (Dept)session.load(Dept.class, 1);
System.out.println("部门名称:"+dept.getDeptName());
for (Emp emp : dept.getEmps()) {
System.out.println("职工姓名:"+emp.getEmpName());
}
System.out.println("==================================================");
Emp emp = (Emp)session.load(Emp.class, 1);
System.out.println("职工姓名:"+emp.getEmpName()+"\t部门名称:"+emp.getDept().getDeptName());
}