Hibernate的高级操作(十八)

简介: Hibernate的高级操作(十八)

一. 批量处理


在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形式的处理


  1. 在hibernate.cfg.xml 中设置批量处理的尺寸


    <!-- 设置批量的尺寸 -->
    <!-- <property name="hibernate.jdbc.batch_size">100</property> -->


  1. 在hibernate.cfg.xml 中关闭二级缓存


<!-- 最好关闭二级缓存 -->
    <!-- <property name="hibernate.cache.use_second_level_cache">false</property> -->


  1. 编写代码


@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的一对多映射的单向关联和双向关联(九) 。这里不做具体的分析创建了。


数据为:


20190324130324860.png


20190410194853903.png


二.一 属性对象.对象属性


如查询员工部门编号为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();
  }


20190410194937516.png


注意,是没有集合这种形式的。


// 这种写法是错误的。
  @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();
  }


201904101952447.png


二.三 内连接 加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();
  }


20190410195613797.png


也是全部的查询出来。 只是,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();
  }


20190410195922574.png


二.五 加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();
  }


20190410200028338.png


与第一个方法,是稍微不一样的。


二.六 左外连接 无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();
  }


20190410200612576.png


20190410200642454.png


三.二 类级别查询 load() 方法


  @Test
  public void test12(){ //查询的是全部的  连接的形式,是on
    Session session=HibernateUtil.getSession();
    User user=session.load(User.class,1);
    System.out.println(user);
    session.close();
  }


20190410200821261.png


20190410200835521.png


20190410200854426.png


三.三 关联级别的查询


一般设置时,都是自动关联查询多的一方。 如果自动关联,多的一方的时候


//关联级别的查询
  @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();
  }


20190410201150591.png


20190410201207947.png


20190410201225703.png


在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”,即不执行懒加载,而是立即加载时。 测试上面的方法,结果为:


20190410201709814.png


20190410201739578.png


20190410201757574.png


lazy 还有一种取值,叫 extra 即lazy=“extra”, 是极度懒惰。 你要什么值,就给什么值。 如 这里只查询出size()的长度,即数目。 那么,这个时候的查询方法为:


20190410201757574.png


只能说,是真得懒啊。 如果是员工查询部门的话,输出 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();
  }


执行的顺序是:


20190410202501700.png


20190410202530263.png


20190410202541850.png


设置批量查询时,利用batch-size ,值越大,发送语句越小。


<set name="users" fetch="select" lazy="false" batch-size="10">


20190410202730194.png


20190410202750688.png


会转换成in 的形式。


谢谢!!!


相关文章
|
8月前
|
SQL 前端开发 Java
JSP毕业设计选题系统统myeclipse开发sql数据库BS模式java编程mvc结构
JSP 毕业设计选题系统是一套完善的web设计系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。
31 0
|
8月前
|
前端开发 Java 数据库
JSp城市生活信息收集发布网myeclipse开发sqlserver2008数据库BS模式java编程网页结构struts2
JSP城市生活信息收集发布网是一套完善的web设计系统,对理解JSP java编程开发语言有帮助 struts2 dao+bean mvc模式,系统具有完整的源代码和数据库,开发环境为TOMCAT7.0,Myeclipse8.5开发,数据库为sqlserver2008,使用java语言开发,系统主要采用B/S模式开发。
29 0
|
8月前
|
Java 关系型数据库 MySQL
JSP学生交流论坛系统myeclipse开发mysql数据库bs框架java编程jdbc
JSP 学生交流论坛系统是一套完善的web设计系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,开发环境为TOMCAT7.0,Myeclipse8.5开发,数据库为Mysql5.0,使用java语,言开发系统主要采用B/S模式开发。 https://www.bilibili.com/video/BV1jB4y1q7Ut?spm_id_from=333.999.0.0
76 0
|
8月前
|
Java 关系型数据库 MySQL
JSP 教学文档管理系统myeclipse开发mysql数据库bs框架java编程jdbc
JSP 教学文档管理系统是一套完善的web设计系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,开发环境为TOMCAT7.0,Myeclipse8.5开发,数据库为Mysql5.0,使用java语,数据库文件名是jspsjxwd.sql,系统名称jxwd,言开发系统主要采用B/S模式开发。
44 0
|
8月前
|
Java 关系型数据库 MySQL
JSP 空教室查询管理系统yeclipse开发mysql数据库bs框架java编程jdbc
JSP 空教室查询管理系统是一套完善的web设计系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,开发环境为TOMCAT7.0,Myeclipse8.5开发,数据库为Mysql5.0,使用java语言开发,系统主要采用B/S模式开发。
269 2
|
8月前
|
SQL 前端开发 Java
JSP网上报名管理系统myeclipse开发sql数据库BS模式java编程mvc结构
JSP 网上报名管理系统是一套完善的web设计系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。
26 0
|
8月前
|
Java 关系型数据库 MySQL
JSP景观工程管理系统myeclipse开发mysql数据库bs框架java编程jdbc
JSP景观工程管理系统是一套完善的web设计系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,开发环境为TOMCAT7.0,Myeclipse8.5开发,数据库为Mysql5.0,使用java语言开,系统主要采用B/S模式开发。
51 1
|
8月前
|
Java 关系型数据库 MySQL
JSP教师辅助办公软件教学进程管理系统yeclipse开发mysql数据库bs框架java编程jdbc
JSP 教师辅助办公软件教学进程管理系统是一套完善的web设计系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,开发环境为TOMCAT7.0,Myeclipse8.5开发,数据库为Mysql5.0,使用java语言开发,系统主要采用B/S模式开发。
44 0
|
11月前
|
存储 缓存 安全
Java安全框架(课时二十三)笔记内容十三
Java安全框架(课时二十三)笔记内容十三
160 0
|
11月前
|
存储 Java 数据库
SpringIoc方案二不使用配置文件开发(课时十二)
SpringIoc方案二不使用配置文件开发(课时十二)
58 0