面试题: get、load方法区别?
get: 及时加载,只要调用get方法立刻向数据库查询
load:默认使用懒加载,当用到数据的时候才向数据库查询。
懒加载:(lazy)
概念:当用到数据的时候才向数据库查询,这就是hibernate的懒加载特性。
目的:提供程序执行效率!
lazy 值
true 使用懒加载
false 关闭懒加载
extra (在集合数据懒加载时候提升效率)
在真正使用数据的时候才向数据库发送查询的sql;
如果调用集合的size()/isEmpty()方法,只是统计,不真正查询数据!
懒加载异常
n Session关闭后,不能使用懒加载数据!
n 如果session关闭后,使用懒加载数据报错:
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
如何解决session关闭后不能使用懒加载数据的问题?
// 方式1: 先使用一下数据
//dept.getDeptName();
// 方式2:强迫代理对象初始化
Hibernate.initialize(dept);
// 方式3:关闭懒加载
设置lazy=false;
// 方式4: 在使用数据之后,再关闭session!
package loaderman.b_one2Many; public class Employee { private int empId; private String empName; private double salary; // 【多对一】员工与部门 private Dept dept;; public int getEmpId() { return empId; } public void setEmpId(int empId) { this.empId = empId; } public String getEmpName() { return empName; } public void setEmpName(String empName) { this.empName = empName; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } public Dept getDept() { return dept; } public void setDept(Dept dept) { this.dept = dept; } }
package loaderman.b_one2Many; import java.util.HashSet; import java.util.Set; public class Dept { private int deptId; private String deptName; // 【一对多】 部门对应的多个员工 private Set<Employee> emps = new HashSet<Employee>(); public int getDeptId() { return deptId; } public void setDeptId(int deptId) { this.deptId = deptId; } public String getDeptName() { return deptName; } public void setDeptName(String deptName) { this.deptName = deptName; } public Set<Employee> getEmps() { return emps; } public void setEmps(Set<Employee> emps) { this.emps = emps; } }
package loaderman.b_one2Many; import org.hibernate.Hibernate; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; import org.hibernate.classic.Session; import org.junit.Test; public class App { private static SessionFactory sf; static { sf = new Configuration() .configure() .addClass(Dept.class) .addClass(Employee.class) // 测试时候使用 .buildSessionFactory(); } //1. 主键查询,及区别 @Test public void get_load() { Session session = sf.openSession(); session.beginTransaction(); Dept dept = new Dept(); // get: 及时查询 // dept = (Dept) session.get(Dept.class, 9); // System.out.println(dept.getDeptName()); // load,默认懒加载, 及在使用数据的时候,才向数据库发送查询的sql语句! dept = (Dept)session.load(Dept.class, 9); // 方式1: 先使用一下数据 //dept.getDeptName(); // 方式2:强迫代理对象初始化 Hibernate.initialize(dept); // 方式3:关闭懒加载 session.getTransaction().commit(); session.close(); // 在这里使用 System.out.println(dept.getDeptName()); } //1. 主键查询,及区别 @Test public void set() { Session session = sf.openSession(); session.beginTransaction(); Dept dept = (Dept) session.get(Dept.class, 10); System.out.println(dept.getDeptName()); System.out.println("------"); System.out.println(dept.getEmps().isEmpty()); // SQL session.getTransaction().commit(); session.close(); } }
<?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="loaderman.b_one2Many"> <class name="Dept" table="t_dept" > <id name="deptId"> <generator class="native"></generator> </id> <property name="deptName" length="20"></property> <!-- 集合属性,默认使用懒加载 lazy true 懒加载 extra 懒加载(智能) false 关闭懒加载 --> <set name="emps" lazy="extra"> <key column="dept_id"></key> <one-to-many class="Employee"/> </set> </class> </hibernate-mapping>
<?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="loaderman.b_one2Many"> <class name="Employee" table="t_employee"> <id name="empId"> <generator class="native"></generator> </id> <property name="empName" length="20"></property> <property name="salary" type="double"></property> <many-to-one name="dept" column="dept_id" class="Dept"></many-to-one> </class> </hibernate-mapping>