hibernate2007-08-04(上午).avi
注意hql的大小写敏感性
下面所有测试用的都是one-to-many代码只是在student中加了一个Data createDate属性还有就是插入的内容不同
//可以省略select
Query q = createQuery("from Student");
//使用select关键字时,必须定义别名
//不支持这样select * from Student会出错。
Query q = createQuery("select s from Student s");
//忽略select 给表加别名
Query q = session.createQuery("from Student s");
---------------------------------------------------
测试一(list()):
/**
* 将发出一条查询语句,获取Student的集合数据
* select student0_.id as id1_, student0_.name as name1_,
* student0_.createTime as createTime1_, student0_.classid as classid1_
* from t_student student0_
*/
List students = session.createQuery("from Student").list();
for (Iterator iter = students.iterator();iter.hasNext();) {
Student student = (Student)iter.next();
System.out.println(student.getName());
}
测试二(iterate()会出现n+1问题):
//会发出n+1 条语句
//先发出查询id的列表语句
//select student0_.id as col_0_0_ from t_student student0_
//再依次发出查询对象的sql(根据id)
//select student0_.id as id1_0_, student0_.name as name1_0_,
//student0_.createTime as createTime1_0_, student0_.classid as classid1_0_
//from t_student student0_ where student0_.id=?
Query query = session.createQuery("from Student");
Iterator students = query.iterate(); //先发出查询id的列表语句,不管缓存里有没有数据,都发
while (students.hasNext()) {//如果缓存有数据就不发,如果没有数据就每次next都会发一条根据id查询的sql
Student student = (Student)students.next();
System.out.println(student.getName());
}
Iterator query = session.createQuery("from Student").iterate();
List students = session.createQuery("from Student").list();
iterate()与list()不同区别是,如上面代码所示就在于发出的sql语句条数不同
Iterator it= session.createQuery("from Student").iterate();
//上面代码先从数据库查出所有id,再根据ID查数据,所以会有n+1问题,但查实体对象会先在一级缓存查找
Iterator it= session.createQuery("select s.name,s.id from Student s").iterate();
//上面代码不会查id而是一次性取出所有数据封装成对像数组返回,它不会从一级缓存里找,而是直接查数据库
测试三(解决n+1问题):
List students = session.createQuery("from Student").list();//发一条取出所有数据并放到缓存里
Query query = session.createQuery("from Student");//这里发一条sql取出所有ID,只取ID列
Iterator students = query.iterate(); //iterate()这里不发了。Iterator会直接在缓存里取。
这样便能解决n+1问题。因为第一句代码运行后会把数据放到缓存里,这样当query.iterator时会先在缓存里找数据
测试四(两个.list):
Query q= session.createQuery("from Student");//发一条取出所有数据并放到缓存里
list students = q.list();//会发一条
//这里是iterator代码
students = q.list();//也会发一条。
//这里是iterator代码
hibernate默认配置了对象缓存(一级缓存)
说明了在默认情况下list()每次都会向数据库发出查询语句取得所有结果,但如果配了二级缓存这里就不会再发sql了。
===============================================
单个属性查询:
List students = session.createQuery("select name from Student").list();
for (Iterator iter = students.iterator();iter.hasNext();) {
String name = (String)iter.next();
System.out.println(name);
}
多个属性查询:
//查询多个属性,其集合元素是对象数组
//数组元素的类型,跟实体类的属性的类型相关
//更常见的用法,给对象起个别名,然后通过别名来引用属性值
//List students = session.createQuery("select s.id, s.name from Student s").list();
List students = session.createQuery("select id, name from Student").list();
for (Iterator iter = students.iterator();iter.hasNext();) {
Object[] obj = (Object[])iter.next();
System.out.println(obj[0] + ", " + obj[1]);
}
简单属性查询
* 单个属性查询,返回的结果集属性的列表,其元素和属性的类型一致
* 多个属性查询,返回的结果集是数组类型,数组的长度和查询的属性数量相关,数组中元素的类型与相应的属性类型相同
参见:SimplePropertyQueryTest.java
====================================================
//条件查询,拼字符串
List students = session.createQuery("SELECT s.id, s.name FROM Student s WHERE s.name LIKE '%1%'")
.list();
for (Iterator iter = students.iterator();iter.hasNext();) {
Object[] obj = (Object[])iter.next();
System.out.println(obj[0] + ", " + obj[1]);
}
----------------------------------------------
//条件查询,使用 ? 的方式传递参数
Query query = session.createQuery("SELECT s.id, s.name FROM Student s WHERE s.name LIKE ?");
//传递参数
//参数的索引是从0开始的
//传递的字符串,无需用''单引号括起来
query.setParameter(0, "%1%");
List students = query.list();
for (Iterator iter = students.iterator();iter.hasNext();) {
Object[] obj = (Object[])iter.next();
System.out.println(obj[0] + ", " + obj[1]);
}
--------------------------------------
//条件查询,使用 :参数名称 的方式传递参数
Query query = session.createQuery("SELECT s.id, s.name FROM Student s WHERE s.name LIKE :myname");
//传递参数
query.setParameter("myname", "%1%");
List students = query.list();
-----------------------------------------
//条件查询,因为setParameter方法返回Query接口,所以可以用省略的方式来查询
List students = session.createQuery("SELECT s.id, s.name FROM Student s WHERE s.name LIKE :myname and s.id = :myid")
.setParameter("myname", "%1%")
.setParameter("myid", 15)
.list();
--------------------------------------------
//条件查询,支持in,需要用setParameterList()进行参数传递
List students = session.createQuery("SELECT s.id, s.name FROM Student s WHERE s.id in(:myids)")
.setParameterList("myids", new Object[]{1, 3, 5})
.list();
-------------------------------------------------
// List students = session.createQuery("SELECT s.id, s.name FROM Student s WHERE " +
// "date_format(s.createTime, '%Y-%m') =?")
// .setParameter(0, "2007-01")
// .list();
------------------------------------------------
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
List students = session.createQuery("SELECT s.id, s.name FROM Student s WHERE " +
"s.createTime between ? and ? ")
.setParameter(0, format.parseObject("2007-01-01"))
.setParameter(1, format.parseObject("2007-03-01"))
.list();
-----------------------------------------------
//嵌入原生sql测试
SQLQuery sqlQuery = session.createSQLQuery("select * from t_student");
List students = sqlQuery.list();
for (Iterator iter = students.iterator();iter.hasNext();) {
Object[] obj = (Object[])iter.next();
System.out.println(obj[0] + ", " + obj[1]);
}
-------------------------------------------------
//* 外置的命名查询测试
List students = session.getNamedQuery("searchStudents")
.setParameter(0, 10)
.list();
for (Iterator iter = students.iterator();iter.hasNext();) {
Student student = (Student)iter.next();
System.out.println(student.getName());
}
select s from Student s where s.id < ?
]]>
外置的命名查询
* 在映射文件中通过标签定义hql
* 在程序中使用session.getNameQuery()方法获得这个查询
参见:Student.hbm.xml,NameQueryTest.java
-----------------------------------------------------------------------------------------
6、查询过滤器
* 定义过滤器参数
* 在类映射文件中使用这些参数
* 在session中启用过滤器
参见:Student.hbm.xml,FilterQueryTest.java
//通过下面的代码自动为本类的所有sql增加上where id session.enableFilter("idfilter")
.setParameter("myid", 10);
List students = session.createQuery("from Student")
.list();
for (Iterator iter = students.iterator();iter.hasNext();) {
Student student = (Student)iter.next();
System.out.println(student.getName());
}
-------------------------------------------------
7、对象导航查询,在HQL语句中,可以使用.的方式进行对象导航【重要】
参见:ObjectNavQueryTest.java
//下面中的s.classes.id就是进行了对象的导航,由student对象导航到classes的对象
List students = session.createQuery("select s.name from Student s where s.classes.id < 2").list();
for (Iterator iter = students.iterator();iter.hasNext();) {
String name = (String)iter.next();
System.out.println(name);
}
----------------------------------------------------
8、连接查询(在对象里可以直接导航)【重要】
* 内连接
* 外连接(左连接/右连接)
参见:JionQueryTest
/**
* 内连接,从Student连接到Classes
*
*/
List students = session.createQuery("select c.name, s.name from Student s join s.classes c ")
.list();
for (Iterator iter = students.iterator();iter.hasNext();) {
Object[] obj = (Object[])iter.next();
System.out.println(obj[0] + ", " + obj[1]);
}
//左外连接
List students = session.createQuery("select c.name, s.name from Classes c left join c.students s ")
.list();
//右外连接
List students = session.createQuery("select c.name, s.name from Classes c right join c.students s ")
.list();
/**
* 内连接,从Classes连接到Student,代码省略,请自己写。
*
*/
--------------------------------------------
9、统计查询
参见:StatQueryTest.java
List students = session.createQuery("select count(*) from Student").list();
Long count = (Long)students.get(0);
System.out.println(count);
int total = ((Integer)session.createQuery("select count(*) from student").uniqueResult).intValue();
List students = session.createQuery("select c.id, c.name, count(s) from Student s join " +
"s.classes c group by c.id, c.name").list();
for (Iterator iter = students.iterator();iter.hasNext();) {
Object[] obj = (Object[])iter.next();
System.out.println(obj[0] + ", " + obj[1] + ", " + obj[2]);
}
----------------------------------------------------------
10、分页查询【重要】
* 通过query接口中的setFirstResult()和setMaxResults() 进行分页
参见:PageQueryTest
Query query = session.createQuery("from Student");
query.setFirstResult(27);
query.setMaxResults(5);
List students = query.list();
------------------------------------------------------------
11、DML风格的操作(尽量少用,因为它直接对数据库操作,而不是对缓存)
/**
* 使用这种风格的操作,将会造成内存中的对象与数据库中的数据不同步,所以
* 建议尽量少使用
*/
Query updateQuery = session.createQuery("update Student a set a.name=? where a.id in(:ids)");
updateQuery.setParameter(0, "张三");
updateQuery.setParameterList("ids", new Object[]{1, 2});
updateQuery.executeUpdate();
session.getTransaction().commit();