Hibernate学习笔记之持久层操作
来源:互联网 发布:怎样进行网络推广 编辑:程序博客网 时间:2024/04/30 14:45
数据加载
Session.get/load
这两个方法都是用来根据实体类以及id从数据库读取数据,并返回对于那个实体对象。
区别:
- 如果未能查询到符合条件的记录,get返回null,load抛出ObjectNotFoundException。
- load方法可以返回实体的代理类实例,而get方法只能返回实体类。
- load方法可以利用内部缓存和二级缓存的数据,而get方法只能利用内部缓存,如果在内部缓存中没有命中,直接执行sql完成查询。
Session加载实体对象的过程:
- Session在调用sql查询前会先在第一级缓存中根据实体类和id进行查找,如果命中则返回。
- 如果第一步没有找到,Session会在当前的“NonExists“记录中查找,如果存在相同的查询条件,则返回Null。“NonExists“记录了当前Session实例在之前所有查询操作中,未能查询到有效数据的查询条件。如果一个Session中无效的查询条件重复出现,即可迅速作出判断,减少对数据库的无效访问。
- 对load方法而言,如果内部缓存没有命中则会继续尝试二级缓存,如果二级缓存命中则返回。
- 如果在缓存中未查询到数据,则执行sql。如果为查询到数据,则将此次查询信息记录在”NonExists”记录中,并返回Null。
- 根据映射配置和ResultSet创建数据对象。
- 将数据对象纳入Session实体管理容器(内部缓存)。
- 执行Interceptor.onLoad方法。
- 将数据纳入二级缓存。
- 如果数据对象实现了LifeCycle接口,则调用 数据对象的onLoad方法。
- 返回数据对象。
Query.list/iterate
通过list或iterate方法可以完成数据批量查询,但是他们的机制是不同的。
list方法:
Query query=session.createQuery("from Userbean user where user.id>0"); List<Userbean> list=query.list(); for (Userbean userbean : list) { System.out.println(userbean.getLoginName()); }
运行结果:
Hibernate: select userbean0_.id as id0_, userbean0_.email as email0_, userbean0_.loginName as loginName0_, userbean0_.password as password0_ from userbean userbean0_ where userbean0_.id>0
yukjin
1
iterate方法:
Iterator<Userbean> it=query.iterate(); while(it.hasNext()){ System.out.println(it.next().getLoginName()); }
运行结果:
Hibernate: select userbean0_.id as col_0_0_ from userbean userbean0_ where userbean0_.id>0
Hibernate: select userbean0_.id as id0_0_, userbean0_.email as email0_0_, userbean0_.loginName as loginName0_0_, userbean0_.password as password0_0_ from userbean userbean0_ where userbean0_.id=?
yukjin
Hibernate: select userbean0_.id as id0_0_, userbean0_.email as email0_0_, userbean0_.loginName as loginName0_0_, userbean0_.password as password0_0_ from userbean userbean0_ where userbean0_.id=?
1
通过运行结果可以看到,list方法执行了一条sql语句,而iterate方法执行了3条,第一条先查出Id,然后再根据id一个一个select出信息。看上去iterate方法会导致效率不高,但正是它的这种方式,使它可以利用Hibernate缓存。
如下代码连续执行两次查询:
Query query=session.createQuery("from Userbean user where user.id>0"); List<Userbean> list=query.list(); for (Userbean userbean : list) { System.out.println(userbean.getLoginName()); } Iterator<Userbean> it=query.iterate(); while(it.hasNext()){ System.out.println(it.next().getLoginName()); }
结果:
Hibernate: select userbean0_.id as id0_, userbean0_.email as email0_, userbean0_.loginName as loginName0_, userbean0_.password as password0_ from userbean userbean0_ where userbean0_.id>0
yukjin
1
Hibernate: select userbean0_.id as col_0_0_ from userbean userbean0_ where userbean0_.id>0
yukjin
1
可以看到这次iterate方法只执行了一句sql从数据库查询出符合条件的id,然后直接根据Id从缓存中返回实体对象。
而list方法是无法利用缓存的(这里就不再实验),例如第一此查询的是id>0的,而第二次查询的是id>2的,list无法确保id>2的结果在缓存中有完整的数据集,只能再次执行sql查询结果。
延迟加载
userbean表和address表存在一对多的关系,address表中存在一个外键userbean_id来绑定一个userbean。反映在实体类则是Userbean类中有一个Set类型的属性address来存储该实体类关联的Address类,而Address有一个Userbean类型的属性关联所属的Address类。当我们通过前面提到的load或get方法加载Userbean时,Hibernate默认会把所关联的Address信息也加载进来,而倘若我们只需要的是登录名,那么无疑是加载了无用信息。延迟加载就是为了解决这样的问题,它会在真正需要address的时候才去加载。
<set name="addresses" lazy="true" inverse="true" cascade="none"> <key> <column name="userbean_id" /> </key> <one-to-many class="bean.Address" /> </set>
通过设置lazy属性开启延迟加载。
批量删除
Hibernate2中的批量删除操作的实现是通过循环调用delete sql语句,因此会造成性能上的损耗,在Hibernate3中是通过一条删除语句实现的,但是却引来了新的问题,缓存与数据库数据不一致,例如以下代码:
Userbean user=(Userbean) session.load(Userbean.class,new Integer(4)); System.out.println(user.getLoginName()); Transaction transaction=session.beginTransaction(); String hql="delete from Userbean u where u.id>3"; Query query=session.createQuery(hql); query.executeUpdate(); transaction.commit(); user=(Userbean) session.load(Userbean.class,new Integer(4)); System.out.println(user.getLoginName());
运行结果:
Hibernate: select userbean0_.id as id0_0_, userbean0_.email as email0_0_, userbean0_.loginName as loginName0_0_, userbean0_.password as password0_0_ from userbean userbean0_ where userbean0_.id=?
3
Hibernate: delete from userbean where id>3
3
代码首先通过load方式加载id等于4的用户,然后通过批量删除操作将id>3的用户信息从数据库中删除,紧接着通过load方法重新加载id=4的用户。从运行结果中可以看到,第二次加载到了已经被删除的数据。
- Hibernate学习笔记之持久层操作
- Hibernate持久层操作
- Hibernate 持久层操作
- Java学习笔记08——持久层框架Hibernate
- Hibernate学习笔记之持久化实现
- 《深入浅出hibernate》(4)持久层操作
- Hibernate级联操作学习之持久化临时对象
- 【Hibernate学习之路4】操作持久化类
- 数据持久层框架Hibernate入门学习
- 数据库持久层开发之Hibernate主键
- Hibernate学习笔记 之 持久化对象的状态
- hibernate之模拟Hibernate持久化操作
- Spring学习笔记 五 整合hibernate持久层 ----1,基本配置
- Spring学习笔记(五)使用Hibernate持久层 --- 2 问题与解决总结
- 【持久层】JDBC详解之基本操作
- Androidc学习笔记四之数据库持久化操作
- 持久层框架iBatis学习笔记
- webx学习笔记3--持久层配置
- FMDB的一些基本操作小结
- SEU寒假训练题解二 G Codeforces 432C
- Android屏幕适配原理
- js将时间戳转化成时间格式字符串(兼容各种浏览器)
- c#网络通信框架networkcomms内核解析之一 消息传送
- Hibernate学习笔记之持久层操作
- c#网络通信框架networkcomms内核解析之二 消息处理流程
- @Repository认识
- ByteArrayOutputStream与InputStream
- c#网络通信框架networkcomms内核解析之三 消息同步调用
- android clipRect Op.xxx各个参数理解
- linux的博客链接
- jquery easyui tree异步加载的简单用法
- 让 UISearchBar 支持空搜索