Hibernate 半深入懒加载与懒加载代理类

来源:互联网 发布:阿里弹性云 编辑:程序博客网 时间:2024/05/29 03:58

标签(空格分隔): 后端技术学习


前言

在hibernate的使用中,为了减少对数据库的访问,对于存在关联关系映射表使用的时候,我们可以使用懒加载的方式,让hibernate帮我查询单个对象信息的同时,暂缓查询它所关联的另一些对象的信息,当我们真正的使用它所管理的对象的时候后再帮我们查询关联对象。同时懒加载的方式也是hibernate为我们默认选择的方式。虽然懒加载为我们带来了减少数据库查询的好处,但是在使用的过程中如果是对hibernate理解不够容易出现难以寻找的问题。

引入

在课堂上老师引导我们,了解hibernate的查询方式的时候,介绍了使用懒加载的时候session.load()查询会返回的内容并不是我们真正的POJO实体对象,实际上返回的是实体对象的代理类。它跟能够在我调用POJO的getXX()方法的时候使用代理的方式帮我们进行数据库的查询实现懒加载,然后返回我们需要查寻得关联对象。接下来我们细细理解一下半深入懒加载与懒加载代理类。


session.load()讲解

API指出 session.load()查询总是返回一个并非直接对应数据库行的假对象(代理类)。查出来的假对象它所有的属性也没有被正式的初始化。对它所有的操作,直到事务提交时才进行对它之前所有操作的合并,然后执行数据库语句。
同时在事务提交的时候,如果数据库中原本并没有假对象对应的行则会抛出ObjectNotFoundException
如果是没有使用事务load()查询,则在进行session.save(“假对象”),session.saveOrUpdate(“假对象”)的时候则会提示org.hibernate.PersistentObjectException: uninitialized proxy passed to save()的异常。原因仍然假对象(代理类)懒加载。

例如 session.load()

coderInput

Stock stock = (Stock)session.load(Stock.class, new Integer(2));           StockTransaction stockTransactions = new StockTransaction();           //set stockTransactions detail           stockTransactions.setStock(stock);           session.save(stockTransactions);

Output

Hibernate:insert into mkyong.stock_transaction (...)values (?, ?, ?, ?, ?, ?)

注意:实际上并不是 session.load()的所有查询都返回的是POJO实体对象的代理类,只有在POJO对象的映射文件*.hbm.xml中指定了懒加载(即没有设置lazy="false")的时候才会返回POJO实体对象的代理类。否则不是代理类。


session.get讲解

相对于session.load(),session.get()就非常直接,使用它的每一次查询操作返回的都是对应着数据库中的真实对象,这个对象代表的是数据库中真实的一行,也不是代理类。
真是因为这个原因session.get()的查询它是不支持懒加载的。如果查询的类有关联对象,它会同时将关联对象统统查出来。
如果在数据库的查询中找不到对应搜索条件的行则返回null,通过由于在session.get()返回的不是代理类,在session.close()后它不会被销毁,不会为空。

例如 session.get()

codeInput

Stock stock = (Stock)session.get(Stock.class, new Integer(2));           StockTransaction stockTransactions = new StockTransaction();           //set stockTransactions detail           stockTransactions.setStock(stock);           session.save(stockTransactions);

Output

Hibernate:select ... from mkyong.stock stock0_where stock0_.STOCK_ID=?Hibernate:insert into mkyong.stock_transaction (...)values (?, ?, ?, ?, ?, ?)

代理类

代理类是通过动态代理的方式创建,是由Hibernate框架帮我们创建的,这也是Hibernate框架的面相切面的特点。Hibernate在通过*.hbm.xml文件帮我们让数据库和正真实体之间建立联系,同时又为我们提供了关联关系映射的功能。在使用懒加载模式下的时候使用session.load等查询的时候,会返回给我们一个代理类。代理类的所有属性都会在真正使用的时候才会去加载。如果仅仅只是执行了查询语句,没有任何的修改访问操作,实际上最后的事务提交时Hibernate是没有进行数据库查询的。
同时非常重要的一点是Hibernate的会在代理类相关联session关闭的时候,会同时销毁代理类。也就是说如果你所使用的引用是代理类,你执行了session.close(),你再去访问这个代理类就会的到这样的org.hibernate.LazyInitializationException: could not initialize proxy - no Session报错提示。
但是如果是使用的session.get(),或者是关闭了懒加载则不会使用到代理类,不会出现上述问题。同时也享受不到Hibernate智能的数据库优化。

原创粉丝点击