前面讲过get和load,一个是直接加载,并不是直接去数据库查询,如果缓存里有,首先到缓存里找,缓存分为一级缓存和二级缓存,首先到一级缓存中查找;
如果在session关闭之后进行获取类的名字之类的属性,依然会获取到,例:
Order od = (Order) session.get(Order.class, 1);
通过get获取的Order类是一个持久化类,如果session关闭之后进行获取,od.getName,它就会变成托管状态,但是这个对象还是有的,所以没事;
另一个是懒加载,他不会直接进行操作,就是除了获取id(标识符)和类.class时,获取其他的类属性都会进行操作,
例:
Account acc=(Account)session.load(Account.class,new Long(1)); //返回一个代理对象
System.out.println(acc.getId);
System.out.prontln(acc.getLonginName());
这里的1是一个代理对象,如果只获取他的id,则不会加载,不会出现select语句,只有获取除他和本身之外才会进行查找;否则访问的只是他的代理对象而已;如果需要取消懒加载,就只需要在你想获取的类属性的映射文件的<class name=”” table=”” lazy=”false”>把他改为false就可以了,这样懒加载就取消了,这里只对load管用,对get()毫无影响;
如果把他System.out.prontln(acc.getLonginName());放在session关闭之后,则会出现错误,因为这里只产生了一个代理对象,没有真正去查,把session关之后,他会去查数据库,要发出sql语句,因为发出sql语句需要在session里面,所以session关了之后,就不能使用了;
接下来说一说他们之间的区别:
延迟加载的过程:通过代理(Proxy)机制来实现延迟加载。Hibernate从数据库获取某一个对象数据时、获取某一个对象的集合属性值时,或获取某一个对象所关联的另一个对象时,由于没有使用该对象的数据(除标识符外),Hibernate并不从数据库加载真正的数据,而只是为该对象创建一个代理对象来代表这个对象,这个对象上的所有属性都为默认值;只有在真正需要使用该对象的数据时才创建这个真正的对象,真正从数据库中加载它的数据。
如果只是访问对象标示符属性,就没有必要初始化代码。
Account acc=(Account)session.load(Account.class,new Long(1)); //返回一个代理对象
Order order=new Order();
order.setCreateTime(new Date());
order.setAccount(acc);
Session.save(order);
在这只需要Account实例来创建一个新的Order订单对象,当调用session.save(order)时,也只需要Account的主标示符值作为外键保存到订单表的对应字段中。这样就少执行一条select语句,从而提高查询效率。
Hibernate中默认采用延迟加载的情况主要有以下几种:
当调用Session上的load()方法加载一个实体时,会采用延迟加载。
当Session加载某个实体时,会对这个实体中的集合属性值采用延迟加载。(one-to-many)
例:当Client这个类里具有集合属性,
Client client = (Client) session.get(Client.class, 4);
System.out.println(client.getName());
获取他的名字,你会发现只有一条sql语句,因为采用了延迟加载,所以如果想
取消,就在该映射文件下<set>里面把lazy改成false;
当Session加载某个实体时,会对这个实体所单端关联(one-to-one, many-to-one)的另一个实体对象采用延迟加载。
能够懒加载的对象都是被改写过的代理对象,当相关联的session没有关闭时,访问这些懒加载对象(代理对象)的属性(getId和getClass除外)hibernate会初始化这些代理,或用Hibernate.initialize(proxy)来初始化代理对象;当相关联的session关闭后,再访问懒加载的对象将出现异常。
2、 关闭延迟加载
在加载单个实体时,如果不需要延迟加载,就可以使用session的get()方法。
当Session加载某个实体时,不需要对这个实体中的集合属性值延迟加载,而是要立即加载。这时可以在映射文件中针对 这个集合属性的配置元素(<set>,<bag>,<list>…)添加属性lazy=“false”。
当Session加载某个实体时,不需要对这个实体所单端关联的另一个实体对象延迟加载,就可以在映射文件中对这个单端关联的配置元素(<one-to-one>,<many-to-one> )添加属性lazy=“false”。
注意:one-to-one不能有constrained=true