* 对象图导航检索方式 -- 对象导航查询
* OID检索方式 -- 用session的get()/load()方法,就是利用id查询
* HQL检索方式 -- 面向对象的查询语言
* QBC检索方式
* SQL检索方式
最优选择QBC(Query By Criteria)查询,特别是离线查询对象很好用;最后选择SQLQuery;
命名查询:
好处:不用特别记住参数是第几个,直接用命名的方式代替;对于参数很多的情况很好用
@Test
public void test011() {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Query query = session.createQuery("from Employee where ename = :ename");
query.setString("ename", "市场1号");
List list = query.list();
for (Employee employee : list) {
System.out.println(employee);
}
// 释放资源
transaction.commit();
session.close();
}
@Test
public void test011() {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Query query = session.createQuery("from Employee where ename like :ename and eid >:eid");
query.setString("ename", "%市场%");
query.setInteger("eid", 5);
List list = query.list();
for (Employee employee : list) {
System.out.println(employee);
}
// 释放资源
transaction.commit();
session.close();
}
投影检索:
其实就是根据不同的字段来查询,如果查询的是多个字段,就会将每条查询结果封装成为一个数组。
@Test//投影查询
public void test013() {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Query query = session.createQuery("select eid,ename from Employee ");
List
投影构造查询:
这种方法需要创建对应参数的构造函数,同时也不要忘记了保留无参数的构造函数,这样只封装了需要的参数到持久化类的对象中去。
@Test//投影构造查询
public void test014() {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Query query = session.createQuery("select new Employee(eid,ename) from Employee ");
List list = query.list();
for (Employee employee : list) {
System.out.println(employee);
}
// 释放资源
transaction.commit();
session.close();
}
QBC是一种完全面向对象的查询语言,所有使用的方法类都是对象
1)使用Order类进行排序查询
使用order类,通过其order的静态方法产生Order对象(排序对象)
2)api
* static Order desc(String propertyName)Order类的静态方法,返回Order的实例对象,按照propertyName(持久化类的属性名)进行降序排列。
* static Order asc(String propertyName)
* criteria.addOrder(Order order),Criteria对象,增加排序对象
@Test//Order类,按照单个字段进行排序
public void test015() {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Criteria criteria = session.createCriteria(Employee.class);
Order desc = Order.desc("eid");
criteria.addOrder(desc);
List list = criteria.list();
for (Object object : list) {
System.out.println(object);
}
// 释放资源
transaction.commit();
session.close();
}
@Test//Order类,按照多个字段进行排序
public void test016() {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Criteria criteria = session.createCriteria(Employee.class);
Order desc = Order.desc("eid");
Order asc = Order.asc("department");
//先加入哪一个排序条件就按照哪一个排序条件进行排序,如果相等的情况才会按照第二个排序条件进行排序
criteria.addOrder(desc);
criteria.addOrder(asc);
List list = criteria.list();
for (Object object : list) {
System.out.println(object);
}
// 释放资源
transaction.commit();
session.close();
}
2)Projection类
Projection可以完成分组统计 、 获取最大值 、 获取最小值 、 获取记录条数
细节:分组和统计、以及得出最大最小值、符合条件的记录数都用Projection
使用Projection,Projections和ProjectList类
* Projection:对象,分组统计对象,对于每个分组或者统计条件,创建一个Projection对象
* Projections:工具类,用于获得Projection实例对象
* ProjectionList:分组统计对象的集合,用于保存多个分组的统计对象
api:
a) Projections工具类的静态方法,返回值是一个Projection实例对象
Projections.groupProperty(String propertyName)
b)Projections.max(String propertyName) //可以用于数据表中某个字段的最大最小值
Projections.avg(String propertyName)
Projections.rouCount(String propertyName)
Projections.count(String propertyName)
Projections.min(String propertyName)
Projections.countDistinct(String propertyName)
c)criteria.setProjection(Projection projection):
--Criteria对象,设置分组统计对象。
d) static ProjectionList projectionList():
–获取projection集合对象,因Criteria对象,只能保存一个Projection对象,在进行分组统计的联合使用时,必定存在二个及以上的Projection对象,所以,需要ProjectionList来保存。
案例:
@Test//查询id最大的员工
public void test017() {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Criteria criteria = session.createCriteria(Employee.class);
Projection projection = Projections.max("eid");
criteria.setProjection(projection);
Object uniqueResult = criteria.uniqueResult();
System.out.println(uniqueResult);
// 释放资源
transaction.commit();
session.close();
}
@Test//查询记录条数
public void test017() {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Criteria criteria = session.createCriteria(Employee.class);
Projection projection = Projections.count("eid");
criteria.setProjection(projection);
Object uniqueResult = criteria.uniqueResult();
System.out.println(uniqueResult);
// 释放资源
transaction.commit();
session.close();
}
@Test//按性别分类和按照分类进行查询各类的记录条数,就是分组统计:先进行分组,然后进行统计
public void test018() {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Criteria criteria = session.createCriteria(Employee.class);
Projection projection1 = Projections.groupProperty("sex");
Projection projection2 = Projections.count("id");
ProjectionList projectionList = Projections.projectionList();
//为什么用ProjectionList,因为setProjection()方法底层只能够加入一个条件
projectionList.add(projection1);
projectionList.add(projection2);
criteria.setProjection(projectionList);
List
DetachedCriteria的定义
常见API介绍
a. static DetachedCriteria forClass(Class clazz): // DetechedCriteria的静态方法,用于创建DetechedCriteria实例对象,clazz指需要查询的持久化类的字节码对象。
b. 增加查询条件,排序,分组统计,和普通的Criteria完全一样。
c. Criteria getExecutableCriteria(Session session): //成员方法,通过session对象,获得普通的Criteria对象,完成查询操作。
@Test//离线条件查询
public void test020() {
//创建离线对象
DetachedCriteria dc = DetachedCriteria.forClass(Employee.class);
//设定查询条件
dc.add(Restrictions.gt("eid", 5));
//获取session
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
//离线查询对象通过session,可以获得可以使用的criteria,相当于复活了
Criteria criteria = dc.getExecutableCriteria(session);
List list = criteria.list();
for (Object object : list) {
System.out.println(object);
}
transaction.commit();
session.close();
}
离线条件查询的价值:
例如京东的查询筛选,筛选条件十分多,而且可能是多选就可以采取离线条件查询,先把条件一个一个的加入到离线对象中去,然后复活对象进行查询。
HQL的多表查询(了解)
多表查询只能够使用HQL语言查询
@Test
public void test01() {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Query query = session.createQuery("from Employee e,Department d where e.department = d.did ");
//注意,在HQL语言中,判定两个字段是不是相等用的就是其id判断的
List
迫切内联接:查询到的结果,封装成一个对象,其他的数据,封装到这个对象的关联对象。
使用迫切内连接的时候一定要加上去重的条件
迫切内联接和普通内联接的区别:
a. fetch:表示:迫切
b. 普通内联接:查询到的结果,会封装成2个对象。
c. 迫切内联接:查询到的结果,封装成一个对象,其他的数据,封装到这个对象的关联对象。
* 因为数据存在重复,需要去重:distinct
* 标准写法:select distinct x from Department x inner join fetch x.employees
@Test //迫切内连接
public void test03() {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Query query = session.createQuery("select distinct d from Department d inner join fetch d.employees");
List list = query.list();
for (Department object : list) {
System.out.println(object);
}
// 释放资源
transaction.commit();
session.close();
}
原因:hibernate的关联查询(级联),非常优美。但严重的影响性能。为了提高性能,hibernate增加了补丁,即抓取策略。
抓取策略:只针对如何获取(查询)关联对象进行优化。
抓取策略,需要配合延迟加载一起使用。
了解抓取策略:
1. 抓取策略是什么
a. 简单而言:hibernate如何获取关联对象的方法。
b. 是hibernate提升性能的一种方法。
c. 使用抓取策略的时候,延迟加载也会影响查询性能。所以,抓取策略和延迟加载,是配合使用。
延迟加载定义
延迟加载的分类
a. 类级别的延迟加载
(1) 查询某个对象时,是否延迟,标签上配置lazy属性,默认值是:true,默认延迟加载。
b. 关联级别的延迟加载。
(1) 查询一个对象的关联对象时,是否延迟。在或上配置延迟。
(2) hibernate关联对象默认采用延迟加载。可以避免一些不必要的性能开销
一)set标签 中配置fetch抓取策略和lazy延迟加载
1)set标签 中配置fetch抓取策略和lazy延迟加载
a. fetch的取值:抓取策略
(1) select.默认值,发送普通的select语句,用到什么查什么
(2) join:发送迫切左外联接去查询。一次性全部查询完
(3) subselect。发送一条子查询语句查询其关联对象.(查询多个对象,才能体现),配置了之后,要查询多个关联对象的时候,只发送一条sql语句将所有关联对象查询出来。
b. lazy的取值:
(1) true。默认值,采用延迟加载
(2) false.不采用延迟加载
(3) extra. 极其懒惰的
2)理解fetch和lazy的取值
a. fetch,配置抓取策略。不同的配置,在查询关联对象时,发送的SQL语句不同。
b. lazy,配置延迟加载。不同的配置,在查询关联对象时,发送SQL语句的时间不同。(立即发送,还是延迟发送)
3)详解
(1) fetch和lazy,关注都是查询关联对象。
(2) fetch=”join”,发送迫切左外连接,把当前对象及其关联对象,一条SQL语句,全部获取。无需再次发送SQL语句,进行关联对象查询,也就无所谓延迟加载的设定(lazy失效)
(3) fetch=”subselect”,需要查询多个对象,才能体现。
(4) lazy=”extra”,意味着“极其懒惰的”,
二)many-to-one上的fetch和lazy
1. 验证的场景
* 查询某个员工,及该员工所在部门的名称
三)关联对象的抓取策略:批量抓取
1. 感受批量抓取
a. 场景1:查询所有部门,并查询每个部门的所有员工的名字
* 在set上配置:batch-size=”3”
b. 场景2:查询所有员工,并查询其对应部门的名称
* batch-size必须配置在一的一方的标签上
案例:
理解配置subselect策略的时候的现象:
@Test
public void test02(){
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Criteria criteria = session.createCriteria(Department.class);
List list = criteria.list();
for (Department object : list) {
System.out.println(object.toString());
System.out.println(object.getEmployees().size());
}
transaction.commit();
session.close();
}
配置为select抓取策略的时候的sql语句:
有多少条记录,执行多少条sql语句进行查询数据库
Hibernate:
select
this_.did as did1_0_0_,
this_.dname as dname2_0_0_
from
department this_
Hibernate:
select
employees0_.e_did as e_did4_1_0_,
employees0_.eid as eid1_1_0_,
employees0_.eid as eid1_1_1_,
employees0_.ename as ename2_1_1_,
employees0_.sex as sex3_1_1_,
employees0_.e_did as e_did4_1_1_
from
employee employees0_
where
employees0_.e_did=?
Hibernate:
select
employees0_.e_did as e_did4_1_0_,
employees0_.eid as eid1_1_0_,
employees0_.eid as eid1_1_1_,
employees0_.ename as ename2_1_1_,
employees0_.sex as sex3_1_1_,
employees0_.e_did as e_did4_1_1_
from
employee employees0_
where
employees0_.e_did=?
Hibernate:
select
employees0_.e_did as e_did4_1_0_,
employees0_.eid as eid1_1_0_,
employees0_.eid as eid1_1_1_,
employees0_.ename as ename2_1_1_,
employees0_.sex as sex3_1_1_,
employees0_.e_did as e_did4_1_1_
from
employee employees0_
where
employees0_.e_did=?
Hibernate:
select
employees0_.e_did as e_did4_1_0_,
employees0_.eid as eid1_1_0_,
employees0_.eid as eid1_1_1_,
employees0_.ename as ename2_1_1_,
employees0_.sex as sex3_1_1_,
employees0_.e_did as e_did4_1_1_
from
employee employees0_
where
employees0_.e_did=?
配置为subselect抓取策略时候的语句:
Hibernate:
select
this_.did as did1_0_0_,
this_.dname as dname2_0_0_
from
department this_
Hibernate:
select
employees0_.e_did as e_did4_1_1_,
employees0_.eid as eid1_1_1_,
employees0_.eid as eid1_1_0_,
employees0_.ename as ename2_1_0_,
employees0_.sex as sex3_1_0_,
employees0_.e_did as e_did4_1_0_
from
employee employees0_
where
employees0_.e_did in (
select
this_.did
from
department this_
)