Hibernate详解4(查询方式和抓取策略)

    xiaoxiao2022-07-14  155

    目录

    Hibernate的查询方式OID查询对象导航检索查询==HQL检索查询==简单查询别名查询条件查询投影查询排序查询分页查询分组统计查询HQL的多表查询 ==QBC检索查询==简单查询条件查询分页查询统计查询离线条件查询 SQL检索查询 Hibernate的抓取策略延迟加载的概述什么是延迟加载延迟加载的分类 抓取策略抓取策略的概述set标签上的fetch和lazy的使用代码实现 many-to-one标签上的fecth和lazy的使用代码实现 批量抓取什么是批量抓取获取一的一方的对象,批量抓取关联的多的一方的对象获取多的一方的对象,批量抓取关联一的一方的对象代码实现

    Hibernate的查询方式

    OID查询

    利用对象的ID进行检索

    使用get() 方法

    Customer customer = session.get(Customer.class,1l);

    使用load() 方法

    Customer customer = session.load(Customer.class,1l);

    对象导航检索查询

    Hibernate根据已经查询出来的对象,获得其关联对象的一种查询方式。

    Customer customer = session.get(Customer.class, 5l); Set linkMans = customer.getLinkMans();

    HQL检索查询

    是一种面向对象化的查询语言,语法类似于SQL,通过session.createQuery(),接受一个HQL进行查询。

    HQL的查询 查询的是对象 :from Customer, 如果使用条件查询,from Customer where cust_id = ? ,cust_id是用的对象中的属性

    简单查询

    @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(); }

    条件查询

    注意:设置条件时候,从 0 开始:query.setParameter(0,“aa”);

    @Test /** * 条件查询 */ public void demo5() { Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); // 条件的查询 // 一、按位置绑定:根据参数的位置进行绑定。 // 一个条件 /* * Query query = session.createQuery("from Customer where cust_name = ?"); * query.setParameter(0, "李兵"); 是从0 开始的,PreporeStatement 中是以 1 开始的 * 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 demo4() { Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); // 排序的查询 // 默认情况 // List<Customer> list = session.createQuery("from Customer order bycust_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 demo7() { Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); // 分页查询 Query query = session.createQuery("from LinkMans"); query.setFirstResult(5); //开始的位置 query.setMaxResults(5); //一页查询几个 List<LinkMans> list = query.list(); for (LinkMans LinkMans : list) { System.out.println(LinkMans); } 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(); }

    HQL的多表查询

    SQL的多表查询

    连接查询

    交叉连接 :笛卡尔积内连接 隐式内连接 :select * from A,B where A.id = B.id显示内连接 : select * from A inner join B on A.id=B.id 外链接 左外连接:select * from A left (outer) join B on A.id=B.id右外连接:select * from A right (outer) join B on A.id = B.id

    子查询 …

    HQL的多表查询

    连接查询 交叉连接 :笛卡尔积内连接 隐式内连接 :select * from A,B where A.id = B.id显示内连接 : select * from A inner join B on A.id=B.id迫切内连接 外链接 左外连接:select * from A left (outer) join B on A.id=B.id右外连接:select * from A right (outer) join B on A.id = B.id迫切左外连接 @Test /** * HQL的多表查询 */ public void demo9() { Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); // SQL:SELECT * FROM cst_customer c INNER JOIN cst_LinkMans l ON // c.cust_id = l.lkm_cust_id; // HQL:内连接 from Customer c inner join c.LinkManss /* * List<Object[]> list = session.createQuery( * "from Customer c inner join c.LinkManss").list(); for (Object[] * objects : list) { System.out.println(Arrays.toString(objects)); } */ // HQL:迫切内连接 其实就在普通的内连接inner join后添加一个关键字fetch. from Customer c inner // join fetch c.LinkManss List<Customer> list = session.createQuery("select distinct c from Customer c inner join fetch c.LinkManss") .list();// 通知hibernate,将另一个对象的数据封装到该对象中 for (Customer customer : list) { System.out.println(customer); } tx.commit(); }

    QBC检索查询

    QBC查询:Query By Criteria,条件查询。是一种更加面向对象化的查询的方式。

    简单查询

    @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(); }

    条件查询

    加条件的时候默认的是and连接,如果想使用or ,这样写:criteria.add(Restrictions.or(Restrictions.like(“cust_name”, “李%”))); 每添加一个条件,就是加一个and 拼接上条件

    @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 */ //使用or criteria.add(Restrictions.or(Restrictions.eq("cust_source","制药"),Restrictions.eq("cust_source", "产品"))); //默认使用and criteria.add(Restrictions.eq("cust_source", "产品")); criteria.add(Restrictions.or(Restrictions.like("cust_name", "张%"))); 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(LinkMans.class); criteria.setFirstResult(10); criteria.setMaxResults(10); List<LinkMans> list = criteria.list(); for (LinkMans LinkMans : list) { System.out.println(LinkMans); } tx.commit(); }

    统计查询

    add :普通的条件。where后面条件 addOrder :排序 setProjection :聚合函数 和 group by having

    @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(); }

    离线条件查询

    用于当多个条件进行判断的时候,如果条件非常多,就可以使用离线查询,这是脱离session使用

    @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(); }

    SQL检索查询

    @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的抓取策略

    延迟加载的概述

    什么是延迟加载

    延迟加载:lazy(懒加载),就是当查询到该行代码的时候,不会立即执行SQL语句,而是当用到该对象属性的时候,才会发送SQL语句进行查询。 例如:Customer cus = session.load(Customer.class,1l); ,当执行到这行代码的时候,不会立即发送sql语句,而是当使用他的时候 customer.getCust_name();才会发送sql语句。 使用customer.getCust_name();则不会发送sql语句,因为id是已知的。

    延迟加载的分类

    类级别的延迟加载 指的是使用load()方法查询某个对象的时候,是否采用延迟加载, session.load(Customer.class,1l);类级别的延迟加载使用<class>标签上的lazy属性进行配置的,lazy默认值为true,如何使lazy失效 将lazy的值改为false将持久化类用final修饰Hibernate.Initialize() 关联级别的延迟加载

    关联级别的加载:当查询出一个对象的时候,通过该对象去查询其关联对象,是否采用延迟加载

    Customer customer = session.get(Customer.class,1l); customer.getLinkMans();----通过客户获得联系人的时候,联系人对象是否采用了延迟加载,称为是关联级别的延迟。

    关联级别的加载往往和抓取策略一起使用,优化语句

    抓取策略

    抓取策略的概述

    通过一个对象获得其关联对象在抓取的时候需要发送SQL语句,采用什么样格式的SQL语?SQL语句如何发送?

    通过set标签或者many-to-one标签上的fetchsh属性的值进行设置 fetch属性作用是发送什么格式的sql语句,而lazy属性的作用是什么时候发送sql语句fetch和这些标签上的lazy如何设置优化发送的SQL语句???

    set标签上的fetch和lazy的使用

    查询到一的一方的对象,去关联查询多的一方的对象

    fetch:抓取策略,控制SQL语句的格式 select:默认值,发送正常形式的sql语句,查询关联对象join:发送采取 迫切左外连接形式的sql语句,查询关联对象subselect:发送采取子查询形式的sql语句,查询关联对象 lazy:延迟加载,控制查询其关联对象的时候,是否采用延迟加载(SQL语句什么时候进行发送)。 true:默认值,查询关联对象的时候,采用延迟加载false:查询关联对象的时候,不采用延迟加载extra:及其懒惰加载(与延迟加载发送的sql语句不一样)

    在实际开发中,一般都采用默认值。如果有特殊要求,采用join

    fetch:select --------------------- lazy:true fetch:select --------------------- lazy:false fetch:select --------------------- lazy:extra fetch:join --------------------- lazy:失效,在查询客户的时候,采用左外连接,直接就把联系人查出来了 fetch:subselect--------------------- lazy:true fetch:subselect--------------------- lazy:false fetch:subselect--------------------- lazy:extra

    代码实现

    package com.day04; import com.utils.HibernateUtils; import org.hibernate.Session; import org.hibernate.Transaction; import org.junit.Test; import java.util.List; /** * 在<set>上的fetch和lazy * 根据客户查询客户的联系人,在一 的一方(客户)的<set> 标签上设置 */ public class HibernateDemo5 { @Test /** * 默认情况: */ public void demo1(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); // 查询5号客户 Customer customer = session.get(Customer.class, 5l);// 发送一条查询客户的SQL System.out.println(customer.getCust_name()); // 查看1号客户的每个联系人的信息 for (LinkMans LinkMans : customer.getLinkMans()) {// 发送一条根据客户ID查询联系人的SQL System.out.println(LinkMans.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, 5l);// 发送一条查询客户的SQL System.out.println(customer.getCust_name()); // 查看1号客户的每个联系人的信息 for (LinkMans LinkMans : customer.getLinkMans()) {// 发送一条根据客户ID查询联系人的SQL System.out.println(LinkMans.getLkm_name()); } tx.commit(); } @Test /** * 设置 fetch="select" lazy="false" */ public void demo3(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); // 查询5号客户 Customer customer = session.get(Customer.class, 5l);// 发送两条SQL语句:查询客户的名称,查询客户关联联系人 System.out.println(customer.getCust_name()); // 查看1号客户的每个联系人的信息 // for (LinkMans LinkMans : customer.getLinkMans()) {// // System.out.println(LinkMans.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(); // 查询5号客户 Customer customer = session.get(Customer.class, 5l);// 发送一条查询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(); } }

    many-to-one标签上的fecth和lazy的使用

    查询到多的一方的对象,去关联查询一的一方的对象

    fetch:抓取策略,控制SQL语句的格式

    select:默认值,发送正常形式的sql语句,查询关联对象join:发送采取 迫切左外连接形式的sql语句,查询关联对象

    lazy:延迟加载,控制查询其关联对象的时候,是否采用延迟加载(SQL语句什么时候进行发送)。

    proxy:默认值,proxy具体的取值,取决于另一端的class标签上的lazy的值。class标签上lazy的值是什么,proxy就表示什么false:查询关联对象的时候,不采用延迟加载no-proxy:不会使用

    fetch:select --------------------- lazy:proxy fetch:select --------------------- lazy:false fetch:join --------------------- lazy:失效,在查询客户的时候,采用左外连接,直接就把联系人查出来了

    代码实现

    package com.day04; import com.utils.HibernateUtils; import org.hibernate.Session; import org.hibernate.Transaction; import org.junit.Test; /** * many-to-one上的fetch和lazy测试 * */ public class HIbernateDemo6 { @Test /** * 默认值 */ public void demo1(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); LinkMans LinkMans = session.get(LinkMans.class, 1l);// 发送一条查询联系人语句 System.out.println(LinkMans.getLkm_name()); System.out.println(LinkMans.getCustomer().getCust_name());// 发送一条select语句查询联系人所关联的客户 tx.commit(); } @Test /** * fetch="select" lazy="proxy" */ public void demo2(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); LinkMans LinkMans = session.get(LinkMans.class, 1l);// 发送一条查询联系人语句 System.out.println(LinkMans.getLkm_name()); System.out.println(LinkMans.getCustomer().getCust_name());// 发送一条select语句查询联系人所关联的客户 tx.commit(); } @Test /** * fetch="select" lazy="false" */ public void demo3(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); LinkMans LinkMans = session.get(LinkMans.class, 1l);// 发送一条查询联系人语句,发送一条select语句查询联系人所关联的客户 System.out.println(LinkMans.getLkm_name()); System.out.println(LinkMans.getCustomer().getCust_name());// tx.commit(); } @Test /** * fetch="join" lazy=失效 */ public void demo4(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); LinkMans LinkMans = session.get(LinkMans.class, 1l);// 发送一条迫切左外连接查询联系人所关联的客户。 System.out.println(LinkMans.getLkm_name()); System.out.println(LinkMans.getCustomer().getCust_name());// tx.commit(); } }

    批量抓取

    什么是批量抓取

    批量抓取就是批量抓取多个关联对象 ,使用属性batch-size=“3”,表示批量抓取一次抓取3个关联对象.

    获取一的一方的对象,批量抓取关联的多的一方的对象

    在一的一方的xml配置文件中的set标签上配置batch-size属性,默认值是1. 批量抓取,sql语句发送的格式和发送的时候是否使用延迟加载,使用fecth和lazy默认的值就可以. batch-size只是表示在抓取的时候抓取多个,控制抓取关联对象的个数.

    获取多的一方的对象,批量抓取关联一的一方的对象

    在一的xml配置文件中的class属性上,配置batch-size属性的值,而不是在多的一方的xml配置文件上的many-to-one标签上去设置batch-size的值,标签上也没有该属性.

    代码实现

    package com.day04; import com.utils.HibernateUtils; import org.hibernate.Session; import org.hibernate.Transaction; import org.junit.Test; import java.util.List; /** * 批量抓取 * */ public class HibernateDemo7 { @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 (LinkMans LinkMans : customer.getLinkMans()) { System.out.println(LinkMans.getLkm_name()); } } tx.commit(); } @SuppressWarnings("unchecked") @Test /** * 获取联系人的时候,批量抓取客户 * * 在Customer.hbm.xml中<class>上配置 */ public void demo2(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); List<LinkMans> list = session.createQuery("from LinkMans").list(); for (LinkMans LinkMans : list) { System.out.println(LinkMans.getLkm_name()); System.out.println(LinkMans.getCustomer().getCust_name()); } tx.commit(); } }
    最新回复(0)