- Hibernate的查询的方式
- OID检索
- get或load方法进行的查询
- 对象导航检索
- linkman.getCustomer();
- HQL检索
- 用于接收hql语句进行查询,面向对象查询方式。
- 通过session.createQuery(String hql);
- 简单查询
- 别名查询
- 排序查询
- 条件查询
- 分组统计查询
- 投影查询
- 分页查询
- 多表查询
- QBC检索
- 用于进行条件查询(Query By Criteria),更加面向对象的方式。
- 通过session.createCriteria(Class clazz);
- 简单查询
- 排序查询
- 分组统计查询
- 分页查询
- 条件查询
- 离线条件查询
- SQL检索
- 用于接收sql进行查询。
- 通过session.createSQLQuery(String sql);
- OID检索
- Hibernate的抓取策略(优化)
- 延迟加载
- 类级别 在<class>上配置lazy属性
- 关联级别 在<set>、<many-to-one>上配置的lazy属性
- 抓取策略
- Set上的fetch和lazy
- fetch :
- select
- join
- subselect
- lazy :
- true
- false
- extra
- fetch :
- many-to-one上fetch和lazy
- fetch
- select
- join
- lazy
- proxy
- false
- no-proxy
- fetch
- Set上的fetch和lazy
- 批量抓取
- 延迟加载
1.1 Hibernate的查询的方式
在Hibernate中提供了很多种的查询的方式。Hibernate共提供了五种查询方式。
1.1.1 Hibernate的查询方式:OID查询
OID检索:Hibernate根据对象的OID(主键)进行检索
1.1.1.1 使用get方法
Customer customer = session.get(Customer.class,1l);
1.1.1.2 使用load方法
Customer customer = session.load(Customer.class,1l);
1.1.2 Hibernate的查询方式:对象导航检索
对象导航检索:Hibernate根据一个已经查询到的对象,获得其关联的对象的一种查询方式。
LinkMan linkMan = session.get(LinkMan.class,1l);
Customer customer = linkMan.getCustomer();
Customer customer = session.get(Customer.class,2l);
Set<LinkMan> linkMans = customer.getLinkMans();
1.1.3 Hibernate的查询方式:HQL检索
HQL查询:Hibernate Query Language,Hibernate的查询语言,是一种面向对象的方式的查询语言,语法类似SQL。通过session.createQuery(),用于接收一个HQL进行查询方式。
1.1.3.1 HQL的简单查询
public void demo2() {
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
// 简单的查询
Query query = session.createQuery("from Customer");
List<Customer> list = query.list();
// sql中支持*号的写法:select * from cst_customer; 但是在HQL中不支持*号的写法。
/*
* Query query = session.createQuery("select * from Customer");// 报错
* List<Customer> list = query.list();
*/
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();
}
1.1.3.2 HQL的别名查询
public void demo3() {
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
// 别名的查询1
/*Query query = session.createQuery("from Customer c");
List<Customer> list = query.list();*/
// 别名的查询2
Query query = session.createQuery("select c from Customer c");
List<Customer> list = query.list();
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();
}
1.2.3.3 HQL的排序查询
public void demo4() {
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
//默认排序
// List<Customer> list = session.createQuery("from Customer order by cust_id").list();
List<Customer> list = session.createQuery("from Customer order by cust_id desc").list();
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();
}
1.2.3.4 HQL的条件查询
public void demo5() {
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
//1.按位置绑定
//单个条件
/*Query query = session.createQuery("from Customer where cust_source=?");
query.setParameter(0, "小卡片");
List<Customer> list = query.list();*/
//多个条件
/*Query query = session.createQuery("from Customer where cust_source=? and cust_name like ?");
query.setParameter(0, "小卡片");
query.setParameter(1, "王%");
List<Customer> list = query.list();*/
//2.按名称绑定
Query query = session.createQuery("from Customer where cust_source =:aaa and cust_name like :bbb");
query.setParameter("aaa", "小卡片");
query.setParameter("bbb", "王%");
List<Customer> list = query.list();
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();
}
1.2.3.5 HQL的投影查询
投影查询:查询对象的某个或某些属性。
public void demo6() {
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
// 投影查询
// 单个属性
/*List<Object> list = session.createQuery("select c.cust_name from Customer c").list();
for (Object object : list) {
System.out.println(object);
}*/
// 多个属性
/*List<Object[]> list = session.createQuery("select c.cust_name,c.cust_source from Customer c").list();
for (Object[] objects : list) {
System.out.println(Arrays.toString(objects));
}*/
// 查询多个属性,但是我想封装到对象中。前提要写出被查对象属性的构造函数。
List<Customer> list = session.createQuery("select new Customer(cust_name,cust_source) from Customer").list();
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();
}
1.2.3.6 HQL的分页查询
public void demo7() {
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
//分页查询
Query query = session.createQuery("from LinkMan");
query.setFirstResult(10);
query.setMaxResults(10);
List<LinkMan> list = query.list();
for (LinkMan linkMan : list) {
System.out.println(linkMan);
}
tx.commit();
}
1.2.3.7 HQL的分组统计查询
public void demo8() {
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
// 聚合函数的使用:count(),max(),min(),avg(),sum()
Object object = session.createQuery("select count(*) from Customer").uniqueResult();
System.out.println(object);
// 分组统计:
List<Object[]> list = session.createQuery("select cust_source,count(*) from Customer group by cust_source").list();
for (Object[] objects : list) {
System.out.println(Arrays.toString(objects));
}
tx.commit();
}
1.2.3.8 HQL的多表查询
- SQL的多表查询
连接查询
1. 交叉连接:笛卡尔积 select * from A,B;
2. 内连接 : inner join (inner 可以省略) 查询两个表的公共部分
隐式内连接:看不到inner join
select * from A,B where A.id = B.aid;
显示内连接:可以看到inner join
select * from A inner join B on A.id = B.aid;
3.外连接 :
左外连接:left outer join(outer 可以省略) 查询左边表的全部信息以及两个表的公共部分
select * from A left outer join B on A.id= B.aid;
右外连接:right outer join(outer 可以省略) 查询右边表的全部信息以及两个表的公共部分
select * from A right outer join B on A.id = B.aid;
子查询
- HQL的多表查询
- 连接查询
- 交叉连接
- 内连接
- 显示内连接
- 隐式内连接
- 迫切内连接
- 外连接
- 左外连接
- 右外连接
- 迫切左外连接
- 连接查询
public void demo9() {
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
// SQL:SELECT * FROM cst_customer c INNER JOIN cst_linkman l ON c.cust_id = l.lkm_cust_id;
// HQL:内连接 from Customer c inner join c.linkMans
/*
* List<Object[]> list = session.createQuery("from Customer c inner join c.linkMans").list();
* for (Object[]objects : list) { System.out.println(Arrays.toString(objects)); }
*/
// HQL:迫切内连接 其实就在普通的内连接inner join后添加一个关键字fetch. from Customer c inner
// join fetch c.linkMans
List<Customer> list = session.createQuery("select distinct c from Customer c inner join fetch c.linkMans").list();// 通知hibernate,将另一个对象的数据封装到该对象中
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();
}
1.1.4 Hibernate的查询方式:QBC检索
QBC查询:Query By Criteria,条件查询。是一种更加面向对象化的查询的方式。
1.1.4.1 简单查询
public void demo1() {
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
//获得Criteria对象
Criteria criteria = session.createCriteria(Customer.class);
List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();
}
1.1.4.2 排序查询
public void demo2() {
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
//获得Criteria对象
Criteria criteria = session.createCriteria(Customer.class);
// criteria.addOrder(Order.asc("cust_id"));//升序
criteria.addOrder(Order.desc("cust_id"));//降序
List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();
}
1.1.4.3 分页查询
public void demo3() {
Session session=HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
Criteria criteria = session.createCriteria(LinkMan.class);
criteria.setFirstResult(0);
criteria.setMaxResults(10);
List<LinkMan> list = criteria.list();
for (LinkMan linkMan : list) {
System.out.println(linkMan);
}
transaction.commit();
}
1.1.4.4 条件查询
public void demo4(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
// 条件查询
Criteria criteria = session.createCriteria(Customer.class);
// 设置条件:
/**
* = eq
* > gt
* >= ge
* < lt
* <= le
* <> ne
* like
* in
* and
* or
*/
criteria.add(Restrictions.eq("cust_source", "小广告"));
// criteria.add(Restrictions.or(Restrictions.like("cust_name", "李%")));
criteria.add(Restrictions.like("cust_name", "李%"));
List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();
}
1.1.4.5 统计查询
public void demo5(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
Criteria criteria = session.createCriteria(Customer.class);
/**
* add :普通的条件。where后面条件
* addOrder :排序
* setProjection :聚合函数 和 group by having
*/
criteria.setProjection(Projections.rowCount());
Long num = (Long) criteria.uniqueResult();
System.out.println(num);
tx.commit();
}
1.1.4.6 离线条件查询(SSH)---DetachedCriteria
public void demo6(){
DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Customer.class);
detachedCriteria.add(Restrictions.like("cust_name", "李%"));
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
Criteria criteria = detachedCriteria.getExecutableCriteria(session);
List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer);
}
transaction.commit();
}
1.1.5 Hibernate的查询方式:SQL检索
1.1.5.1 SQL查询
SQL查询:通过使用sql语句进行查询
public void demo1(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
/*SQLQuery sqlQuery = session.createSQLQuery("select * from cst_customer");
List<Object[]> list = sqlQuery.list();
for (Object[] objects : list) {
System.out.println(Arrays.toString(objects));
}*/
SQLQuery sqlQuery = session.createSQLQuery("select * from cst_customer");
sqlQuery.addEntity(Customer.class);
List<Customer> list = sqlQuery.list();
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();
}
1.2 Hibernate的抓取策略(优化)
1.2.1延迟加载的概述
1.2.1.1什么是延迟加载
延迟加载:lazy(懒加载)。执行到该行代码的时候,不会发送语句去进行查询,在真正使用这个对象的属性的时候才会发送SQL语句进行查询。
1.2.1.2 延迟加载的分类
类级别的延迟加载
指的是通过load方法查询某个对象的时候,是否采用延迟。session.load(Customer.class,1l);
类级别延迟加载通过<class>上的lazy进行配置,如果让lazy失效
- 将lazy设置为false
- 将持久化类使用final修饰
- Hibernate. Initialize()
关联级别的延迟加载
- 指的是在查询到某个对象的时候,查询其关联的对象的时候,是否采用延迟加载。
- 通过在set或者many-to-one标签配置lazy属性
Customer customer = session.get(Customer.class,1l);
customer.getLinkMans();----通过客户获得联系人的时候,联系人对象是否采用了延迟加载,称为是关联级别的延迟。
抓取策略往往会和关联级别的延迟加载一起使用,优化语句。
public class HibernateDemo1 {
@Test
/**
* 类级别的延迟加载
* * 在<class>的标签上配置的lazy
*/
public void demo1(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
Customer customer = session.load(Customer.class, 1l);
Hibernate.initialize(customer);//令延迟加载失效
System.out.println(customer);
tx.commit();
}
}
1.2.2 抓取策略
1.2.2.1 抓取策略的概述
- 通过一个对象抓取到关联对象需要发送SQL语句,SQL语句如何发送,发送成什么样格式通过策略进行配置。
- 通过<set>或者<many-to-one>上通过fetch属性进行设置
- fetch和这些标签上的lazy如何设置优化发送的SQL语句
1.2.2.2<set>上的fetch和lazy
- fetch:抓取策略,控制SQL语句格式
- select :默认值,发送普通的select语句,查询关联对象
- join :发送一条迫切左外连接查询关联对象(lazy失效)
- subselect :发送一条子查询查询其关联对象
- lazy:延迟加载,控制查询关联对象的时候是否采用延迟
- true :默认值,查询关联对象的时候,采用延迟加载
- false :查询关联对象的时候,不采用延迟加载
- extra :及其懒惰。
- 在实际开发中,一般都采用默认值。如果有特殊的需求,可能需要配置join。
/**
* 在<set>上的fetch和lazy
*/
public class HibernateDemo2 {
@Test
/**
* 默认情况:
*/
public void demo1(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
// 查询1号客户
Customer customer = session.get(Customer.class, 1l);// 发送一条查询客户的SQL
System.out.println(customer.getCust_name());
// 查看1号客户的每个联系人的信息
for (LinkMan linkMan : customer.getLinkMans()) {// 发送一条根据客户ID查询联系人的SQL
System.out.println(linkMan.getLkm_name());
}
tx.commit();
}
@Test
/**
* 设置fetch="select" lazy="true"
*/
public void demo2(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
// 查询1号客户
Customer customer = session.get(Customer.class, 1l);// 发送一条查询客户的SQL
System.out.println(customer.getCust_name());
// 查看1号客户的每个联系人的信息
for (LinkMan linkMan : customer.getLinkMans()) {// 发送一条根据客户ID查询联系人的SQL
System.out.println(linkMan.getLkm_name());
}
tx.commit();
}
@Test
/**
* 设置 fetch="select" lazy="false"
*/
public void demo3(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
// 查询1号客户
Customer customer = session.get(Customer.class, 1l);// 发送两条SQL语句:查询客户的名称,查询客户关联联系人
System.out.println(customer.getCust_name());
/*// 查看1号客户的每个联系人的信息
for (LinkMan linkMan : customer.getLinkMans()) {//
System.out.println(linkMan.getLkm_name());
}*/
System.out.println(customer.getLinkMans().size());
tx.commit();
}
@Test
/**
* 设置fetch="select" lazy="extra"
*/
public void demo4(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
// 查询1号客户
Customer customer = session.get(Customer.class, 1l);// 发送一条查询1号客户的SQL语句
System.out.println(customer.getCust_name());
System.out.println(customer.getLinkMans().size());// 发送一条select count() from ...;
tx.commit();
}
@Test
/**
* 设置fetch="join" lazy=失效
*/
public void demo5(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
// 查询1号客户
Customer customer = session.get(Customer.class, 1l);// 发送一条迫切左外连接查询记录
System.out.println(customer.getCust_name());
System.out.println(customer.getLinkMans().size());// 不发送
tx.commit();
}
@SuppressWarnings("unchecked")
@Test
/**
* 设置fetch="subselect" lazy="true"
*/
public void demo6(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
List<Customer> list = session.createQuery("from Customer").list();// 发送查询所有客户的SQL
for (Customer customer : list) {
System.out.println(customer.getCust_name());
System.out.println(customer.getLinkMans().size());// 发送一条子查询
}
tx.commit();
}
@SuppressWarnings("unchecked")
@Test
/**
* 设置fetch="subselect" lazy="false"
*/
public void demo7(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
List<Customer> list = session.createQuery("from Customer").list();// 发送查询所有客户的SQL,发送一条子查询
for (Customer customer : list) {
System.out.println(customer.getCust_name());
System.out.println(customer.getLinkMans().size());//
}
tx.commit();
}
}
1.2.2.3 <many-to-one>上的fetch和lazy
- fetch :抓取策略,控制SQL语句格式。
- select :默认值,发送普通的select语句,查询关联对象。
- join :发送一条迫切左外连接。(lazy失效)
- lazy :延迟加载,控制查询关联对象的时候是否采用延迟。
- proxy :默认值,proxy具体的取值,取决于另一端的<class>上的lazy的值,和它一样。
- false :查询关联对象,不采用延迟。
- no-proxy :(不会使用)
- 在实际开发中,一般都采用默认值。如果有特殊的需求,可能需要配置join。
/**
* many-to-one上的fetch和lazy测试
*/
public class HibernateDemo3 {
@Test
/**
* 默认值
*/
public void demo1(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
LinkMan linkMan = session.get(LinkMan.class, 1l);// 发送一条查询联系人语句
System.out.println(linkMan.getLkm_name());
System.out.println(linkMan.getCustomer().getCust_name());// 发送一条select语句查询联系人所关联的客户
tx.commit();
}
@Test
/**
* fetch="select" lazy="proxy"
*/
public void demo2(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
LinkMan linkMan = session.get(LinkMan.class, 1l);// 发送一条查询联系人语句
System.out.println(linkMan.getLkm_name());
System.out.println(linkMan.getCustomer().getCust_name());// 发送一条select语句查询联系人所关联的客户
tx.commit();
}
@Test
/**
* fetch="select" lazy="false"
*/
public void demo3(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
LinkMan linkMan = session.get(LinkMan.class, 1l);// 发送一条查询联系人语句,发送一条select语句查询联系人所关联的客户
System.out.println(linkMan.getLkm_name());
System.out.println(linkMan.getCustomer().getCust_name());//
tx.commit();
}
@Test
/**
* fetch="join" lazy=失效
*/
public void demo4(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
LinkMan linkMan = session.get(LinkMan.class, 1l);// 发送一条迫切左外连接查询联系人所关联的客户。
System.out.println(linkMan.getLkm_name());
System.out.println(linkMan.getCustomer().getCust_name());//
tx.commit();
}
}
1.2.3 批量抓取
1.2.3.1 什么是批量抓取
一批关联对象一起抓取,batch-size
1.2.3.2测试批量抓取
/**
* 批量抓取
*/
public class HibernateDemo4 {
@SuppressWarnings("unchecked")
@Test
/**
* 获取客户的时候,批量抓取联系人
* 在Customer.hbm.xml中set上配置batch-size
*/
public void demo1(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
List<Customer> list = session.createQuery("from Customer").list();
for (Customer customer : list) {
System.out.println(customer.getCust_name());
for (LinkMan linkMan : customer.getLinkMans()) {
System.out.println(linkMan.getLkm_name());
}
}
tx.commit();
}
@SuppressWarnings("unchecked")
@Test
/**
* 获取联系人的时候,批量抓取客户
* * 在Customer.hbm.xml中<class>上配置
*/
public void demo2(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
List<LinkMan> list = session.createQuery("from LinkMan").list();
for (LinkMan linkMan : list) {
System.out.println(linkMan.getLkm_name());
System.out.println(linkMan.getCustomer().getCust_name());
}
tx.commit();
}
}