首先,Hibernate默认开启懒加载策略!是Hibernate推崇的一种提高性能的方法!
get()与load()都用于加载已存在id值的对象到内存中
区别:
get()
get()马上发出SQL语句查询相关对象
get()操作的对象如果不存在,抛NullPointerException
get()返回的是原始对象
load()
load()使用Hibernate的懒加载策略,除非调用到对象的非id属性,否则不会发出查询语句
load()加载的对象如果不存在,抛ObjectNotFountException
load()返回的是1个代理对象
如果懒加载策略被取消(lazy=false),则load()会立即发出SQL查询语句,而且不再返回代理对象
懒加载---重点
1. 实体类一定要有无参构造方法!
2. 任何一个实体类都必须有唯一的数据库标识值(逻辑主键,不要用业务主键)
3. 数据库标识不允许修改---所以不能将业务属性定义为主键
4. 主键-非空、唯一
5. 懒加载只有在使用load()的前提下,且lazy=true,且session未关闭前才会生效
6. 如果session已经关闭,使用懒加载机制会发生异常:LazyInitializationException: could not initialize proxy - no Session
7. get()与懒加载机制无关,即使lazy=true,懒加载也不会生效
8. 懒加载实现原理---代理对象
9. *只要调用user中除了getId()之外的其他任何方法(只要是在User类中定义的方法,包括从Object中继承的toString()),
hibernate就认为使用到了对象的非id属性,这是就会立即发出select语句从数据库获取对象属性!
注意:即使是调用setId()都会促发hibernate发出select查询!但是,一般都不使用setId(),因为:修改主键值是什么行为呢?
10. 延迟加载的好处:只需要加载到对象,而不需要对象的属性,使用懒加载机制就能避免发出select查询语句,这样提高了程序执行效率!!!
关联映射时,就用load(),不用hibernate发出查询语句!
11. 延迟发出:
hibernate的性能调整方案!
比如:insert\delete 语句在commit之后才被发出(一批数据与数据库进行通信)--这就是延迟,这就是性能调整!
建议多用load(),充分利用hibernate的性能调整!
12. get时,如果对象不存在,主键id不存在,在get时会马上抛空指针异常
load时,对象不存在,会延迟到真正加载对象(发出select语句时)才会抛异常,即异常被延迟抛出,因为前面还没有访问数据库,怎么抛异常呢!
13. 如果lazy=false,则不会有代理对象!
package org.leadfar.hibernate.model;
import java.util.Date;
import junit.framework.TestCase;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class UserTest04 extends TestCase {
//session未关闭,lazy=true,使用load()懒加载机制生效。
//直到真正使用到对象非id属性时才会发出select语句
//或者说调用了User类中非getId()的任何方法,hibernate就会发出select语句
//注意:调用setId()也会促使hibernate发出select语句,但是修改主键为其它值,则会发生异常!
public void testUser_Lazy01() throws Exception {
//默认读取类路径根目录下的hibernate.cfg.xml配置文件
Configuration cfg = new Configuration().configure();
//创建SessionFactory
SessionFactory sfactory = cfg.buildSessionFactory();
//创建Hibernate Session
Session session = sfactory.openSession();
try {
//开启事务
session.beginTransaction();
//使用load方法获取对象属性,当lazy="true"时,访问id属性是不会发出select语句的
//因为id作为主键,在load方法中已经指明了,所以hibernate不用访问数据库就能直到id值是多少
User user =(User)session.load(User.class, 109);
System.out.println(user.getId());
System.out.println(user.getName());
//提交事务
session.getTransaction().commit();
} catch(Exception e) {
e.printStackTrace();
//出现异常,回滚事务
session.getTransaction().rollback();
} finally {
//关闭session
session.close();//session关闭之后,user对象处于离线Detached状态
}
}
//session未关闭,lazy=false,懒加载不会生效
public void testUser_Lazy02() throws Exception {
//默认读取类路径根目录下的hibernate.cfg.xml配置文件
Configuration cfg = new Configuration().configure();
//创建SessionFactory
SessionFactory sfactory = cfg.buildSessionFactory();
//创建Hibernate Session
Session session = sfactory.openSession();
try {
//开启事务
session.beginTransaction();
//使用load方法获取对象属性,当lazy="false"时,hibernate会马上发出select语句,即不会延迟加载
//相当于使用get()方法没有延迟加载机制
//使用get()即使lazy=true,懒加载机制也不会生效。
//懒加载只有在使用load的前提下,且lazy=true才会生效
User user =(User)session.load(User.class, 109);
System.out.println(user.getId());
System.out.println(user.getName());
//提交事务
session.getTransaction().commit();
} catch(Exception e) {
e.printStackTrace();
//出现异常,回滚事务
session.getTransaction().rollback();
} finally {
//关闭session
session.close();//session关闭之后,user对象处于离线Detached状态
}
}
//使用懒加载机制,在session关闭之后,访问对象属性,会发生LazyInitializationException异常
//session关闭之后才真正访问到对象非id属性时,这时再加载就会发生异常!
//该异常发生的前提:1.lazy=true 2.session有效期间没有发出select语句
//3,在session关闭后,才需要hibernate发出select语句,但是此时session已经关闭,所以异常发生了!
public void testUser_Lazy03() throws Exception {
//默认读取类路径根目录下的hibernate.cfg.xml配置文件
Configuration cfg = new Configuration().configure();
//创建SessionFactory
SessionFactory sfactory = cfg.buildSessionFactory();
//创建Hibernate Session
Session session = sfactory.openSession();
User user = null;
try {
//开启事务
session.beginTransaction();
//使用load方法获取对象属性,当lazy="false"时,hibernate会马上发出select语句,即不会延迟加载
//相当于使用get()方法没有延迟加载机制
//使用get()即使lazy=true,懒加载机制也不会生效。
//懒加载只有在使用load的前提下,且lazy=true,且session未关闭前才会生效
user =(User)session.load(User.class, 109);
System.out.println(user.getId());
//提交事务
session.getTransaction().commit();
} catch(Exception e) {
e.printStackTrace();
//出现异常,回滚事务
session.getTransaction().rollback();
} finally {
//关闭session
session.close();//session关闭之后,user对象处于离线Detached状态
}
//session关闭之后,懒加载失效
System.out.println(user.getName());
System.out.println(user.getBirthday());
//org.hibernate.LazyInitializationException: could not initialize proxy - no Session
}
//加载对象的时候不能使用setId()方法改变对象的id主键值,否则引发异常
//当然,使用setId()修改为同一个值不会引发异常,会促发hibernate发出select语句!
public void testUser_Lazy04() throws Exception {
//默认读取类路径根目录下的hibernate.cfg.xml配置文件
Configuration cfg = new Configuration().configure();
//创建SessionFactory
SessionFactory sfactory = cfg.buildSessionFactory();
//创建Hibernate Session
Session session = sfactory.openSession();
User user = null;
try {
//开启事务
session.beginTransaction();
//加载对象时,修改了id主键,commit的时候会报异常
user =(User)session.load(User.class, 109);
System.out.println(user.getId());
user.setId(110);//setId()方法会促发hibernate发出select语句!!!!!
//user.setId(110);--->引发异常,主键值被修改了
//注意:setId()调用会不论异常发生与否,hibernate都会发出select语句查询数据库并通过setX()设置对象属性
//提交事务
session.getTransaction().commit();
} catch(Exception e) {
e.printStackTrace();
//出现异常,回滚事务
session.getTransaction().rollback();
} finally {
//关闭session
session.close();//session关闭之后,user对象处于离线Detached状态
}
//即使调用setId()引发了异常,下面一样可以访问到对象属性值
//同时,发生异常的话,下面获取到的id值一定是新值
//如果还是以前的值,那么修改的id值就是同一个值,即没有发生异常!!!
System.out.println(user.getId());
System.out.println(user.getName());
System.out.println(user.getMoney());
}
//get()加载对象,如果对象不存在时,即使没有使用到对象的非id属性,也会抛异常
//因为一旦get,就会发出select语句
public void testUser_Lazy05() throws Exception {
//默认读取类路径根目录下的hibernate.cfg.xml配置文件
Configuration cfg = new Configuration().configure();
//创建SessionFactory
SessionFactory sfactory = cfg.buildSessionFactory();
//创建Hibernate Session
Session session = sfactory.openSession();
User user = null;
try {
//开启事务
session.beginTransaction();
//加载对象时,主键不存在,执行到下一句时,异常抛出
user =(User)session.get(User.class, 200);
System.out.println(user.getMoney());
System.out.println(user.getId());
//提交事务
session.getTransaction().commit();
} catch(Exception e) {
e.printStackTrace();
//出现异常,回滚事务
session.getTransaction().rollback();
} finally {
//关闭session
session.close();//session关闭之后,user对象处于离线Detached状态
}
}
//load()加载对象,如果对象不存在时,又没有使用到对象的其他非id属性,不会发生异常
//因为没有发出select语句查询数据库,所以不会有异常发生
//如果使用到了其他属性,则异常会延迟到真正发select语句后才会抛出!
public void testUser_Lazy06() throws Exception {
//默认读取类路径根目录下的hibernate.cfg.xml配置文件
Configuration cfg = new Configuration().configure();
//创建SessionFactory
SessionFactory sfactory = cfg.buildSessionFactory();
//创建Hibernate Session
Session session = sfactory.openSession();
User user = null;
try {
//开启事务
session.beginTransaction();
//加载对象时,修改了id主键,commit的时候会报异常
user =(User)session.load(User.class, 200);
System.out.println(user.getId());
//提交事务
session.getTransaction().commit();
} catch(Exception e) {
e.printStackTrace();
//出现异常,回滚事务
session.getTransaction().rollback();
} finally {
//关闭session
session.close();//session关闭之后,user对象处于离线Detached状态
}
}
}