东家蝴蝶西家飞,白骑少年今日归。 愿,所有迷茫的人,都不再迷茫的,愿,所有努力工作的人,都可以得到应有的回报,愿,所有的人,都可以找到回家的方向,愿,再无苦痛,再无离别。
上一章简单介绍了Hibernae的Criteria 查询(十七),如果没有看过,请观看上一章
一. 批量处理
在Hibernate中,有一种批处理。 利用多对多案例中的Role 类。 是一个单表类。 只有id,name,description 三个字段属性。
一.一 原始做法
@Test public void insertTest1(){ Session session=HibernateUtil.getSession(); for(int i=0;i<1000000;i++){ Role role=new Role(); role.setName("两个蝴蝶飞"+i); role.setDescription("这是描述啊"+i); session.save(role); } session.close(); }
如果插入的数据量很大的话,如一百万条,一千万条时,会抛出栈溢出的错误。即 StackOverflowError
一.二 Hibernate形式的处理
在hibernate.cfg.xml 中设置批量处理的尺寸
<!-- 设置批量的尺寸 --> <!-- <property name="hibernate.jdbc.batch_size">100</property> -->
在hibernate.cfg.xml 中关闭二级缓存
<!-- 最好关闭二级缓存 --> <!-- <property name="hibernate.cache.use_second_level_cache">false</property> -->
编写代码
@Test public void insertTest2(){ Session session=HibernateUtil.getSession(); for(int i=0;i<1000000;i++){ Role role=new Role(); role.setName("两个蝴蝶飞"+i); role.setDescription("这是描述啊"+i); session.save(role); if(i%100==0){ //100 为刚才设置的尺寸 session.flush(); //与数据库保持同步 session.clear(); //清空一级缓存中的所有数据,及时释放相应的内存。 } } session.close(); }
一.三 jdbc形式的批处理
@Test public void insertTest3(){ Session session=HibernateUtil.getSession(); // 必须要开启事务. Transaction transaction=null; try{ transaction=session.beginTransaction(); // hibernate中调用jdbc,使用doWork 进行相应的创建。 session.doWork(new Work(){ //匿名类 @Override public void execute(Connection connection) throws SQLException { PreparedStatement pst=connection.prepareStatement("insert into role(name,description) values(?,?)"); for(int i=0;i<100;i++){ //100 为相应的尺寸。 pst.setString(1,"两个蝴蝶飞"+i); pst.setString(2,"这是描述啊"+i); pst.addBatch(); } pst.executeBatch(); } }); transaction.commit(); }catch(Exception e){ e.printStackTrace(); transaction.rollback(); } //session.close(); //不要关闭 }
切记,session不能进行关闭。 这是调用jdbc的形式进行处理,所以并不会在控制台输出插入的语句。 同样,也有关于批量的修改,和批量的删除。 方法与其一样,不做举例了。
二. 多表查询
具体的例子,参照的是Hibernate的一对多映射的单向关联和双向关联(九) 。这里不做具体的分析创建了。
数据为:
二.一 属性对象.对象属性
如查询员工部门编号为1的所有的员工。 即查询部门编号为1的所有员工,只是查询出来直接是员工。
@Test public void test1(){ Session session=HibernateUtil.getSession(); String hql="from User t where t.dept.id=1"; Query query=session.createQuery(hql); List<User> userList=query.list(); userList.forEach(n ->System.out.println(n)); session.close(); }
注意,是没有集合这种形式的。
// 这种写法是错误的。 @Test public void test2(){ Session session=HibernateUtil.getSession(); String hql="from Dept t where t.users.id=1"; //是不能根据多的一方进行查询的。 Query query=session.createQuery(hql); List<User> userList=query.list(); userList.forEach(n ->System.out.println(n)); session.close(); }
二.二 内连接查询,为List Object数组
@Test public void test3(){ //查询的是全部的 连接的形式,是on Session session=HibernateUtil.getSession(); String hql="from User t inner join t.dept"; // 查询出来的是Object [] Query query=session.createQuery(hql); List<Object []> userList=query.list(); for (Object[] objects : userList) { for (int i = 0; i < objects.length; i++) { Object object = objects[i]; System.out.print(object+","); } System.out.println(); } session.close(); }
二.三 内连接 加fetch
@Test //查询的只是user public void test4(){ Session session=HibernateUtil.getSession(); // 用一个fetch , 就可以转换成相应的实体了。 String hql="from User t inner join fetch t.dept"; Query query=session.createQuery(hql); List<User> userList=query.list(); userList.forEach(n ->System.out.println(n)); session.close(); }
也是全部的查询出来。 只是,fetch 的时候,会将查询出来的结果,按照属性相同的规则,进行相应的赋值到对象里面,可以封装成相应的对象。
二.四 直接采用 on的形式
@Test public void test6(){ //查询的是全部的 连接的形式,是on Session session=HibernateUtil.getSession(); String hql="from Dept t inner join t.users"; //是不能根据多的一方进行查询的。 Query query=session.createQuery(hql); List<Object []> userList=query.list(); for (Object[] objects : userList) { for (int i = 0; i < objects.length; i++) { Object object = objects[i]; System.out.print(object+","); } System.out.println(); } session.close(); }
二.五 加where 语句
@Test //查询的只是user public void test5(){ //后面跟where 之后,就可以跟条件了。 Session session=HibernateUtil.getSession(); String hql="from User t inner join fetch t.dept where t.dept.id=1"; Query query=session.createQuery(hql); List<User> userList=query.list(); userList.forEach(n ->System.out.println(n)); session.close(); }
与第一个方法,是稍微不一样的。
二.六 左外连接 无fetch Object[] 对象
tring hql="from Dept t left outer join t.users";
二.七 左外连接 有 fetch
String hql="from Dept t left outer join fetch t.users";
二.八 右外连接 无fetch Object[] 对象
String hql="from Dept t right outer join fetch t.users";
二.九 右外连接 有 fetch
String hql="from Dept t right outer join fetch t.users";
三. 延迟检索查询
延迟,在Hibernate中可以分为两种,一种是类级别的延迟。 第二种是 关联级别的查询。 其中,类级别的延迟,可以用load() 方法,区别于get() 方法。
关联级别的查询,需要配置一下 fetch 和lazy
三.一 类级别查询 get() 方法
//检索查询 @Test public void test11(){ //查询的是全部的 连接的形式,是on Session session=HibernateUtil.getSession(); User user=session.get(User.class,1); System.out.println(user); session.close(); }
三.二 类级别查询 load() 方法
@Test public void test12(){ //查询的是全部的 连接的形式,是on Session session=HibernateUtil.getSession(); User user=session.load(User.class,1); System.out.println(user); session.close(); }
三.三 关联级别的查询
一般设置时,都是自动关联查询多的一方。 如果自动关联,多的一方的时候
//关联级别的查询 @Test public void test13(){ Session session=HibernateUtil.getSession(); Dept dept=session.get(Dept.class,1); Set<User> userList=dept.getUsers(); //这一步,并不会查询 System.out.println("长度是:"+userList.size()); //才开始查询。 session.close(); }
在Dept.hbm.xml 中,默认是懒加载的,lazy=“true” . 关联查询,用fetch=“select” . 即为:
set name="users" fetch="select" lazy="true"> <!-- 这个deptId 要与User.hbm.xml中的dept属性中的column保持一致 --> <key column="deptId"></key> <one-to-many class="User"/> </set>
fetch 为select. lazy=“true”,默认为true,即使用懒加载。 懒加载的意思是不去加载。 也就是说,查询出部门之后,并不会查询部门下的员工集合,即users.
将lazy=“true” 改成成lazy=“false”,即不执行懒加载,而是立即加载时。 测试上面的方法,结果为:
lazy 还有一种取值,叫 extra 即lazy=“extra”, 是极度懒惰。 你要什么值,就给什么值。 如 这里只查询出size()的长度,即数目。 那么,这个时候的查询方法为:
只能说,是真得懒啊。 如果是员工查询部门的话,输出 user.getDept().getName() 的话,便只会查询出部门的名称,不会查询出部门的描述。
四. 批量抓取
如,查询所有部门下的所有的员工 。
@Test public void test15(){ //进行相应的查询 Session session=HibernateUtil.getSession(); List<Dept> deptList=session.createQuery("from Dept").list(); for(Dept d:deptList){ System.out.println(d); Set<User> userList=d.getUsers(); for(User user:userList){ System.out.println(user); } } session.close(); }
执行的顺序是:
设置批量查询时,利用batch-size ,值越大,发送语句越小。
<set name="users" fetch="select" lazy="false" batch-size="10">
会转换成in 的形式。
谢谢!!!