一·关联关系(多对多)
举例:一个员工可以开发多个项目,一个项目也可以被多个员工开发
1.1单向
Project实体
public class Project { private Integer proid; private String proname; }
Project.hbm.xml文件
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="cn.hibernate.mapping.manytomany.entity"> <class name="Project" table="Project" schema="wy"> <id name="proid" column="proid"> <generator class="native"/> </id> <property name="proname" column="proname"></property> </class> </hibernate-mapping>
Employee 实体
再该实体中植入项目的实体
public class Employee { private Integer empid; private String empname; private Set<Project> projects = new HashSet<Project>(); }
Employeehbm.xml 文件
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="cn.hibernate.mapping.manytomany.entity"> <class name="Employee" table="Employee" schema="wy" lazy="false"> <id name="empid" column="empid"> <generator class="native"/> </id> <property name="empname" column="empname"></property> <set name="projects" table="REmpPro" cascade="save-update"> <key column="REmpNo"></key> <many-to-many class="Project" column="RProNo"></many-to-many> </set> </class> </hibernate-mapping>
<set>标签:
name:被植入的set集合的属性名
table:多对多的中间表名称
cascade:(级联)当执行修改和添加时hibernate框架会自动将关联的实体做对应的操作
key column:表示中间表中员工的外键
class:set集合中的属性
column:集合中元素在中间表的外键
单测:
@Test public void add(){ Session session = HibernateUtil.getSession(); Employee emp1=new Employee(); emp1.setEmpname("刘黑子"); Project pro1=new Project(); pro1.setProname("项目1"); Project pro2=new Project(); pro2.setProname("项目2"); emp1.getProjects().add(pro1); emp1.getProjects().add(pro2); session.save(emp1); HibernateUtil.closeSession(); System.out.println("add ok!"); }
1.2双向
在单向的基础上,将项目实体类中也加入员工的实体类集合
修改后的Project 实体
public class Project { private Integer proid; private String proname; private Set<Employee> projects = new HashSet<Employee>(); }
修改后的Project.hbm.xml文件
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="cn.hibernate.mapping.manytomany.entity"> <class name="Project" table="Project" schema="wy"> <id name="proid" column="proid"> <generator class="native"/> </id> <property name="proname" column="proname"></property> <set name="employees" table="REmpPro"> <key column="RProNo"></key> <many-to-many class="Project" column="REmpNo"></many-to-many> </set> </class> </hibernate-mapping>
单测:
@Test public void sel(){ Session session = HibernateUtil.getSession(); Employee employee = session.get(Employee.class, 6); for (Project item:employee.getProjects()){ System.out.println(item.getProname()); } HibernateUtil.closeSession(); System.out.println("sel ok!"); }
二.延迟加载
2.1类级别的延迟加载
立即检索:立即加载检索方法指定的对象,立即发送SQL
延迟检索:延迟加载检索方法指定的对象.在使用具体的属性时,再进行加载,才发送SQL
注意:无论<class>元素的lazy属性是true还是false,Session的get()方法及Query的list()方法在类级别总是使用立即检索策略
同样继续使用上述的实体
将加载方式改为立即加载
单测:
@Test public void sel(){ Session session = HibernateUtil.getSession(); Employee employee = session.load(Employee.class, 6); HibernateUtil.closeSession(); System.out.println("sel ok!"); }
结果:
发送了sql
将加载方式修改为延迟加载
单测
@Test public void sel(){ Session session = HibernateUtil.getSession(); Employee employee = session.load(Employee.class, 6); HibernateUtil.closeSession(); System.out.println("sel ok!"); }
结果:
没有sql
2.2一对多和多对多的延迟加载
继续使用上述实体
不延迟加载
Debug:
@Test
public void sel(){
Session session = HibernateUtil.getSession();
Employee employee = session.get(Employee.class, 6);
HibernateUtil.closeSession();
System.out.println("sel ok!");
}
加强延迟加载
Debug
Test public void sel(){ Session session = HibernateUtil.getSession(); Employee employee = session.load(Employee.class, 6); HibernateUtil.closeSession(); System.out.println("sel ok!"); }
结果:
当访问employee的属性时不会加载其中的set<project>集合。当访问set集合的属性时也不会加载,当访问set集合中元素时才会查询