一、Hibernate的查询方式:OID查询
1、OID检索:Hibernate根据对象的OID(主键)进行检索
1-1、使用get方法
Customer customer = session.get(Customer.class,1L);
1-2、使用load方法
Customer customer = session.load(Customer.class,1L);
3、对象导航检索:Hibernate根据一个已经查询到的对象,获得其关联的对象的一种查询方式。
Customer customer = session.get(Customer.class,1L); Set<LinkMan> linkManSet = customer.getLinkMans();
4-1、HQL查询
Hibernate Query Language,Hibernate的查询语言,是一种面向对象的方式的查询语言,语法类似SQL。通过session.createQuery(),用于接收一个HQL进行查询方式。
package com.turtle.test; import java.util.Arrays; import java.util.List; import com.turtle.dao.Customer; import com.turtle.dao.LinkMan; import com.turtle.utils.HibernateUtils; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction; import org.junit.Test; /** * HQL的查询方式的测试类 * * @author jt * */ public class Hibernater_01 { @Test /** * 初始化数据 */ public void demo1() { Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); // 创建一个客户 Customer customer = new Customer(); customer.setCust_name("李向文"); for (int i = 1; i <= 10; i++) { LinkMan linkMan = new LinkMan(); linkMan.setLkm_name("王东" + i); linkMan.setCustomer(customer); customer.getLinkMans().add(linkMan); session.save(linkMan); } session.save(customer); tx.commit(); } @Test /** * 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(); } @Test /** * 别名查询 */ public void demo3() { Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); // 别名的查询 /* * Query query = session.createQuery("from Customer c"); List<Customer> * list = query.list(); */ Query query = session.createQuery("select c from Customer c"); List<Customer> list = query.list(); for (Customer customer : list) { System.out.println(customer); } tx.commit(); } @Test /** * 排序查询 */ public void demo4() { Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); // 排序的查询 // 默认情况 // List<Customer> list = session.createQuery("from Customer order by // cust_id").list(); // 设置降序排序 升序使用asc 降序使用desc List<Customer> list = session.createQuery("from Customer order by cust_id desc").list(); for (Customer customer : list) { System.out.println(customer); } tx.commit(); } @Test /** * 条件查询 */ public void demo5() { Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); // 条件的查询 // 一、按位置绑定:根据参数的位置进行绑定。 // 一个条件 /* * Query query = session.createQuery("from Customer where cust_name = ?"); * 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(); */ // 二、按名称绑定 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(); } @Test /** * 投影查询 */ 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(); } @Test /** * 分页查询 */ public void demo7() { Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); // 分页查询 Query query = session.createQuery("from LinkMan"); query.setFirstResult(20); query.setMaxResults(10); List<LinkMan> list = query.list(); for (LinkMan linkMan : list) { System.out.println(linkMan); } tx.commit(); } @Test /** * 分组统计查询 */ 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(); } @Test /** * 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(); } }
4-2、 HQL的多表查询
SQL的多表查询
连接查询
交叉连接:笛卡尔积
select * from A,B;
内连接 :inner join (inner 可以省略)
隐式内连接:
select * from A,B where A.id = B.aid;
显示内连接:
select * from A inner join B on A.id = B.aid;
外连接 :
左外连接: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的多表查询
连接查询
交叉连接
内连接
显示内连接
隐式内连接
迫切内连接
外连接
左外连接
右外连接
迫切左外连接
5、QBC查询:Query By Criteria,条件查询。是一种更加面向对象化的查询的方式。
package com.turtle.test; import java.util.List; import com.turtle.dao.Customer; import com.turtle.dao.LinkMan; import com.turtle.utils.HibernateUtils; import org.hibernate.Criteria; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.criterion.DetachedCriteria; import org.hibernate.criterion.Order; import org.hibernate.criterion.Projections; import org.hibernate.criterion.Restrictions; import org.junit.Test; /** * QBC的查询 * @author jt * */ public class Hibernater_02 { @Test /** * 简单的查询 */ 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(); } @Test /** * 排序查询 */ public void demo2(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); // 排序查询 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(); } @Test /** * 分页查询 */ public void demo3(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); // 分页查询 Criteria criteria = session.createCriteria(LinkMan.class); criteria.setFirstResult(10); criteria.setMaxResults(10); List<LinkMan> list = criteria.list(); for (LinkMan linkMan : list) { System.out.println(linkMan); } tx.commit(); } @Test /** * 条件查询 */ 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(); } @Test /** * 统计查询 */ 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(); } @Test /** * 离线条件查询 */ 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(); } }
6、SQL查询:通过使用sql语句进行查询
package com.turtle.test; import java.util.Arrays; import java.util.List; import com.turtle.dao.Customer; import com.turtle.utils.HibernateUtils; import org.hibernate.SQLQuery; import org.hibernate.Session; import org.hibernate.Transaction; import org.junit.Test; /** * SQL查询 * @author jt * */ public class Hibernate_03 { @Test 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(); } }
二、 Hibernate的抓取策略(优化)
1、 延迟加载
什么是延迟加载
延迟加载:lazy(懒加载)。执行到该行代码的时候,不会发送语句去进行查询,在真正使用这个对象的属性的时候才会发送SQL语句进行查询。
延迟加载的分类
类级别的延迟加载
指的是通过load方法查询某个对象的时候,是否采用延迟。session.load(Customer.class,1l);
类级别延迟加载通过<class>上的lazy进行配置,如果让lazy失效
将lazy设置为false
将持久化类使用final修饰
Hibernate. Initialize()
关联级别的延迟加载
指的是在查询到某个对象的时候,查询其关联的对象的时候,是否采用延迟加载。
Customer customer = session.get(Customer.class,1l);
customer.getLinkMans();----通过客户获得联系人的时候,联系人对象是否采用了延迟加载,称为是关联级别的延迟。
抓取策略往往会和关联级别的延迟加载一起使用,优化语句。
package com.turtle.test2; import com.turtle.dao.Customer; import com.turtle.utils.HibernateUtils; import org.hibernate.Hibernate; import org.hibernate.Session; import org.hibernate.Transaction; import org.junit.Test; /** * Hibernate的延迟加载 * @author jt * */ public class Hibernate_01 { @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(); } }
2、抓取策略
抓取策略的概述
通过一个对象抓取到关联对象需要发送SQL语句,SQL语句如何发送,发送成什么样格式通过策略进行配置。
通过<set>或者<many-to-one>上通过fetch属性进行设置
fetch和这些标签上的lazy如何设置优化发送的SQL语句
2-1 <set>上的fetch和lazy
fetch:抓取策略,控制SQL语句格式
select :默认值,发送普通的select语句,查询关联对象
join :发送一条迫切左外连接查询关联对象
subselect :发送一条子查询查询其关联对象
lazy :延迟加载,控制查询关联对象的时候是否采用延迟
true :默认值,查询关联对象的时候,采用延迟加载
false :查询关联对象的时候,不采用延迟加载
extra :及其懒惰。
在实际开发中,一般都采用默认值。如果有特殊的需求,可能需要配置join。
package com.turtle.test2; import java.util.List; import com.turtle.dao.Customer; import com.turtle.dao.LinkMan; import com.turtle.utils.HibernateUtils; import org.hibernate.Session; import org.hibernate.Transaction; import org.junit.Test; /** * 在<set>上的fetch和lazy * @author jt * */ public class Hibernate_02 { @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(); } }
2-1<many-to-one>上的fetch和lazy
fetch :抓取策略,控制SQL语句格式。
select :默认值,发送普通的select语句,查询关联对象。
join :发送一条迫切左外连接。
lazy :延迟加载,控制查询关联对象的时候是否采用延迟。
proxy :默认值,proxy具体的取值,取决于另一端的<class>上的lazy的值。
false :查询关联对象,不采用延迟。
no-proxy :(不会使用)
在实际开发中,一般都采用默认值。如果有特殊的需求,可能需要配置join。
package com.turtle.test2; import com.turtle.dao.LinkMan; import com.turtle.utils.HibernateUtils; import org.hibernate.Session; import org.hibernate.Transaction; import org.junit.Test; /** * many-to-one上的fetch和lazy测试 * @author jt * */ public class Hibernate_03 { @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(); } }
3、批量抓取,一批关联对象一起抓取,batch-size
package com.turtle.test2; import java.util.List; import com.turtle.dao.Customer; import com.turtle.dao.LinkMan; import com.turtle.utils.HibernateUtils; import org.hibernate.Session; import org.hibernate.Transaction; import org.junit.Test; /** * 批量抓取 * @author jt * */ public class Hibernate_04 { @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(); } }