Hibernate框架入门学习(四)

个人博客原文链接

OID和对象导航方式

例:

public void run1(){
	Session session = HibernateUtils.getSession();
	Transaction tr = session.beginTransaction();
	//唯一OID方式查询客户
	Customer c = session.get(Customer.class, 1L);
	//对象导航方式
	System.out.println(c.getLinkMans().size());
	tr.commit();
	
}

HQL

HQL查询方式

  1. 介绍
    HQL(Hibernate Query Language) 是面向对000000象的查询语言, 它和SQL 查询语言有些相似,在Hibernate提供的各种检索方式中,HQL是使用最广的一种检索方式。

  2. HQL与SQL的关系

    • HQL查询语句是面向对象的,Hibernate负责解析HQL查询语句,然后根据对象-关系映射文件中的映射信息, 把HQL查询语句翻译成相应的SQL语句.
    • HQL查询语句中的主体是域模型中的类及类的属性
    • SQL查询语句是与关系数据库绑定在一起的
    • SQL查询语句中的主体是数据库表及表的字段
  3. HQL的简单查询

    1. 基本查询
      /**
       * 基本查询
       */
      @Test
      public void run1(){
      	Session session = HibernateUtils.getSession();
      	Transaction tr = session.beginTransaction();
      	//创建HQL查询的接口
      	Query query = session.createQuery("from Customer");
      	List list = query.list();
      	for (Customer customer : list) {
      		System.out.println(customer);
      	}		
      	tr.commit();	
      }
      
    2. 支持方法链的编程查询
      可以在createQuery方法后面跟多个方法传入参数如list()
      /**
       * 支持方法链的编程
       */
      @Test
      public void run2(){
      	Session session = HibernateUtils.getSession();
      	Transaction tr = session.beginTransaction();
      	//支持方法链,在后面接.list
      	List list = session.createQuery("from Customer").list();
      	for (Customer customer : list) {
      		System.out.println(customer);
      	}		
      	tr.commit();	
      }
      
    3. 支持别名方式查询
      /**
       * 支持别名方式
       * 同SQL
       */
      @Test
      public void run3(){
      	Session session = HibernateUtils.getSession();
      	Transaction tr = session.beginTransaction();
      	//select c可省略,千万不要加*
      	List list = session.createQuery("select c from Customer c where c.cust_id=1").list();
      	for (Customer customer : list) {
      		System.out.println(customer);
      	}		
      	tr.commit();	
      }
      
      
    4. 排序查询
      /**
       * 排序查询
       * order by 属性名  asc/desc
       */
      @Test
      public void run4(){
      	Session session = HibernateUtils.getSession();
      	Transaction tr = session.beginTransaction();
      

    /* //升序排列
    List list = session.createQuery(“from LinkMan l order by lkm_id asc”).list();*/
    //降序排列
    List list = session.createQuery(“from LinkMan l order by lkm_id desc”).list();
    for (LinkMan linkman : list) {
    System.out.println(linkman);
    }
    tr.commit();
    }
    ```

    1. 分页查询
      /**
       * 分页查询
       * 起始页:setFirstResult(a)	
       * 页大小:setMaxResults(b)
       */
      @Test
      public void run5(){
      	Session session = HibernateUtils.getSession();
      	Transaction tr = session.beginTransaction();
      	/*//第一页,设置起始页为0,每页记录3条数据
      	List list = session.createQuery("from LinkMan l order by lkm_id desc").setFirstResult(0).setMaxResults(3).list();*/
      	//第二页,设置起始页为3,每页记录3条数据
      	List list = session.createQuery("from LinkMan l order by lkm_id desc").setFirstResult(3).setMaxResults(3).list();		
      	for (LinkMan linkman : list) {
      		System.out.println(linkman);
      	}		
      	tr.commit();	
      }
      
    2. 带条件的查询
    /**
     * 条件查询查询
     */
    @Test
    public void run6(){
    	Session session = HibernateUtils.getSession();
    	Transaction tr = session.beginTransaction();
    
    	/*//按位置绑定参数?的条件查询(指定下标值,默认从0开始)
    	List list = session.createQuery("from LinkMan l where lkm_id > ?").setLong(0,3L).list();*/		
    
    	/*//按名称绑定参数的条件查询(HQL语句中的 ? 号换成 :名称 的方式)
    	List list = session.createQuery("from LinkMan l where lkm_id > :id").setLong("id", 2L).list();*/	
    
    	//不用考虑参数的具体类型setParameter("?号的位置,默认从0开始","参数的值")
    	List list = session.createQuery("from LinkMan l where lkm_id > ? and lkm_name = ?").setParameter(0, 2L).setParameter(1, "四号").list();
    	
    	for (LinkMan linkman : list) {
    		System.out.println(linkman);
    	}		
    	tr.commit();	
    }
    
  4. 投影查询
    投影查询就是想查询某一字段的值或者某几个字段的值

    1. 直接查询
      /**
       * 投影查询:只查询几个字段,不是所有字段
       * 相当于sql的"select id,name from LinkMan"
       * 直接查询
       */
      @Test
      public void run8(){
      	Session session = HibernateUtils.getSession();
      	Transaction tr = session.beginTransaction();
      
      	List list = session.createQuery("select lkm_name,lkm_id from LinkMan").list();		
      	for (Object[] objects : list) {
      		System.out.println(Arrays.toString(objects));
      	}
      	tr.commit();	
      }
      
    2. 封装到对象中查询
      /**
      *在LinkMan中添加以下构造函数
      */
      
      //投影查询,空的构造函数不能省略
      public LinkMan(){
      	
      }
      //投影查询,传入要查询字段对应的参数
      public LinkMan(long lkm_id, String lkm_name) {
      	super();
      	this.lkm_id = lkm_id;
      	this.lkm_name = lkm_name;
      }
      
      /** 
       * 投影查询:只查询几个字段 ,不是所有字段
       * 相当于sql的"select id, name from LinkMan"
       * 封装到对象中查询 
       * 第一步:需要在JavaBean 类提供对应的构造方法
       * 第二步:修改HQL语句 
       */ 
      @Test 
      public void run7(){
      	Session session = HibernateUtils.getSession();
      	Transaction tr = session.beginTransaction();
      
      	List list = session.createQuery("select new LinkMan(lkm_id,lkm_name) from LinkMan").list();
      	
      	for (LinkMan linkman : list) {
      		System.out.println(linkman);
      	}		
      	tr.commit();	
      }
      
  5. 聚合函数查询

    /**
     * 聚合函数
     * sum() count() avg() max() min()
     * 查询联系人的数量
     */
    @Test
    public void run9(){
    	Session session = HibernateUtils.getSession();
    	Transaction tr = session.beginTransaction();
    	//count(别名) = count(*) 
    	List list = session.createQuery("select count(l) from LinkMan l").list();		
    	//通过下标取值,longValue()改变类型
    	System.out.println(list.get(0).longValue());
    	tr.commit();	
    }
    
    /**
     * 聚合函数
     * sum() count() avg() max() min()
     * 查询联系人id的和
     */
    @Test
    public void run10(){
    	Session session = HibernateUtils.getSession();
    	Transaction tr = session.beginTransaction();
    	//count(别名) = count(*) 
    	List list = session.createQuery("select sum(lkm_id) from LinkMan l").list();		
    	//通过下标取值,longValue()改变类型
    	System.out.println(list.get(0).longValue());
    	tr.commit();	
    }
    
    

HQL多表查询

内连接

简介:查询两表之间的交集(有关联)部分,默认返回object[]数组
代码实例:

/**
 * 内连接:查询两表之间的交集(有关联)部分
 * 客户对象 inner join 客户对象的联系人集合
 * 默认返回object[]数组
 * 查询客户,客户和联系人有关联
 */
@Test
public void run1(){
	Session session = HibernateUtils.getSession();
	Transaction tr = session.beginTransaction();
	//创建HQL的查询接口
	Query query = session.createQuery("from Customer c inner join c.LinkMans");
	List list = query.list();
	for (Object[] objects : list) {
		System.out.println(Arrays.toString(objects));
	}
	tr.commit();
}

迫切内连接

简介:查询两表之间的交集(有关联)部分,返回对应的实体对象
代码实例:

/**
 * 迫切内连接:查询两表之间的交集(有关联)部分
 * 客户对象 inner join fetch客户对象的联系人集合
 * 返回对应的实体对象
 * 把对象封装在Set集合,去掉重复数据
 * 查询客户,客户和联系人有关联
 */
@Test
public void run2(){
	Session session = HibernateUtils.getSession();
	Transaction tr = session.beginTransaction();
	//创建HQL的查询接口
	Query query = session.createQuery("from Customer c inner join fetch c.LinkMans");
	List list = query.list();
	//手动去掉重复数据
	Set set = new HashSet(list);
	for (Customer customer : set) {
		System.out.println(customer);
	}
	tr.commit();
}

左(右)外连接

简介:查询左(右)表和两表之间交集(关联)部分,默认返回object[]数组
代码实例:

/**
 * 左外连接:查询左表和两表之间交集(关联)部分
 * 客户对象 left join 客户对象的联系人集合
 * 默认返回object[]数组
 * 查询客户,客户和联系人有关联
 */
@Test
public void run3(){
	Session session = HibernateUtils.getSession();
	Transaction tr = session.beginTransaction();
	//创建HQL的查询接口
	Query query = session.createQuery("from Customer c left join c.LinkMans");
	List list = query.list();
	for (Object[] objects : list) {
		System.out.println(Arrays.toString(objects));
	}
	tr.commit();
}

迫切左(右)外连接

简介:查询左(右)表和两表之间交集(关联)部分,返回实体对象
代码实例:

/**
 * 迫切左外连接:查询左表和两表之间交集(关联)部分
 * 客户对象 left join fetch客户对象的联系人集合
 * 返回对应的实体对象
 * 把对象封装在Set集合,去掉重复数据
 * 查询客户,客户和联系人有关联
 */
@Test
public void run4(){
	Session session = HibernateUtils.getSession();
	Transaction tr = session.beginTransaction();
	//创建HQL的查询接口
	Query query = session.createQuery("from Customer c left join fetch c.LinkMans");
	List list = query.list();
	//手动去掉重复数据
	Set set = new HashSet(list);
	for (Customer customer : set) {
		System.out.println(customer);
	}
	tr.commit();
}

QBC

QBC查询方式

  1. 简介
    QBC查询即Query By Criteria,按条件查询
  2. 简单查询
    /**
     * 基本查询
     */
    @Test
    public void run1(){
    	Session session = HibernateUtils.getSession();
    	Transaction tr = session.beginTransaction();
    	//创建QBC查询接口
    	Criteria criteria = session.createCriteria(LinkMan.class);
    	//查询所有值
    	List list = criteria.list();
    	for (LinkMan linkMan : list) {
    		System.out.println(linkMan);
    	}
    	
    	tr.commit();
    }
    
  3. 排序查询
    /**
     * 排序查询
     * 使用addOrder()设置参数
     */
    @Test
    public void run2(){
    	Session session = HibernateUtils.getSession();
    	Transaction tr = session.beginTransaction();
    	//创建QBC查询接口
    	Criteria criteria = session.createCriteria(LinkMan.class);
    	//添加排序desc or 
    	criteria.addOrder(Order.desc("lkm_id"));
    	criteria.addOrder(Order.asc("lkm_id"));
    	//查询所有值
    	List list = criteria.list();
    	for (LinkMan linkMan : list) {
    		System.out.println(linkMan);
    	}
    	tr.commit();
    }
    
  4. 分页查询
    /**
     * 分页查询
     * setFirstResult()和setMaxResult()
     * 起始页和页的大小
     */
    @Test
    public void run3(){
    	Session session = HibernateUtils.getSession();
    	Transaction tr = session.beginTransaction();
    	//创建QBC查询接口
    	Criteria criteria = session.createCriteria(LinkMan.class);
    	//设置每一页三条数据
    	criteria.setFirstResult(0);
    	criteria.setMaxResults(3);
    	//查询所有值
    	List list = criteria.list();
    	for (LinkMan linkMan : list) {
    		System.out.println(linkMan);
    	}
    	tr.commit();
    }
    
  5. 条件查询
    • 简介:Criterion是查询条件的接口,Restrictions类是Hibernate框架提供的工具类,使用该工具类来设置查询条件
    • 条件查询使用Criterion接口的add方法,用来传入条件
    • 使用Restrictions的添加条件的方法来添加条件
    • 常见的条件
      • Restrictions.eq – 相等
      • Restrictions.gt – 大于号
      • Restrictions.ge – 大于等于
      • Restrictions.lt – 小于
      • Restrictions.le – 小于等于
      • Restrictions.between – 在之间
      • Restrictions.like – 模糊查询
      • Restrictions.in – 范围
      • Restrictions.and – 并且
      • Restrictions.or – 或者
      • Restrictions.isNull – 是否等于null
    • 代码实例
      /**
       * 条件查询
       * 使用Criterion接口的add方法,用来传入条件
       * 多个条件就用多个add添加条件
       * 使用Restrictions的添加条件的方法来添加条件
       */
      @Test
      public void run4(){
      	Session session = HibernateUtils.getSession();
      	Transaction tr = session.beginTransaction();
      	//创建QBC查询接口
      	Criteria criteria = session.createCriteria(LinkMan.class);
      	//查询lkm_id=1L的值或lkm_id>4L的值
      	criteria.add(Restrictions.or(Restrictions.gt("lkm_id", 4L), Restrictions.eq("lkm_id", 1L)));
      	//查询3-5之间的值
      	criteria.add(Restrictions.between("lkm_id", 3L, 5L));
      	//查询所有值
      	List list = criteria.list();
      	for (LinkMan linkMan : list) {
      		System.out.println(linkMan);
      	}
      	tr.commit();
      }
      
  6. 聚合函数查询
    • 简介:Projection的聚合函数的接口,而Projections是Hibernate提供的工具类,使用该工具类设置聚合函数查询。
    • 使用QBC的聚合函数查询,需要使用criteria.setProjection()方法。
    • 代码实例
      /**
       * 聚合函数查询
       * 注:在查询完聚合函数后,要继续查询其他字段的话要设置回默认
       */
      @Test
      public void run5(){
      	Session session = HibernateUtils.getSession();
      	Transaction tr = session.beginTransaction();
      	//创建QBC查询接口
      	Criteria criteria = session.createCriteria(LinkMan.class);	
      	//设置聚合函数的方式
      	List list = criteria.setProjection(Projections.count("lkm_id")).list();
      	Long count = list.get(0).longValue();
      	System.out.println(count);
      	//继续查询其他字段的话要设置回默认
      	criteria.setProjection(null);
      	List list2 = criteria.list();
      	for (LinkMan linkMan : list2) {
      		System.out.println(linkMan);
      	}
      	tr.commit();
      }
      
  7. 离线条件查询
    • 简介:离线条件查询使用的是DetachedCriteria接口进行查询,离线条件查询对象在创建的时候,不需要使用Session对象,只是在查询的时候使用Session对象即可
    • 代码实例
    /**
     * 离线条件查询
     * 注:脱离session,可以不使用session来创建离线查询对象,只在查询的时候需要Session对象
     */
    @Test
    public void run6(){
    	Session session = HibernateUtils.getSession();
    	Transaction tr = session.beginTransaction();
    	//创建离线查询接口
    	DetachedCriteria criteria = DetachedCriteria.forClass(LinkMan.class);
    	//添加条件
    	criteria.add(Restrictions.gt("lkm_id", 3L));
    	//查询数据
    	List list = criteria.getExecutableCriteria(session).list();
    	for (LinkMan linkMan : list) {
    		System.out.println(linkMan);
    	}
    	tr.commit();
    }
    

SQL

  1. 简介
    直接使用SQL语句进行查询
  2. 代码实例
    /**
     * SQL基本查询
     * 把数据封装到对象
     */
    @Test
    public void run(){
    	Session session = HibernateUtils.getSession();
    	Transaction tr = session.beginTransaction();
    	String sql = "select * from cst_linkman where lkm_id = ?";
    	//创建SQL的查询接口
    	SQLQuery query = session.createSQLQuery(sql);
    	query.setParameter(0, 1L);
    	//设置数据封装对象
    	query.addEntity(LinkMan.class);
    	List list = query.list();
    	for (LinkMan linkMan : list) {
    		System.out.println(linkMan);
    	}
    	tr.commit();
    }
    

延迟加载

延迟加载先获取到代理对象,当真正使用到该对象中的属性的时候,才会发送SQL语句,是Hibernate框架提升性能的方式。

  1. 类级别的延迟加载
    • Session对象的load方法默认就是延迟加载
    • 只有在使用该对象属性时才发送SQL语句
      • 代码实例
        /**
         * 类级别的延迟加载
         * 只有在使用该对象属性时才发送SQL语句
         */
        @Test
        public void run() {
        	Session session = HibernateUtils.getSession();
        	Transaction tr = session.beginTransaction();
        	//开启类级别的延迟加载
        	Customer c = session.load(Customer.class,1L);
        	System.out.println("-----------");
        	System.out.println(c.getCust_name());
        	tr.commit();
        }
        
    • 使类级别的延迟加载失效
      • 在该类的配置文件的标签添加lazy=“false”
      • 添加语句Hibernate.initialize(Object proxy);
      • 代码实例
        /**
         * 使类级别的延迟加载失效的两种方式
         * 		1.在该类的配置文件的标签添加lazy="false"
         * 		2.添加语句Hibernate.initialize(Object proxy);
         */
        @Test
        public void run2() {
        	Session session = HibernateUtils.getSession();
        	Transaction tr = session.beginTransaction();
        	//开启类级别的延迟加载
        	Customer c = session.load(Customer.class,1L);
        	//直接初始化c对象,使其延迟加载失效
        	Hibernate.initialize(c);	//在这会有SQL语句
        	System.out.println("-----------");
        	System.out.println(c.getCust_name());
        	tr.commit();
        }
        
  2. 关联级别的延迟加载
    • 默认为延迟加载
    • 查询客户时,不会把联系人信息查询出来,而是在用到客户中的联系人时才会发送SQL语句
    • 代码实例
      /**
       * 关联级别的延迟加载
       * 默认就是延迟加载
       * 客户中的联系人信息只有在用到的时候才会发送SQL语句
       */
      @Test
      public void run3() {
      	Session session = HibernateUtils.getSession();
      	Transaction tr = session.beginTransaction();
      	Customer c = session.get(Customer.class, 1L);
      	Set mans = c.getLinkMans();
      	for (LinkMan linkMan : mans) {
      		System.out.println(linkMan);
      	}
      	tr.commit();
      }
      

配置查询策略

  • 使用Hibernate查询一个对象的时候,查询其关联对象应该如何查询是Hibernate的一种优化手段!
  • lazy属性解决查询的时机的问题,需要配置是否采用延迟加载
  • fetch属性就解决查询语句的形式问题

在set标签上配置策略

  • fetch的取值:控制SQL语句生成的格式
    • select:默认值,发送基本select语句查询
    • join:连接查询,发送的是一条迫切左外连接,配置了join会使lazy属性失效!
    • subselect:子查询,发送一条子查询查询其关联对象。(需要使用list()方法进行测试)
  • lazy的取值 :查找关联对象的时候是否采用延迟!
    • true:默认值,延迟加载
    • false:不延迟加载
    • extra :及其懒惰,sql语句会精简化
  • fetch的默认值为:select,lazy的默认值为true
  • 在开发中基本上使用默认值,特殊情况除外

在标签上配置策略

  • fetch的取值:控制SQL语句生成的格式
    • select:默认值,发送基本select语句查询
    • join:连接查询,发送迫切左外连接查询,配置了join会使lazy属性失效!
  • lazy的取值:控制加载关联对象是否采用延迟。
    • false:不采用延迟加载。
    • proxy:默认值,代理。由另一端的上的lazy值来确定是否延迟加载,如果那端的class上的lazy="true"则proxy相当于true(延迟加载),如果那端class上的lazy=“false”,则proxy相当于false(不延迟加载)

你可能感兴趣的:(Java,Web)