Hibernate中get方法get和load的区别方法的区别

hibernate延迟加载(load、get区别) - 思想有多远,就能走多远 - ITeye技术网站
博客分类:
由于Spring控制的Hibernate的生命周期只针对数据层和服务层,而未管理到表现层,所以在表现层使用延时加载会出现the owning Session was closed或者no session or session was closed的异常信息。针对这一点,可以通过hibernate filter的方式来解决。
在WEB.xml文件中配置filter.
&!-- hibernate session filter --&
&filter-name&OpenSessionInViewFilter&/filter-name&
&filter-class&
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
&/filter-class&
&filter-mapping&
&filter-name&OpenSessionInViewFilter&/filter-name&
&url-pattern&*.do&/url-pattern&
&/filter-mapping&
我们的系统架构是struts+spring+hibernate,struts跟spring的整合是在struts-config.xml里加了个plugin(注:这个plugin似乎对编码也有影响,需要用spring的过滤器、自己写的过滤器达不到效果,以后测试完了,分析下)
&plug-in
className="org.springframework.WEB.struts.ContextLoaderPlugIn"&
&set-property property="contextConfigLocation"
value="/WEB-INF/classes/applicationContext.xml" /&
&/plug-in&
在WEB.xml中配置hibernateFilter 后,还需要在struts-config.xml里把plugin去掉,在WEB.xml里加上如下代码:
&!--Spring ApplicationContext--&
&context-param&
&param-name&contextConfigLocation&/param-name&
&param-value&/WEB-INF/classes/applicationContext.xml&/param-value&
&/context-param&
&listener&
&listener-class&
org.springframework.web.context.ContextLoaderListener
&/listener-class&
&/listener&
这样配置之后如果没有配置事务,是有问题的。不能进行update和insert操作了。
怎么办呢?只需要在filter中加入一个参数
&init-param&
&&& &param-name&singleSession&/param-name&
&&& &param-value&true&/param-value&
&/init-param&
就可以了,当然这样 每次访问dao都会新开个session,对性能的影响还是比较大的。最好的办法当然是配置事务了。
配置说完了,下面介绍下延迟加载的优缺点,即getHibernateTemplate.load() 和get()之间的区别
主要的地方:
getHibernateTemplate.load() 存在延迟加载问题。
getHibernateTemplate.get() 不存在此问题,不采用lazy机制的。
1 当记录不存在时候,get方法返回null,load方法产生异常,即get()可以取空的数据集,但load()不行。&
2 load方法可以返回实体的代理类,get方法则返回真是的实体类
3 load方法可以充分利用hibernate的内部缓存和二级缓存中的现有数据,而get方法仅仅在内部缓存中
进行数据查找,如果没有发现数据則将越过二级缓存,直接调用SQL查询数据库。
4 也许别人把数据库中的数据修改了,load如何在缓存中找到了数据,则不会再访问数据库,而get则
会返回最新数据。
浏览: 17533 次
来自: 北京
兄弟,源码挂上撒...有关数据更新(不一定用到update方法) - 一梦三四年 - ITeye技术网站
在介绍hibernate的更新之前,我们先来看看session的两个方法。load和get方法;这两个方法是获取数据的根据对象的id值;
先看两段代码。load和get的方法都含有两个参数,前者是得到的对象类型。后者是一个可序列化的值,说白了也就是你要获取数据库里面对应的主键的值,你的主键如果是id。你获取的是第一条记录那么则是一,如果你的主键是name。你就写上某个名字。然后获取这个名字对应的数据记录。
当我们执行下面两条语句的时候,我们会发现第一条报错。而第二条是没有什么问题的。
但是如果我们把两个里面的打印语句都写到commit之前的时候。我们发现两个都不会报错了。
public void testload(){
Session session =
session =sessionFactory.getCurrentSession();
session.beginTransaction();
t=(Teacher) session.load(Teacher.class, 1);
session.getTransaction().commit();
System.out.println(t.getName());
public void testget(){
Session session =
session =sessionFactory.getCurrentSession();
session.beginTransaction();
t=(Teacher) session.get(Teacher.class, 1);
session.getTransaction().commit();
System.out.println(t.getName());
这里面是有原因的。当用load获取的时候,其实执行load语句只是将对象置入到内存中。而执行get方法的时候。不但将对象放入到了内存而且。对象执行了sql语句。对象的值已经在getName方法执行已经赋值了。而load方法。在执行getName方法的时候才执行sql语句,从数据库里面获取相关的记录。当我们在执行getName方法前后加上时间的时候。我们得到时间差的话我们会发现,我load这种情况下getName费许多的时间。而get这种情况几乎没有费什么时间。
那么为什么在提交之后,load得到getName的方法会出错呢。那是因为提交完之后。当前的session自动关闭了。当然这是getCurrentSession的情况下。而再去调用镀锡的getName方法的时候。session对象关闭了。相等于缓存中没有对应的记录了。只有数据库和内存中有。此时再无获取getname的时候没有中间桥梁session。那么肯定出错。而get方法的话。因为已经在get方法执行的时候将数据赋值给了对象。那么我们获取的时候直接从内存里面拿去好了。用不着经由session去访问数据库。所以不会出错。
下面来具体谈谈更新数据的情况
更新数据我们的第一反应是从数据库里面讲数据拿出来然后改变某些值,然后再调用update的方法完成操作。这种方法是对的。但是不是只有这一种方法的。我们还有不通过调用update方法就可以完成更新。update方法里面传入的对象。一定要有主键的值。并且主键的记录一定可以在数据库里面找得到,这样才不会报错的。所以我们可以先不用从数据库里面拿去对象。而是先定义一个对象。之后再给此对象赋值。然后更新此对象。如果给的值在数据库中含有那么对应的记录也可以然后更新。
1.常规方法先从数据库里面拿取,然后更新
Session session =
session =sessionFactory.getCurrentSession();
session.beginTransaction();
t=(Teacher) session.get(Teacher.class, 1);
t.setName("wsx");
session.update(t)
session.getTransaction().commit();
2.先创建一个对象,然后给其赋值。再更新。
Session session =
session =sessionFactory.getCurrentSession();
session.beginTransaction();
t=new Teacher();
t.setName("wsx");
session.update(t)
session.getTransaction().commit();
以上这两种方法都可以完成更新的操作。
而以下的这种方法也是可以完成更新的。并且没有用到update方法;
Session session =
session =sessionFactory.getCurrentSession();
session.beginTransaction();
t=(Teacher) session.get(Teacher.class, 1);
t.setName("wsx");
session.getTransaction().commit();
我们仔细瞧下来会发现。它与第一个方法的不同之处就是没有用到update方法。难道这也行吗?嗯。我肯定的告诉你。
接下来我们探究其道理。
当我们执行get方法的时候,其实在内存中,缓存session中,数据库中都有对应的Teacher对象。而当我们改变其内存中对象的名字的时候。我们再提交的话,其实是数据库事务会去检测,内存中的session对象的值和缓存session中的值是否一致,不一致的话,那么则提交更新。
更新数据时遇到的问题。
我们会发现更新数据的时候。如果一个表中有五个字段,而我们只更新一个字段比较说更新年龄字段的时候。那么我们会从打印日志中惊奇的发现我们的其他几个字段也更新了。这种更新方式是很不友好的。代价也很巨大。也许本来你只需更新一个年龄的值。而其他字段里面有一篇文章。那么你只简简单单更新一个年龄却引起一篇文章的更新。
根据这一问题,我们有一些几个解决问题的办法
1.通过annotation在某个不需要更新的字段的get方法之前加上@column(updatable=false);
@Column(updatable=false)
public String getName() {
这种方法的缺点是这个字段永远不会更新。这个我们一想就感觉很不灵活。也许某一天这个字段需要更新。但是也有永不更新的情况。这个很多。比如一个银行的名字。等待。
2.在xml配置文件里面class加上dynamic——update=true;
&hibernate-mapping&
&class name="com.bjsxt.hibernate.Student"
dynamic-update="true"&
&id name="id" column="id"/&
&property name="name" /&
&property name="age" /&
&/hibernate-mapping&
这样就会自动更新。但是我们的自动更新某些需要更新的列的话,我们必须要在同一个session中。不同的session。找不到参考依据的话,那么也会集体更新的。
public void testupdate1(){
Session session =
session =sessionFactory.getCurrentSession();
session.beginTransaction();
t=(Teacher) session.get(Teacher.class, 1);
t.setName("wsx");
session.update(t);
session.getTransaction().commit();
t.setName("wsx1");
Session session1 =
session1 =sessionFactory.getCurrentSession();
session1.beginTransaction();
session.update(t);
session.getTransaction().commit();
第一个session的update方法只会更新name。而第二个全部属性都会更新;
3.用hql语句。你需要更新那个列,那么则写成相应的形式;
public void testupdate2(){
Session session =
session =sessionFactory.getCurrentSession();
session.beginTransaction();
Query q=session.createQuery("update tablename set name='wsx' where id=1 ");
q.executeUpdate();
session.getTransaction().commit();
我们很多情况下用到第三种方式。 好了更新就讲到这儿。
浏览: 98268 次
来自: 广州
哥们,源码注释都是乱码。你用什么编码格式的?我试过bg2312 ...
三大框架其实没有,hibernate
ssh这也不是三大框 ...
chairmanMao 写道楼主解释的真是太详细了,
对大家有 ...
楼主解释的真是太详细了,
2楼说的不无道理,我这几天好好研究下mysql和其他数据库相关 ...get与load方法的区别_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
get与load方法的区别
上传于||文档简介
&&g​e​t​与​l​o​a​d​方​法​的​区​别
阅读已结束,如果下载本文需要使用
想免费下载本文?
你可能喜欢您现在的位置:&&>>&&>>&&>>&&>>&正文
Hibernate中load和get的区别
  Hibernate中Session.load/get方法均可以根据指定的实体类和id从数据库读取记录,并返回与之对应的实体对象。其区别在于:
  1.get()方法直接返回实体类,load()方法可以返回实体的代理类实例。
  2.hibernate load是采用延迟机制(当lazy属性为true时) 而get不采用延迟机制(get语句马上读库)
  3.找不到符合条件的数据 get方法将返回null
  load将会报出ObjectNotFoundExcepion
  4.get支持多态查询,load只有在lazy=false的情况下才支持多态查询
  所谓多态查询,就是可以明确区分加载的是什么类型的对象,load采用代理机制无法支持
  延迟加载:Hibernate尽量延迟向数据库发送sql,它自己有一个缓冲区,先把sql放在里面,最后一起发送,减少网络开销和数据库开销。
  load方法原理:
  当对象.hbm.xml配置文件元素的lazy属性设置为true时,调用load()方法时则返回持久对象的代理类实例,此时的代理类实例是由运行时动态生成的类,该代理类实例包括原目标对象的所有属性和方法,该代理类实例的属性除了ID不为null外,所在属性为null值,查看日志并没有Hibernate SQL输出,说明没有执行查询操作,当代理类实例通过getXXX()方法获取属性值时,Hiberante才真正执行数据库查询操作。
  注意:
  01.StudentEh s=(StudentEh)session.load(StudentEh.class,10);
  03.System.out.println(s.getId());
  这两条语句同样不会产生sql语句,因为session.load后会在hibernate的一级缓存里存放一个map对象,该map的key就是id的值,但是当你getId()时,它是从一级缓存里取map的key值,而不去执行数据库查询。
  当对象.hbm.xml配置文件元素的lazy属性设置为false时,调用load()方法则是立即执行数据库并直接返回实体类,并不返回代理类。而调用get()方法时不管lazy为何值,都直接返回实体类。
  get方法原理:
  get方法,hibernate会确认一下该id对应的数据是否存在,首先在session缓存中查找,然后在二级缓存中查找,还没有就查数据库,数据库中没有就返回null。
  get方法如果在session缓存中找到了该id对应的对象,如果刚好该对象前面是被代理过的,如被load方法使用过,或者被其他关联对象延迟加载过,那么返回的还是原先的代理对象,而不是实体类对象,如果该代理对象还没有加载实体数据(就是id以外的其他属性数据),那么它会查询二级缓存或者数据库来加载数据,但是返回的还是代理对象,只不过已经加载了实体数据。
  总结描述:
  如果使用load方法,hibernate认为该id对应的对象(数据库记录)在数据库中是一定存在的,所以它可以放心的使用代理来延迟加载该对象。在用到对象中的其他属性数据时才查询数据库,但是万一数据库中不存在该记录,那没办法,只能抛异常,所说的load方法抛异常是指在使用该对象的数据时,数据库中不存在该数据时抛异常,而不是在创建这个对象时。由于session中的缓存对于hibernate来说是个相当廉价的资源,所以在load时会先查一下session缓存看看该id对应的对象是否存在,不存在则创建代理。所以如果你知道该id在数据库中一定有对应记录存在就可以使用load方法来实现延迟加载。
  而对于get方法,hibernate一定要获取到真实的数据,否则返回null。
  自己在开发过程中遇到的问题:
  我们用MyEclipse hibernate工具通过数据库生成的DAO类,它的findById方法是用的session.get()方法,这是即时获得pojo对象,如果是load方法,在执行完load后如果关闭了session,那在接下来用到这个pojo对象时就会报session已关闭的错误。
【责编:ivy】
?&[]?&[]?&[]?&[]?&[]?&[]?&[]?&[]?&[]?&[]
相关产品和培训
 友情推荐链接
 认证培训
 专题推荐
 ? ? ? ? ? ? ? ? ? ?
 今日更新
?&?&?&?&?&?&?&?&?&?&
 社区讨论
 博客论点
 频道精选
 Java 频道导航Hibernate的get与load方法 -
- ITeye技术网站
1.在懒加载方面的区别:
示例代码如下:
public class HibernateTest {
public static void main(String[] args) {
User user = getUser(1);
System.out.println(user.getName());
static User getUser(int id){
Session session =
session = HibernateSessionFactory.getSession();
session.beginTransaction();
① User user =(User)session.load(User.class, id);
② User user =(User)session.get(User.class, id);
session.getTransaction().commit();
session.close();
执行代码① 使用load方法:
执行结果如下:
log4j:WARN No appenders could be found for logger (org.hibernate.cfg.Environment).
log4j:WARN Please initialize the log4j system properly.
Exception in thread "main" org.hibernate.LazyInitializationException: could not initialize proxy - the owning Session was closed
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:56)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:98)
at org.hibernate.proxy.CGLIBLazyInitializer.intercept(CGLIBLazyInitializer.java:158)
at po.User$$EnhancerByCGLIB$$6b9e0a10.getName(&generated&)
at po.HibernateTest.main(HibernateTest.java:10)
将抛出懒加载异常
执行代码②使用get方法
执行结果如下:
Hibernate: select user0_.id as id0_0_, user0_.name as name0_0_, user0_.age as age0_0_ from mytest.user user0_ where user0_.id=?
执行结果正常输出。
2. 空值处理方面(所查询的值不存在):
示例代码如下:
Session session =
session = HibernateSessionFactory.getSession();
session.beginTransaction();
①User user =(User)session.load(User.class, 2);
②User user =(User)session.get(User.class, 2);
System.out.println(user);
System.out.println(user.getName());
session.getTransaction().commit();
session.close();
执行代码① 使用load方法:
执行结果如下:
Hibernate: select user0_.id as id0_0_, user0_.name as name0_0_, user0_.age as age0_0_ from mytest.user user0_ where user0_.id=?Exception in thread "main" org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [po.User#2] at org.hibernate.ObjectNotFoundException.throwIfNull(ObjectNotFoundException.java:27) at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:65) at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:98) at org.hibernate.proxy.CGLIBLazyInitializer.intercept(CGLIBLazyInitializer.java:158) at po.User$$EnhancerByCGLIB$$6b9e0a10.toString(&generated&) at java.lang.String.valueOf(Unknown Source) at java.io.PrintStream.print(Unknown Source) at java.io.PrintStream.println(Unknown Source) at po.HibernateTest.getUser(HibernateTest.java:19) at po.HibernateTest.main(HibernateTest.java:9)
在①处将抛出ObjectNotFoundException异常,该异常在执行load方法发现不存在该对象时就抛出
使用load方法不会立即访问数据库,而是返回一个代理对象,只有在使用时,才回去访问数据库。
执行代码②使用get方法
执行结果如下:
Hibernate: select user0_.id as id0_0_, user0_.name as name0_0_, user0_.age as age0_0_ from mytest.user user0_ where user0_.id=?nullException in thread "main" java.lang.NullPointerException at po.HibernateTest.getUser(HibernateTest.java:20) at po.HibernateTest.main(HibernateTest.java:9)
在执行get方法时,发现查询结果为空,将null赋给user,当执行user.getUser()方法③时会抛出空指针异常。
3.其他区别
load方法可以返回实体的代理类,get方法则返回真是的实体类。
load方法可以充分利用hibernate的内部缓存和二级缓存中的现有数据,而get方法仅仅在内部缓存中进行数据查找,如果没有发现数据則将越过二级缓存,直接调用SQL查询数据库。
也许别人把数据库中的数据修改了,load如何在缓存中找到了数据,则不会再访问数据库,而get则会返回最新数据。
yang7551735
浏览: 27788 次
来自: 北京
, 来赞一个~
总结的太好了,忍不住登录上来支持一下。
方法根本不存在于栈中}

我要回帖

更多关于 get load 区别 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信