Hibernate学习——之延迟加载

在使用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: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方法以非延迟加载的方式解决的办法之一



你可能感兴趣的:(Hibernate,延迟加载)