Hibernate学习笔记9

来源:互联网 发布:安卓流畅优化软件 编辑:程序博客网 时间:2024/06/06 06:36
 

Hibernate学习笔记9

学习课程:

简单属性查询

SimplePropertyQueryTest

实体对象查询

SimleObjectQueryTest

条件查询

ConditionQueryTest

原生SQL查询

ConditionQueryTest

外置命名查询

NameQueryTest

查询过滤器

FilterQueryTest

分页查询

PageQueryTest

对象导航查询

ObjectNavigationQueryTest

连接查询

JoinQueryTest

统计查询

StatisticsQueryTest

DML查询

DMLQueryTest

HQL简介

数据查询与检索是Hibernate中的一个亮点,相对其他ORM实现而言,Hibernate

提供了灵活多样的查询机制。

HQL(Hibernate Query Language):它是完全面向对象的查询语句,查询功能非常

强大,具备多态,关联等操作,

HQL用面向对象的方式生成SQL

*以类和属性来代替表和数据列

*支持多态

*支持各种关联

*减少了SQL的冗余

HQL支持所有的关系数据库操作

*连接(joins,包括Inner/Oouter/full joins) ,笛卡尔积(cartesion products)

*投影(projection)

*聚合(Aggregation,max,avg)和分组(group)

*排序(Ordering)

*子查询(Subqueries)

*SQL函数(SQL function calls)

HQL查询对象,不会直接查表,关键字不区分大小写,但是属性和类名区分大小写

中立的一套语言

准备工作:

在Student中加入createTime,对时间进行查询

 

1.简单属性查询

testQuery1

单一属性查询,返回结果皆属性列表,元素类型和实体类型的属性类型一致

  1. List<String> list = session.createQuery(
  2.  "select name from Student" ).list(); 
  3. for ( String s : list ){
  4. System.out.println( s );
  5. }

 

testQuery2

多个属性查询——返回类型对象数组(Object[])

 

  1. List list = session.createQuery( 
  2. "select name , id from Student" ).list();
  3. for ( Iterator iter = list.iterator();
  4. iter.hasNext(); ){
  5. Object[] obj = (Object[]) iter.next();
  6. System.out.println( obj[0] + " : " +  obj[1] );
  7. }

 

testQuery3

多个属性查询——返回实体类型 采用HQL动态实例化,此时list中为Student对象集合

为Student提供构造函数

首先提供一个空的构造函数

在提供一个带参数的构造函数

提供的参数为查询的字段

 

  1. List list = session.createQuery( 
  2. "select new Student(id , name )from Student" ).list();
  3. for ( Iterator iter = list.iterator();
  4. iter.hasNext(); ){
  5. Student student = (Student)iter.next(); 
  6. System.out.println( student.getId() + " ,  " + student.getName() );
  7. }

 

testQuery4

使用别名进行查询

  1. List list = session.createQuery( "select s.id , s.name from Student s" ).list();

 

testQuery5

使用as命名别名进行查询

  1. List list = session.createQuery( 
  2. "select student.id , student.name from Student as student" ).list();

 

 

2.实体对象查询

testQuery1

查询实体,返回实体类型Set<Student>   省略select 与以前进行的查询一样 from Student

 

  1. List list = session.createQuery( "from Student" ).list();
  2. for ( Iterator iter = list.iterator();
  3. iter.hasNext();){
  4. Student student = (Student)iter.next(); System.out.println( student.getId() + " , " + student.getName() );
  5. }

 

testQuery2

使用别名进行查询from Student s

 

  1. List list = session.createQuery( "from Student s" ).list();

 

testQuery3

可以使用as 命名别名from Student as s

  1. List list = session.createQuery( "from Student as s" ).list();

 

testQuery4

加入select 关键字,查询实体对象必须采用别名 select s 

from Student s

 

  1. List list = session.createQuery( "select s from Student s" ).list();

 

testQuery5

不支持select * from Student 进行查询出错 采用count(*)

 

  1. List list = session.createQuery( "select * from Student" ).list();

 

testQuery6

采用iterate进行查询需要修改连接数据库URL,添加

SelectMethod=cursor,否则报错

 

  1. Iterator iter = session.createQuery("from Student").iterate();
  2. while(iter.hasNext()) {
  3. Student student = (Student)iter.next(); System.out.println(student.getName());
  4. }

 

出现N+1问题,

1:先发出查询id列表的sql,

N:再依次发出根据id查询Student对象的Sql

资源浪费非常的严重

在默认情况下,使用query.iterate查询,有可能出现N+1问题

第一条查询语句 查询表中所有的id,然后通过id一条一条进行查询,迭代接口使用缓存

采用iterate查询

testQuery7

先调用list,

再调用Iterator

不会出现N+1问题,因为list操作已经将已经将对象放到一级缓存中,在此使用iterate

操作的时候,首先发出一条查询Id列表的语句,根据id在缓存中取数据,只有当缓存中

找不到的相应数据的时候,才发出sql到数据中进行查询

  1. List students = session.createQuery("from Student").list();
  2. for (Iterator iter=students.iterator();  iter.hasNext();) {
  3. Student student = (Student)iter.next();
  4. System.out.println(student.getName());
  5. }
  6. System.out.println("---------------------");
  7. Iterator iter = session.createQuery("from  Student").iterate();
  8. while(iter.hasNext()) {
  9. Student student = (Student)iter.next();
  10. System.out.println(student.getName());
  11. }

testQuery8

执行两次list,将会发出两次查询语句

虽然在一级缓存中已经有了对象数据,但list在默认情况下不只用缓存,它只向缓存中放

入数据,除非配置查询缓存

  1. List students = session.createQuery("from Student").list();
  2. for(Iterator iter=students.iterator();  iter.hasNext();) {
  3. Student student = (Student)iter.next();
  4. System.out.println(student.getName());
  5. }
  6. System.out.println("---------------------");
  7. students=session.createQuery(
  8. "from Student").list();
  9. for (Iterator iter=students.iterator();  iter.hasNext();) {
  10. Student student = (Student)iter.next();
  11. System.out.println(student.getName());
  12. }

3.条件查询

testQuery1

1.支持where语句,支持模糊查询

 

  1. List list = session.createQuery( "select s.id , s.name from Student as s where s.name like '%1%'").list();

 

testQuery2

2.占位符的方式进行查询

可以使用?方式传递参数,参数的索引从0开始,传递的值不用单引号引起来

 

  1. Query query = session.createQuery(
  2. "select s.id , s.name from Student as s where s.name like ?");
  3. query.setParameter(0"%1%");
  4. List list = query.list();

 

testQuery3

Hibernate支持一种编程风格:方法链编程

 

  1. List list = session.createQuery(
  2. "select s.id , s.name from Student as s where s.name like ?")
  3. .setParameter(0"%1%")
  4. .list();

 

testQuery4

3.使用 (:+参数名称)的方式传递参数值,进行查询

 

  1. List list = session.createQuery(
  2. "select s.id , s.name from Student as s where s.name like :myname")
  3. .setParameter("myname""%1%")
  4. .list();

 

testQuery5

4.多参数查询

 

  1. List list = session.createQuery(
  2. "select s.id , s.name from Student as s ""where s.name like :myname"
  3. " and s.id = :myid")
  4. .setParameter("myname""%1%")
  5. .setParameter("myid"12)
  6. .list();

 

testQuery6

5.支持in,需要使用setParameterList进行参数传递

  1. List list = session.createQuery(
  2. "select s.id , s.name from Student as s where s.name in(:myname)")
  3. .setParameterList("myname",
  4. new Object[] { "学生1""学生2""学生3" })
  5. .list();

testQuery7

6.查询某个月的学生,可以使用与数据库相关的系统函数

不会使用,教程中使用的是MySQL数据库,本机的是SQL Server 2000,还有我的数据库知识欠缺

testQuery8

7.查询日期段的学生 2008-01-2

——

2008-05-3

 

  1. SimpleDateFormat sdf = 
  2. new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  3. List list = session.createQuery(
  4. "select s.id , s.name from Student as s where s.createTime between ? and ? ")
  5. .setParameter(0, sdf.parseObject("2008-01-02 00:00:00") )
  6. //必须为Date类型
  7. .setParameter(1, sdf.parseObject("2008-05-03 23:59:59") )
  8. //所以对字符串进行需要格式化
  9. .list();

 

testQuery9

使用原生查询,即使用SQL语句进行查询

  1. List list = session.createSQLQuery( "select * from t_student" ).list();

 

4.外置命名查询

将HQL放到外置文件中,降低耦合度

 

  1. <!--query标签与class平行,可以放到任何的映射文件中都可以,
  2. 但是注意 name属性值不要重复-->
  3. <query name="search">
  4. <![CDATA[ 
  5. SELECT s FROM Student s where s.id<?
  6. ]]>
  7. </query>
  8. List list = session.getNamedQuery( "search" ).setParameter( 0 , 10 ).list();

 

5.查询过滤器

步骤:

在映射文件中定义过滤器的参数

在类映射文件中使用定义的参数

在程序中启用过滤器

作用域:

当定义完查询的时候,session没有关闭,执行的所有HQl,都会加上这个条件

配置文件,加入标签

 

  1. <filter-def name="filterTest">
  2. <filter-param name="myid" type="integer"/>
  3. </filter-def>

 

在class标签内加入

  1. <filter name="filterTest" condition="name_id < :myid" />

调用方法 

  1. session.enableFilter( "filterTest" ).setParameter( "myid", 20 );

6.分页查询【重要】

  1. List list = session.createQuery( "from Student" )
  2.    .setFirstResult( 3 ) //设置第一行检索
  3.    .setMaxResults( 20 ) //设置每页最多的数据条目
  4.    .list();

7.对象导航查询,在HQL中采用 "."进行导航,进行查询【重要】

  1. //只检索一个字段,返回类型为 Object,
  2. List list = session.createQuery( "select s.name from Student s where s.classes.name like '%1%'" ).list();

8.连接查询【重要】

连接分为:

内连

外连(左连接,右连接)

testQuery1

1.查询学生的名字以及所在班级的名字

内连接

  1. //只检索一个字段,返回类型为 Object,
  2. List list = session.createQuery( "select c.name , s.name from Student s join s.classes c" ).list();
  3. for ( Iterator iter = list.iterator(); iter.hasNext();){
  4. Object[] obj = (Object[]) iter.next();//类型转换必须一致,否则会报出[Ljava.lang.Object错误
  5. System.out.println( obj[0] + " : " + obj[1] );
  6. }

testQuery2

2.显示无学生班级

左连接

  1. List list = session.createQuery( "select c.name , s.name from Classes c left join c.students s " ).list();

testQuery3

3.显示无业游民

右连接

 

  1. List list = session.createQuery( "select c.name , s.name from Classes c right join c.students s" ).list();

 

9.统计查询【重要】

testQuery1

统计学生人数

 

  1. //只检索一个字段,返回类型为 Object,
  2. List list = session.createQuery("select count(*) from Student") .list();
  3. Long count = (Long) list.get(0);
  4. System.out.println("统计学生人数:" + count);

 

testQuery2

设置返回单一值,而不是返回List类型

 

  1. Long count = (Long) session.createQuery(
  2. "select count(*) from Student")
  3. .uniqueResult();
  4. System.out.println("统计学生人数:" + count);

 

10.DML风格的操作

//批量更新

//建议少用因为和缓存不同步

 

  1. session.createQuery("update Student s set s.name=? where s.id < ?")
  2.         .setParameter(0"张林")
  3.         .setParameter(110)
  4.         .executeUpdate();
  5. List list = session.createQuery(
  6.     "select s.id , s.name from Student s where s.id < 10").list();

 

原创粉丝点击