您的位置:首页 > 其它

Hibernate学习——之延迟加载

2015-08-10 20:19 459 查看
在使用load()方法加载持久化对象是,它返回的是一个未初始化的代理(即未从数据库中抓取数据对象的数据),直到调用代理的某个方法时Hibernate才会访问数据库。而非延迟加载过程中,Hibernate会直接访问数据库,并不会使用代理对象。

而恰恰是因为这种情况,测试load方法会有一些不同的问题出现

@Test
public void testload01() {
Session session = null;
try {
session = HibernateUtil.openSession();
session.beginTransaction();
User user = (User)session.load(User.class, 33);
System.out.println(user.getId());
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtil.closeSession(session);
}
}id为33的数据在数据库中并不存在,但以此方法却能输出33.
而将输出语句换为System.out.println(user.getNickname());
则会抛出org.hibernate.ObjectNotFoundException异常: No row with the given identifier exists: [com.norman.model.User#33]

这是因为输出id时id是从代理中读取的,而而输出Nickname时则需要从数据库中抓取数据,数据库中并没有这个对象,但是user并不是空。

使用get()方法则是直接从数据库中抓取数据,因为不存这个对象,所以抛出的是空指针异常。

当使用userDao的方式加载数据时,同样会出现一些不同于mybatis框架下load()方法的问题:

//UserDao文件中load方法
public User load(int id){
Session session = null;
User user = new User();
try {
session = HibernateUtil.openSession();
session.beginTransaction();
user = (User)session.load(User.class, id);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtil.closeSession(session);
}
return user;
}
单元测试文件方法
@Test
public void testLoad() {
UserDao userDao = new UserDao();
User user = userDao.load(3);
System.out.println(user);
}这种方法并不能输出user对象,而是出现异常:
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:165)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:286)
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java
4000
:185)
at com.norman.model.User_$$_jvst1b4_0.toString(User_$$_jvst1b4_0.java)
at java.lang.String.valueOf(Unknown Source)
at java.io.PrintStream.println(Unknown Source)
at com.norman.test.TestLazy.testLoad(TestLazy.java:16)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

这是因为使用load方法延迟加载,返回时只是一个代理对象仅仅只有一个id。在真正调用的时候Session已经关闭,此时需要从数据库中读取数据时Session已经关闭所以会抛出上述异常。使用get方法以非延迟加载的方式解决的办法之一
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: