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方法以非延遲加載的方式解決的辦法之一



發佈了29 篇原創文章 · 獲贊 5 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章