Hibernate 延迟加载原理

    如何简单的理解延迟加载?开发中常见的org.hibernate.LazyInitializationException no session错误又是怎么产生的?下面通过一个简单的例子来解析一下。

load VS. get

    load是Hibernate利用延迟加载获取对象的方法,当调用load时返回的是一个代理对象,并且该对象只包含主键ID。只有当你想主动获取该对象的其他非主键属性时,才会去数据库中获取对应的属性返回。如果这时该对象对应的数据库记录被删除了或不存在则会报抛出ObjectNotFoundException异常。

    get是Hibernate获取对象的一个普通方法,没有使用延迟加载,调用get时hibernate直接返回数据库中对应的记录信息。如果数据库中不存在该对象的记录,会抛出空指针异常。

程序所示

load:

   1:  Session session = null;
   2:          try {
   3:              session = HibernateUtil.openSession();
   4:              //使用load,利用延迟加载获取对象其他属性
   5:              Object object = session.load(Member.class, 121L);
   6:              String mobile = ((Member) object).getMobile();//<---这里当调用getMobile()时,才会去数据库查询对应的记录
   7:              System.out.println(mobile);
   8:          } catch (HibernateException e) {
   9:              e.printStackTrace();
  10:          } finally {
  11:              if (session != null)
  12:                  session.close();
  13:          }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

get:

   1:  Session session = null;
   2:          try {
   3:              session = HibernateUtil.openSession();
   4:              //使用get,直接从数据库中查询对应的记录
   5:              Object object = session.get(Member.class, 121L);
   6:              String mobile = ((Member) object).getMobile();//<---这里没有使用延迟加载直接获取mobile
   7:              System.out.println(mobile);
   8:          } catch (HibernateException e) {
   9:              e.printStackTrace();
  10:          } finally {
  11:              if (session != null)
  12:                  session.close();
  13:          }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

使用延迟加载时,常见的org.hibernate.LazyInitializationException no session异常,又是怎么产生的呢?

这是因为当使用延迟加载获取对象属性时如果这时session已经关闭,则无法进行数据库操作,就会报出上述异常,我们用程序模拟一下:

get:

   1:  Session session = null;
   2:          try {
   3:              session = HibernateUtil.openSession();
   4:              //使用get,直接从数据库中查询对应的记录
   5:              Object object = session.get(Member.class, 121L);
   6:              session.close();//这时关闭session
   7:              String mobile = ((Member) object).getMobile();//可以正常获取,因为mobile是从对象中直接获取的
   8:              System.out.println(mobile);
   9:          } catch (HibernateException e) {
  10:              e.printStackTrace();
  11:          } 

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

load:

   1:  Session session = null;
   2:          try {
   3:              session = HibernateUtil.openSession();
   4:              //使用get,直接从数据库中查询对应的记录
   5:              Object object = session.load(Member.class, 121L);
   6:              session.close();//这时关闭session
   7:              String mobile = ((Member) object).getMobile();//使用load的情况,获取mobile是从数据库中查询的,但此时session已经关闭,故调用getMobile时会抛出org.hibernate.LazyInitializationException no session异常
   8:              System.out.println(mobile);
   9:          } catch (HibernateException e) {
  10:              e.printStackTrace();
  11:          } 

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

上一篇:Spring Boot 系列(一)快速入门


下一篇:Struts入门(二) 配置文件的讲解