|
1.lazy是什么
Hibernate中的lazy(默认true)网上很多人都把它叫 懒人机制,主要是告诉Hibernate获取数据时 在什么时候去读库; 2.lazy的影响 就我做的例子看来。lazy只对session.Load和获取级联信息(1对1,1对多,多对多)时起作用; 3.Session读取信息的方式(Load和级联信息) 3.1延迟加载(lazy=true) 当我用Load或者是该bean中有级联对象的时候,执行Load的时候并不去读库,但Load还是会返回一个对象给你,但该对象中只有主键, 读库是在你使用该对象的其他属性的时候去读的; 3.2非延迟加载(lazy=false) 在执行Load的时候就会去把库中的数据读取出来; 4.出问题的地方 由于我们要保证Session要及时关闭,即Load完之后,我们要执行session.close操作;但是当lazy为真的时候,在Load的时候并是直接去读库,而是等使用里面属性的时候才去读库。那么到你打印信息的时候就会报session已经被关闭的错误。 现在你是否要问,那直接把lazy设置成false不就可以了吗?现在看下面的例子吧: 5.例子(要调用Hibernate的show_sql为真) 5.1lazy不设置,或者设置为true的时候(Load的情况) 5.1.1代码 Session session = HibernateSessionFactory.getSession();//获取session Tabuser tabuser = (Tabuser) session.load(Tabuser.class, new Long(1));//获取数据 HibernateSessionFactory.closeSession();//关闭session System.out.println(tabuser.getUserid()); System.out.println(tabuser.getUsername()); 5.1.2问题 这时会提示第5行代码出错the owning Session was closed; 这是由于session已经被你关闭了; 5.1.3解决 这时的解决办法有四种: a)设置class标签的lazy=false;(这种方式不推荐使用) b)在第三行之前加入Hibernate.initialize(tabuser); c)使用get方法(推荐使用这个,《get和load的区别》) d)使用spring(网上看到的:用filter[由于spring我还不懂,现在不讲这种方式,可能这种方式会更好]) 5.2一对多映射中set标签下 lazy不设置,或者设置为true的时候(获取级联信息的情况1对多) 5.2.1代码 Session session = HibernateSessionFactory.getSession(); Tabuser tabuser = (Tabuser) session.get(Tabuser.class, new Long(1)); HibernateSessionFactory.closeSession(); System.out.println(tabuser.getUserid()); System.out.println(tabuser.getUsername()); System.out.println(tabuser.getPostlist().iterator().next().getPostid()); 5.2.2问题 这时第6行会报错no session or session was closed; 这是由于session已经被你关闭了; 5.2.3解决方法有三种: a)set标签下设置lazy=false;(这种方式不可行) b)在第三行之前加入Hibernate.initialize(tabuser.getPostlist()); c) 使用spring 5.2.4 为什么说设置lazy=false不可行 由于你在set标签后设置lazy=false的时候,那么以后你再搜索数据的时候,Hibernate都会去获取其对应的set列表(那是否浪费掉非常多的资源,设置了这个值,可能会把整个数据库中与tabuser表有级联关系的数据全读出来[一条链子]) 6.总结 大家可以运行上面的例子,并注意观察打印信息及HQL显示的位置,即可推断出HQL是什么时候执行的 7.补充 有涉及到延迟读取好像只有Load读取和级联信息 如果获取信息用Query的话,则执行query.list的时候就已经读库了 |