Hibernate批量处理数据、[HQL连接查询]
一、批量处理操作
批量处理数据是指在一个事务场景中处理大量数据。在应用程序中难以避免进行批量操作,Hibernate提供了以下方式进行批量处理数据:
(1)使用HQL进行批量操作 数据库层面
(2)使用JDBC API进行批量操作 数据库层面
(3)使用Session进行批量操作 会进缓存
1.使用HQL进行批量操作
HQL可以查询数据,也可以批量插入、更新和删除数据。HQL批量操作实际上直接在数据库中完成,处理的数据不需要加载到Session缓存中。使用Query接口的executeUpdate()方法执行用于插入、更新和删除的HQL语句。
以Emp和Dept为例:
例:批量添加3个部门
@Test public void addTest(){ String hql="insert into Dept(deptName) select d.deptName||d.deptNo from Dept d where d.deptNo>0"; Query query=session.createQuery(hql); int count=query.executeUpdate(); System.out.println("add ok!!"); }
2.使用JDBC API进行批量操作
在Hibernate应用中使用JDBC API批量执行插入、修改和删除语句时,需要使用Session的doWork(Work work)方法执行Work对象指定的操作,即调用Work对象的execute()方法。Session把当前使用的数据库连接传给execute()方法,执行持久化操作。
例:实现批量修改部门名称
将部门编号大于3的修改为开发部
注意:该方式使用的连接依然是最初的连接对象,并且命令对象依然是根据连接创建的,注意这里是SQL语句,不是HQL语句
@Test public void updateTest(){ final String sql="update Dept set deptname=? where deptno>?"; Work work=new Work(){ public void execute(Connection con) throws SQLException{ PreparedStatement ps = con.prepareStatement(sql); ps.setString(1,"开发部"); ps.setInt(2, 3); int count=ps.executeUpdate(); //System.out.println(count); } }; session.doWork(work); System.out.println("update ok!!!"); }
实现效果:
3、实现session进行批量操作
使用Session对象处理大量持久化对象,需及时从缓存中清空已经处理完毕并且不会再访问的对象。可以在处理完成一个对象或小批量对象后,调用flush()方法强制同步缓存和数据库,然后调用clear()方法清空缓存。
例:批量添加15个员工
/* * session 实现批量添加15个员工 */ @Test public void addSessionTest(){ for(int i=0;i<=15;i++){ Emp emp=new Emp(); emp.setEmpName("呵呵"+i); Dept dept=new Dept(); dept.setDeptNo(1); emp.setDept(dept); session.save(emp); if(i%10==0){ session.flush(); session.clear(); } } System.out.println("add ok!!"); }
输出结果:
------------------------------------------------------------------------------------------------------------
二、HQL连接查询
HQL提供的连接方式如下表所示:
内连接:
语法:
from Entity inner join Entity.property
例:使用内连接查询员工隶属的部门
list集合中的每个元素都是一个Object数组,from后面紧接的是部门 则输出的先是部门的内存地址
/* * 内连接 员工隶属的部门 */ @Test public void innerTest(){ Query query=session.createQuery("from Dept d inner join d.emps"); List<Object[]> list = query.list(); for (Object[] item : list) { //一个item就是一个数组 System.out.println(((Dept)item[0]).getDeptName()+"\t"+((Emp)item[1]).getEmpName()); } }
隐式内连接:
在HQL查询语句中,如果对Emp类赋别名为”e”,可以通过e.dept.deptName的形式访问dept对象的deptName属性。使用隐式内连接按部门查询员工信息。
例:按部门条件查询员工信息
/* * 隐式内连接 按部门条件查询员工信息 */ @Test public void hideTest(){ Query query=session.createQuery("from Emp e where e.dept.deptName='开发部'"); List<Emp> list = query.list(); for (Emp item : list) { //一个item就是一个数组 System.out.println(item.getEmpName()); } }
3、迫切内连接
例:查询所有的雇员名称和隶属部门名称 需使用关键字fetch
/* * 迫切内连接 查询所有的雇员名称和隶属部门名称 */ @Test public void FetchTest(){ Query query=session.createQuery("from Dept d inner join fetch d.emps"); List<Dept> list=query.list(); for (Dept item : list) { System.out.println(item.getDeptName()+"\t"+item.getEmps().iterator().next().getEmpName()); } }