Hibernate笔记 6:查询相关

来自Wikioe
跳到导航 跳到搜索


单表查询

Hibernate 的检索方式主要有 5 种:分别为“导航对象图查询”、“OID 查询”、“HQL 查询”、“QBC 查询”和“SQL 查询”。

导航对象图查询


导航对象图查询:根据已经加载的对象,导航到他的关联对象。【利用类与类之间的关系来检索对象】 

前提是必须在对象关系映射文件上配置了关联关系。

示例:

		LinkMan linkMan = (LinkMan)session.get(LinkMan.class, 11);
		Customer customer = linkMan.getCustomer();

OID 查询


OID 查询:主要指用 Session 的 get() 和 load() 方法加载某条记录对应的对象。【利用 OID 检索对象】

示例:

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

HQL 查询


HQL(Hibernate Query Language)是面向对象的查询语言,它和 SQL 查询语言有些相似,但它使用的是类、对象和属性的概念,而没有表和字段的概念。

在 Hibernate 提供的各种检索方式中,HQL 是官方推荐的查询语言,也是使用最广泛的一种检索方式。

它具有如下功能:

  • 在查询语句中设定各种查询条件
  • 支持投影查询,即仅检索出对象的部分属性。
  • 支持分页查询
  • 支持分组查询,允许使用 group by 和 having 关键字。
  • 提供内置聚集函数,如 sum()、min() 和 max()。
  • 能够调用自定义 SQL 函数
  • 支持子查询,即嵌套查询。
  • 支持动态绑定参数


Hibernate 提供的 Query 接口是专门的 HQL 查询接口,它能够执行各种复杂的 HQL 查询语句。

完整的 HQL 语句结构如下:

select ... from ... where ... group by ... having ... order by ... asc/desc
  • 通常情况下,当检索数据表中的所有记录时,select 关键字可以省略;
    • 不支持“select *”。
  • HQL 中使用的是类名,而非表名;
    • 类名需要区分大小写。


基本查询

示例:

	@Test
	/**
	* HQL:基本检索
	*/
	public void demo(){
		Session session = HibernateUtils.getCurrentSession();
		Transaction tx = session.beginTransaction();
		
		// 查询所有
		//Query query = session.createQuery("from Customer");
		// 使用别名
		//Query query = session.createQuery("from Customer c");
		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
	/**
	* HQL:排序检索
	*/
	public void demo(){
		Session session = HibernateUtils.getCurrentSession();
		Transaction tx = session.beginTransaction();
		
		Query query = session.createQuery("from Customer order by cust_id desc");
		List<Customer> list = query.list();
		
		for (Customer customer : list){
			System.out.println(customer);
		}
		
		tx.commit();
	}

条件查询

示例:

	@Test
	/**
	*HQL:条件查询
	*/
	public void demo(){
		Session session = HibernateUtils.getCurrentSession();
		Transaction tx = session.beginTransaction();
		
		// 按位置绑定参数
		Query query1 = session.createQuery("from Customer where cust name =?");
		//query.setString(0,"中国移动");  // 按类型设置参数
		query.setParameter(0,"中国移动")
		
		List<Customer> list = query1.list();
		for (Customer customer : list){
			System.out.println(customer);
		}
		
		//按名称绑定参数
		Query query2 = session.createQuery("from Customer where cust name = :name");
		query.setParameter("name","中国联通")
		
		Customer customer = (Customer)query2.uniqueResult();
		System.out.println(customer);
		
		
		tx.commit();
	}

分页查询

示例:

	@Test
	/**
	*HQL:分页查询
	*/
	public void demo(){
		Session session = HibernateUtils.getCurrentSession();
		Transaction tx = session.beginTransaction();
		
		Query query = session.createQuery("from LinkMan order by lkm_id desc");
		query.setFirstResult(5);
		query.setMaxResults(5);
		
		List<LinkMan> list = query.list();
		for (LinkMan linkMan : list){
			System.out.printIn(linkMan);
		}
		
		tx.commit();
	}

统计查询

示例:

	@Test
	/**
	*HQL:统计查询
	*/
	public void demo(){
		Session session = HibernateUtils.getCurrentSession();
		Transaction tx = session.beginTransaction();
		
		Query query = session.createQuery("select count(*)from Customer");
		Long num = (Long)query.uniqueResult();
		System.out.println(num);
		
		tx.commit();
	}

投影查询

示例:

	@Test
	/**
	*HQL:投影查询
	*/
	public void demo(){
		Session session = HibernateUtils.getCurrentSession();
		Transaction tx = session.beginTransaction();
		
		// 投影查询一列
		List<String> list1 = session.createQuery("select cust_name	from Customer").list();
		for (String string : list1){
			System.out.println(string);
		}
		
		// 投影查询多列:
		List<Object>[] list2 = session.createQuery("select cust id,cust name from Customer").list();
		for (Object[] objects : list2){
			System.out.println(Arrays.tostring(objects));
		}
		
		// 投影的构造的方式查询:【!!!】
		List<Customer> list3 = session.createQuery("select new Customer(cust id,cust name) from Customer").list();
		for (Customer customer : list3){
			System.out.println(customer);
		}
		
		tx.commit();
	}

QBC 查询


QBC(Query By Criteria)是 Hibernate 提供的另一种检索对象的方式,它主要由 Criteria 接口、Criterion 接口和 Expression 类组成。

Criteria 接口是 Hibernate API 中的一个查询接口,它需要由 session 进行创建。
Criterion 是 Criteria 的查询条件,在 Criteria 中提供了 add(Criterion criterion) 方法来添加查询条件。

Restrictions 类中提供了大量的静态方法来创建查询条件:

方法 描述
Restrictions.eq 等于
Restrictions.allEq 使用 Map,使用 key/value 进行多个等于的比较
Restrictions.gt 大于 >
Restrictions.ge 大于等于 >=
Restrictions.lt 小于
Restrictions.le 小于等于 <=
Restrictions.between 对应 SQL 的 between 子句
Restrictions.like 对应 SQL 的 like 子句
Restrictions.in 对应 SQL 的 in 子句
Restrictions.and and 关系
Restrictions.or or 关系
Restrictions.sqlRestriction SQL 限定查询

基本查询

示例:

	@Test
	/**
	*QBC:简单查询
	*/
	public void demo(){
		Session session = HibernateUtils.getCurrentSession();
		Transaction tx = session.beginTransaction();
		
		Criteria criteria = session.createCriteria(Customer.class);
		
		List<Customer> list = criteria.list();
		for (Customer customer : list){
			System.out.println(customer);
		}
		
		tx.commit();
	}

条件查询

示例:

	@Test
	/**
	*QBC:条件查询
	*/
	public void demo(){
		Session session = HibernateUtils.getCurrentSession();
		Transaction tx = session.beginTransaction();
		
		Criteria criteria = session.createCriteria(Customer.class);
		//设置条件:
		//criteria.add(Restrictions.eg("cust name","老张"));
		criteria.add(Restrictions.like("cust name","老"))
		criteria.add(Restrictions.gt("cust id",11));
		
		List<Customer> list = criteria.list();
		for (Customer customer : list){
			System.out.println(customer);
		}
		
		tx.commit();
	}

分页查询

示例:

	@Test
	/**
	*QBC:分页查询
	*/
	public void demo(){
		Session session = HibernateUtils.getCurrentSession();
		Transaction tx = session.beginTransaction();
		
		Criteria criteria = session.createCriteria(LinkMan.class);
		//设置分页:
		criteria.setFirstResult(5);
		criteria.setMaxResults(5);

		List<LinkMan>list = criteria.list();
		for (LinkMan linkMan : list){
			System.out.println(linkMan);
		}
		
		tx.commit();
	}

排序查询

示例:

	@Test
	/**
	*QBC:排序查询
	*/
	public void demo(){
		Session session = HibernateUtils.getCurrentSession();
		Transaction tx = session.beginTransaction();
		
		Criteria criteria = session.createCriteria(LinkMan.class);
		//设置排序:
		criteria.addorder(Order.desc("1kmid"));

		List<LinkMan>list = criteria.list();
		for (LinkMan linkMan : list){
			System.out.println(linkMan);
		}
		
		tx.commit();
	}

统计查询

示例:

	@Test
	/**
	*QBC:统计查询
	*/
	public void demo(){
		Session session = HibernateUtils.getCurrentSession();
		Transaction tx = session.beginTransaction();
		
		Criteria criteria = session.createCriteria(LinkMan.class);
		criteria.setProjection(Projections.rowCount());
		
		Long count = (Long)criteria.uniqueResult();
		System.out.println(count);
		
		tx.commit();
	}

离线条件查询(DetachedCriteria)

DetachedCriteria 翻译为离线条件查询,因为它是可以脱离 Session 来使用的一种条件查询对象:
    Criteria 对象必须由 Session 对象来创建,即:必须先有 Session 才可以生成 Criteria 对象。而 DetachedCriteria 对象可以在其他层对条件进行封装。

主要优点:
在做一些特别复杂的条件查询的时候,往往会在 WEB 层向业务层传递很多的参数,业务层又会将这些参数传递给 DAO 层,最后在 DAO 中拼接 SQL 完成查询。
有了离线条件查询对象后,可以直接在 WEB 层将数据封装好,传递到业务层,再由业务层传递给 DAO 完成查询。

示例:

	@Test
	/**
	*离线条件查询:DetachedCriteria
	*
	*/
	public void demo(){
		//获得一个离线条件查询的对象
		DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Customer.class);
		detachedCriteria.add(Restrictions.eg("cust_name","中国移动"))
		
		Session session = HibernateUtils.getCurrentSession();
		Transaction tx = session.beginTransaction();
		
		//离线条件查询对象与session绑定
		List<Customer> list = detachedCriteria.getExecutableCriteria(session).list();
		
		for (Customer customer : list){
			System.out.println(customer);
		}
		
		tx.commit();
	}

多表查询

SQL 连接查询

  1. 交叉连接:交叉连接返回的结果是被连接的两个表中所有数据行的笛卡尔积,也就是返回“第一个表中符合查询条件的数据行数”乘以“第二个表中符合查询条件的数据行数”。
    语法格式:
    SELECT * from 1 CROSS JOIN 2;
    
    # 
    
    SELECT * from 1, 2;
    
    • 在实际开发中这种业务需求是很少见的,一般不会使用交叉连接,而是使用具体的条件对数据进行有目的的查询。
  2. 内连接(“简单连接”或“自然连接”):使用比较运算符对两个表中的数据进行比较,并列出与连接条件匹配的数据行,组合成新的记录 —— 即:只有满足条件的记录才能出现在查询结果中。
    语法格式:
    SELECT 查询字段 FROM 1 [INNER] JOIN 2 ON 1.关系字段 = 2.关系字段
    
    • 内连接其实还可以细分为如下两类:
      1. 隐式内连接:在语句中使用关键字“where”替代“inner join”。
        SELECT * from 1, 2 where 1.关系字段 = 2.关系字段;
        
      2. 显示内连接:在语句中明显的调用了“inner join”的关键字。
        SELECT * from 1 inner join 2 on 1.关系字段 = 2.关系字段;
        
        SELECT * from 1 join 2 on 1.关系字段 = 2.关系字段;
        
  3. 外连接:返回查询结果中不仅包含符合条件的数据,而且还包括左表(“左连接”或“左外连接”)、右表(“右连接”或“右外连接”)或两个表(“全外连接”)中的所有数据。
    语法格式:
    SELECT 所查字段 FROM 1 LEFT|RIGHT [OUTER] JOIN 2
    ON 1.关系字段 = 2.关系字段 WHERE 条件
    
    • 对于“左连接”和“右连接”,其查询结果是不一致的:
      1. 左连接LEFT JOIN):返回包括左表中的所有记录和右表中符合连接条件的记录。
        SELECT * from 1 1eft outer join 2 on 1.关系字段 = 2.关系字段;
        
        SELECT * from 1 1eft join 2 on 1.关系字段 = 2.关系字段;
        
      2. 右连接RIGHT JOIN):返回包括右表中的所有记录和左表中符合连接条件的记录。
        SELECT * from 1 right outer join 2 on 1.关系字段 = 2.关系字段;
        SELECT * from 1 right join 2 on 1.关系字段 = 2.关系字段;
        

HQL 连接查询

Hibernate 进行多表查询与 SQL 其实是很相似的,但是 HQL 会在原来 SQL 分类的基础上又多出来一些操作。
  1. 交叉连接
  2. 内连接
    1. 显示内连接
      	@Test
      	/**
      	*HQL的多表的连接查询:显示内连接
      	*/
      	public void demo(){
      		Session session = HibernateUtils.getCurrentSession();
      		Transaction tx = session.beginTransaction();
      		
      		List<Object[]> list = session.createQuery("from Customer c inner join c.linkMans").list();
      	
      		for(Object[] objects : list){
      			System.out.println(Arrays.tostring(objects));
      		}
      	
      		tx.commit();
      	}
      
    2. 隐式内连接
    3. 迫切内连接
      	@Test
      	/**
      	*HQL的多表的连接查询:迫切内连接
      	*/
      	public void demo(){
      		Session session = HibernateUtils.getCurrentSession();
      		Transaction tx = session.beginTransaction();
      		
      		List<Customer> list = session.createQuery("from Customer c inner join fetch c.linkMans").list();
      	
      		for(Customer customer : list){
      			System.out.println(Arrays.tostring(objects));
      		}
      	
      		tx.commit();
      	}
      
  3. 外连接
    1. 左外连接
    2. 迫切左外连接
    3. 右外连接

迫切连接

迫切连接:在连接语句中加入“fetch”关键字(非 SQL 关键字,只能在 HQL 中使用)

“迫切连接”与“非迫切连接”,生成的底层 SQL 和查询得到的结果集都是一样的,二者主要区别在于封装数据

  1. 迫切连接:封装的时候将属于各自对象的数据封装到各自的对象中,最后得到一个 List<Object[]>
  2. 非迫切连接:封装数据到对象中,最后得到一个 List<实体类名>
    • 会出现重复数据,所以一般通过 distinct 去掉重复值:
      		List<Customer> list = session.createQuery("select distinct c from Customer c inner join fetch c.linkMans").list();
      

抓取策略

“抓取策略”(查询策略):当应用程序需要在关联关系间进行导航的时候,如何获取关联对象的策略。

    —— 即:“查询到某个对象的时候,如何抓取其关联对象”


其作用是“提升性能”:可以在获取关联对象的时候,对发送的语句进行优化,但是往往需要和延迟加载一起使用来提升性能。

延迟加载(lazy 属性

延迟加载(懒加载,lazy load)是 Hibernate 关联关系对象默认的加载方式:在需要数据的时候,才真正执行数据加载操作。

其作用是为了避免无谓的性能开销。

延迟加载分为两类:

  1. 类级别延迟:查询某个对象(load 方法加载数据)的时候,是否采用有延迟。
    		Customer customer = session.load(Customer.class,11);
    
    • 通常在 <class> 标签上配置 lazy 属性。
  2. 关联级别的延迟:查询一个对象的关联对象的时候是否采用延迟加载。
    		Customer customer = session.get(Customer.class,11);
    		Set<LinkMan> linkMans = customer.getLinkMans();
    
    • 通常在 <set><many-to-one> 上配置 lazy 属性。
      • <set> 标签中 lazy 属性的取值:
        1. true:(默认值)采用延迟加载;
        2. false:检索关联对象的时候,不采用延迟加载;
        3. extra:及其懒惰的。
      • <many-to-one> 标签中 lazy 属性的取值:
        1. proxy:(默认值)是否采用延迟取决于“一端”类上的 lazy 属性的值;
        2. false:检索关联对象的时候,不采用延迟加载;
        3. no-proxy
抓取策略主要在于“关联级别的延迟”。  —— “类级别延迟”一般默认即可。

抓取策略(fetch 属性

通过在关联对象的 <set><many-to-one> 标签上配置 fetch 属性,以实现不同的效果。


注意:fetch 取值为 join 时,lazy 将会失效。
  1. <set> 标签中 fetch 属性的取值:
    1. select:(默认值)发送“普通 select 语句”来查询其关联对象;
    2. join:发送“迫切左外连接”来查询其关联对象;
    3. subselect:发送“子查询语句”来查询其关联对象。
  2. <many-to-one> 标签中 fetch 属性的取值:
    1. select:(默认值)发送“普通 select 语句”来查询其关联对象;
    2. join:发送“迫切左外连接”来查询其关联对象;

示例

  1. <set> 标签,以“查询 1 号客户,并获取其联系人数量”为例:
    1. (默认情况)fetch="select",lazy="true":
      	@Test
      	/**
      	* 查询1号客户,同时查询1号客户的联系人的数量
      	*(默认情况)<set>配置:fetch="select",lazy="true"
      	*/
      	public void demo(){
      		Session session = HibernateUtils.getCurrentSession();
      		Transaction tx = session.beginTransaction();
      		
      		//查询客户
      		Customer customer = session.get(Customer.class,11);   //发送一条“普通select”:查询客户
      		//获取客户的联系人数量
      		System.out.println(customer.getLinkMans().size());   //发送一条“普通select”:查询客户的所有联系人
      		
      		tx.commit();
      	}
      
    2. fetch="select",lazy="false":
      	@Test
      	/**
      	* 查询1号客户,同时查询1号客户的联系人的数量,
      	* <set>配置:fetch="select",lazy="false"
      	*/
      	public void demo(){
      		Session session = HibernateUtils.getCurrentSession();
      		Transaction tx = session.beginTransaction();
      		
      		//查询客户
      		Customer customer = session.get(Customer.class,11);   //发送两条“普通select”:1、查询客户,2、查询客户的所有联系人
      		//获取客户的联系人数量
      		System.out.println(customer.getLinkMans().size());   //不发送语句
      		
      		tx.commit();
      	}
      
    3. fetch="select",lazy="extra":
      	@Test
      	/**
      	* 查询1号客户,同时查询1号客户的联系人的数量
      	* <set>配置:fetch="select",lazy="extra"
      	*/
      	public void demo(){
      		Session session = HibernateUtils.getCurrentSession();
      		Transaction tx = session.beginTransaction();
      		
      		//查询客户
      		Customer customer = session.get(Customer.class,l1);   //发送一条“普通select”:查询客户
      		//获取客户的联系人数量
      		System.out.println(customer.getLinkMans().size());   //发送一条“普通select”:用 count(*) 语句统计联系人个数
      		
      		tx.commit();
      	}
      
    4. fetch="join",lazy 失效:
      	@Test
      	/**
      	* 查询1号客户,同时查询1号客户的联系人的数量.
      	* <set>配置:fetch="join",lazy 失效
      	*/
      	public void demo(){
      		Session session = HibernateUtils.getCurrentSession();
      		Transaction tx = session.beginTransaction();	
      		
      		//查询客户
      		Customer customer = session.get(Customer.class,1l);   //发送一条“迫切左外连接”:查询客户及其关联对象
      		//获取客户的联系人数量
      		System.out.println(customer.getLinkMans().size());   //不发送语句
      		
      		tx.commit();
      	}
      
    5. fetch="subselect",lazy="true":
      	@SuppressWarnings ("unchecked")
      	@Test
      	/**
      	* 查询1号客户,同时查询1号客户的联系人的数量.
      	* <set>配置:fetch="subselect",lazy="true"
      	*/
      	public void demo(){
      		Session session = HibernateUtils.getCurrentSession();
      		Transaction tx = session.beginTransaction();
      		
      		//查询所有客户(子查询不能查询某一个对象,查询多个对象来测试)
      		List<Customer> list = session.createQuery("from Customer").list();   //发送一条“普通select”:查询所有客户
      		
      		for (Customer customer : list){
      			System.out.println(customer.getLinkMans().size());   //发送一条“子查询”:查询客户的所有联系人
      		}
      		
      		tx.commit();
      	}
      
    6. fetch="subselect",lazy="false":
      	@SuppressWarnings ("unchecked")
      	@Test
      	/**
      	*查询1号客户,同时查询1号客户的联系人的数量.
      	*<set>配置:fetch="subselect",lazy="false"
      	*/
      	public void demo(){
      		Session session = HibernateUtils.getCurrentSession();
      		Transaction tx = session.beginTransaction();
      		
      		//查询所有客户(子查询不能查询某一个对象,查询多个对象来测试)
      		List<Customer> list = session.createQuery("from Customer").list();   //发送:1、“普通select”:查询所有客户,2、“子查询”:查询客户的联系人
      		
      		for (Customer customer : list){
      			System.out.println(customer.getLinkMans().size());
      		}
      		
      		tx.commit();
      	}
      
  2. <many-to-one> 标签,以“查询 1 号联系人,并获取其客户信息”为例:
    1. (默认情况)fetch="select",lazy="proxy":
      	@Test
      	/**
      	* 查询1号联系人,同时查询1号联系人所关联客户的信息
      	*(默认情况)<many-to-one>配置:fetch="select",lazy="proxy"
      	*/
      	public void demo(){
      		Session session = HibernateUtils.getCurrentSession();
      		Transaction tx = session.beginTransaction();
      		
      		//查询联系人
      		LinkMan linkMan = session.get(LinkMan.class,1l);   //发送一条“普通select”:查询联系人
      		//获取关联的客户信息
      		System.out.printin(linkMan.getCustomer().getCust_name());   //发送一条“普通select”:查询对应客户的信息
      		
      		tx.commit();
      	}
      
    2. fetch="select",lazy="false":
      	@Test
      	/**
      	* 查询1号联系人,同时查询1号联系人所关联客户的信息
      	* <many-to-one>配置:fetch="select",lazy="false"
      	*/
      	public void demo(){
      		Session session = HibernateUtils.getCurrentSession();
      		Transaction tx = session.beginTransaction();
      		
      		//查询联系人
      		LinkMan linkMan = session.get(LinkMan.class,1l);   //发送两条“普通select”:1、查询联系人,2、查询对应客户的信息
      		//获取关联的客户信息
      		System.out.println(linkMan.getCustomer().getCust_name());   //不发送
      		
      		tx.commit();
      	}
      
    3. fetch="join",lazy 失效:
      	@Test
      	/**
      	* 查询1号联系人,同时查询1号联系人所关联客户的信息
      	* <many-to-one>配置:fetch="join",lazy 失效
      	*/
      	public void demo(){
      		Session session = HibernateUtils.getCurrentSession();
      		Transaction tx = session.beginTransaction();
      		
      		//查询联系人
      		LinkMan linkMan = session.get(LinkMan.class,1l);   //发送一条“迫切左外连接”:查询联系人及其关联客户
      		//获取关联的客户信息
      		System.out.println(linkMan.getCustomer().getCust_name());   //不发送
      		
      		tx.commit();
      	}
      

批量抓取

批量抓取:就是同时查询多个对象的关联对象的时候。


可以通过配置 batch-size 属性来配置一次抓取的量。

“一端”批量抓取

在“一端”的 <set> 标签中配置 batch-size 即可。

对于代码:(查询客户,批量抓取联系人)

	@Test
	//查询客户,并获取关联的联系人
	public void demo(){
		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();
	}
  1. 未使用 batch-size:
    效果:先查询所有客户,再分别对每个客户查询联系人
    Hibernate:
    	select
    		...
    	from
    		cst customer customer0
    客户名称中国移动
    Hibernate:
    	select
    		...
    	from
    		cst_linkman linkmans0
    	where
    		linkmans0_.1km_cust_id=?
    客户对应的联系人的名称老张
    客户对应的联系人的名称小李
    客户名称中国联通
    Hibernate:
    	select
    		...
    	from
    		cst linkman linkmans0
    	where
    		linkmans0.1km cust id=?
    客户对应的联系人的名称老王
    
  2. 使用 batch-size:
    		<!--配置关联关系映射-->
    		<set name="LinkMans" batch-size="2">
    			<key column="..."/>
    			<one-to-many class="..."/>
    		</set>
    
    效果:先查询所有客户,再查询所有客户的联系人
    Hibernate:
    	select
    		...
    	from
    		cst_customer customer0_
    客户名称中国移动
    Hibernate:
    	select
    		...
    	from
    		cst linkman linkmans0
    	where
    		linkmans0.1km_cust_id in (
    			?? 
    		)
    客户对应的联系人的名称老张
    客户对应的联系人的名称小李
    客户名称中国联通
    客户对应的联系人的名称老王
    

“多端”批量抓取

在“一端”的 <class> 标签中配置 batch-size 即可。

对于代码:(查询联系人,批量抓取客户)

	@Test
	//查询联系人,并获取关联的客户
	public void demo(){
		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();
	}
  1. 未使用 batch-size:
    效果:先查询所有联系人,再分别对每个联系人查询客户
    Hibernate:
    	select
    		...
    	from
    		cst linkman linkmane
    联系人名称老张
    Hibernate:
    	select
    		...
    	from
    		cst_customer customer0_
    	where
    		customer0_.cust id=?
    联系人对应的客户名称中国移动
    联系人名称小李
    Hibernate:
    	select
    		...
    	from
    		cst customer customer0
    	where
    		customer0_.cust_id=?
    联系人对应的客户名称中国移动
    联系人名称老王
    Hibernate:
    	select
    		...
    	from
    		cst_customer customer0_
    	where
    		customer0_.cust id=?
    联系人对应的客户名称中国联通
    
  2. 使用 batch-size:
    	<class name="..." table="cst_customer" batch-size="2">
    	...
    
    效果:先查询所有联系人,再查询所有联系人的客户
    Hibernate:
    	select
    		...
    	from
    		cst_linkman linkman0_
    联系人名称老张
    Hibernate:
    	select
    		...
    	from
    		cst_customer customer0
    	where
    		customer0.custid in (
    			?? 
    		)
    联系人对应的客户名称中国移动
    联系人名称小李
    联系人对应的客户名称中国移动
    联系人名称老王
    联系人对应的客户名称中国联通