springboot之hibernate查询进阶

springboot之hibernate进阶

    • 简介
    • Hibernate的查询方式
      • HQL查询
      • Criteria
      • 原生SQL查询

简介

上一篇我们学习了hibernate基本的概念和与springboot整合简单使用,那么这篇我门将要讲解一些高级的查询知识

Hibernate的查询方式

HQL查询

和sql一样但是,但这是针对对象来操作,条件也是对象的属性

1、  第一种,用?占位符,如:
//登录(用?占位符)
 public List LoginUser(UserPO up)throws Exception{
  Session session = HibernateSessionFactory.getSession();
  String hql = "from UserPO where name = ? and pwd= ?";
  Query query = session.createQuery(hql);
  query.setString(0, up.getName());
  query.setString(1, up.getPwd());
  List list = query.list();
  session.close();
  return list;
 }

2、用“:+命名”占位符,如:
//登录(用":命名"占位符)
 public List LoginUser2(UserPO up)throws Exception{
  Session session = HibernateSessionFactory.getSession();
  String hql = "from UserPO where name = :n and pwd= :p";
  Query query = session.createQuery(hql);
  query.setString("n", up.getName());
  query.setString("p", up.getPwd());
  List list = query.list();
  session.close();
  return list;
 }
 
2.1、使用这种占位符还可以这样设值,如:
 
//登录(用":命名"占位符,用setParameter设值)
 public List LoginUser3(UserPO up)throws Exception{
  Session session = HibernateSessionFactory.getSession();
  String hql = "from UserPO where name = :n and pwd= :p";
  Query query = session.createQuery(hql);
  query.setParameter("n", up.getName());
  query.setParameter("p",up.getPwd());
  List list = query.list();
  session.close();
  return list;
 }
   使用这种方式不需要写明映射的类型,Hibernate会通过配置自动给我们转,但是由于Hibernate有两种日期格式:Date和TIMESTAMP,所以对于日期类型必须写明映射的类型。写法: 
 
3、按照对象进行参数绑定,如:
 
 //登录(用":命名"占位符,用setProperties设值,命名参数必须要与被绑定的属性名相同)
 public List LoginUser4(UserPO up)throws Exception{
  Session session = HibernateSessionFactory.getSession();
  String hql = "from UserPO where name = :name and pwd= :pwd";
  Query query = session.createQuery(hql);
  query.setProperties(up);
  List list = query.list();
  session.close();
  return list;
 }
/**
     * 排序查询:
     *      使用HQL语句,给查询结果排序
     *
     * HQL语句中的排序:
     *         order by
     *         asc:升序(默认值)
     *         desc:降序
     */
    @Test
    public void test4(){
        Session session = HibernateUtils.openSession();
        Transaction transaction = session.beginTransaction();
        // 按联系人ID降序排序联系人
        Query query = session.createQuery("from LinkMan order by lkmId desc");
        @SuppressWarnings("unchecked")
        List linkMans = query.list();
        transaction.commit();
        for (LinkMan linkMan : linkMans) {
            System.out.println(linkMan);
        }
    }
 
    /**
     * 分页查询
     * MySQL中分页关键字:
     *         Limit
     * limit的两个参数: 第一个参数:查询的开始记录索引。(它是从0开始的)
     *                    第二个参数:每次查询多少条记录。(它是固定的)
     * Hibernate中涉及的方法
     *         setFirstResult(int firstResult):查询的开始记录索引
     *         setMaxResults(int maxResults):每次查询多少条记录
     */
    @Test
    public void test5(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction transaction = session.beginTransaction();
        //1.获取Query对象
        Query query = session.createQuery("from LinkMan");
        //2.使用Hibernate提供的方法来设置分页条件
        Integer firstResult = 0;
        Integer maxResults = 2;
        query.setFirstResult(firstResult);
        query.setMaxResults(maxResults);
        //3.执行query对象的方法
        @SuppressWarnings("unchecked")
        List list = query.list();
        transaction.commit();
        for (LinkMan linkMan : list) {
            System.out.println(linkMan);
        }
    }
 
    /**
     * 统计查询
     *       其实就是在HQL语句中使用聚合函数
     *         count() sum() avg() max() min()
     *      使用聚合函数查询时,如果没有group by,返回的结果集是一行一列的
     *
     *  聚合函数都不会计算为null的字段。
     * 
     *  count(*)和count(主键)是一样的。
     */
    @Test
    public void test6(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction transaction = session.beginTransaction();
        // 查询一共有多少个联系人
        Query query = session.createQuery("select count(lkmId) from LinkMan");
        Long count = (Long) query.uniqueResult();
        transaction.commit();
        System.out.println(count);
    }
 
    /**
     * 投影查询:
     *      当我们查询实体对象时,并不需要所有字段信息,只查询部分,但是还想让他成为一个实体对象。其实就是用部分字段来投影出整个实体对象。
     * 使用要求:
     *     HQL语句:
     *         写法必须是  new 实体类名称(查询的字段)
     *         select new Customer(custId,custName) from Customer
     *         注意:如果你的实体类在工程中唯一,则可以直接写类名。如果实体类在工程中不唯一,需要写全限定类名。
     *  实体类要求:
     *      必须在实体类中提供一个相同参数列表的构造函数。
     *         
     */
    @Test
    public void test71(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction transaction = session.beginTransaction();
        // 只获取客户的ID和名字,并封装成客户对象
        Query query = session.createQuery("select new Customer(custId, custName) from Customer");
        @SuppressWarnings("unchecked")
        List customers = query.list();
        transaction.commit();
        for (Customer customer : customers) {
            System.out.println(customer.getCustId() + " " + customer.getCustName());
        }
    }
 
    @Test
    public void test72(){
        Session s = HibernateUtils.getCurrentSession();
        Transaction tx = s.beginTransaction();
        //1.获取Query对象
        Query query = s.createQuery("select custId,custName from Customer ");
        //2.执行query对象的方法
        @SuppressWarnings("unchecked")
        List list = query.list();
        tx.commit();
        for(Object[] os : list){
            System.out.println("----------每个数组中的内容------------");
            for(Object o : os){
                System.out.println(o);
            }
        }
    }
 
    /**
     * 左外连接查询和迫切左外连接查询的区别
     * 区别:
     *     返回的结果集不一样。在实际开发中用的不多,此处讲解就是为了说明他们之间的区别
     * 注意:
     *     Hibernate中没有右外连接
     *
     * Hibernate左外连接返回的数据:   
     *         返回的是一个有Object数组组成的List集合,该数组中有两个对象。一个是主表实体,一个是从表实体。
     *         主表实体有可能重复
     */
    //左外连接查询
    @Test
    public void test81(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction transaction = session.beginTransaction();
        //1.获取Query对象
        //sql语句的左外:select * from cst_customer c left outer join cst_linkman l on c.cust_id = l.lkm_cust_id;
        Query query = session.createQuery("from Customer c left join c.linkMans");
        //2.执行query对象的方法
        @SuppressWarnings("unchecked")
        List list = query.list();
        transaction.commit();
        for (Object[] objects : list) {
            System.out.println("------一组对象-------");
            for (Object object : objects) {
                System.out.println(object);
            }
        }
    }
 
    /**
     * 迫切左外连接查询:
     *         要想使用迫切,需要在查询HQL语句中加入一个关键字:fetch
     * Hibernate迫切左外连接返回的数据:
     *         返回的是左表实体对象的List集合,并且左表中对应右表的字段已经被填充
     */
    @Test
    public void test82(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction transaction = session.beginTransaction();
        //1.获取Query对象
        Query query = session.createQuery("from Customer c left join fetch c.linkMans");
        //2.执行query对象的方法
        @SuppressWarnings("unchecked")
        List customers = query.list();
        transaction.commit();
        for (Customer customer : customers) {
            System.out.println("------一组对象-------");
            System.out.println(customer);
            for (LinkMan linkMan : customer.getLinkMans()) {
                System.out.println(linkMan);
            }
            System.out.println("");
        }
    }
 
    /**
     * 使用HQL进行更新操作
     */
    @Test
    public void test9(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction transaction = session.beginTransaction();
        //1.获取Query对象
        Query query = session.createQuery("update Customer set custName = ? where custId = ?");
        query.setString(0, "XX公司");
        query.setString(1, "1");
        //2.执行query对象的方法
        int result = query.executeUpdate();
        transaction.commit();
        System.out.println(result);
    }
}

Criteria

QBC(Query By Criteria)是Hibernate提供的另一种检索对象的方式,它主要由Criteria 接口、Criterion接口和Expression类组成 。Criteria接口是Hibernate API中的一个查询接口,它需要由session进行创建。Criterion是Criteria的查询条件,在Criteria中提供了add(Criterion criterion)方法来添加查询条件。
涉及的对象:
Criteria
DetachedCriteria
获取的方式:
session.createCriteria(Class clazz);参数指的是要查询的字节码
添加条件的方法:
Criteria的add方法
添加条件涉及的对象:
Restrictions

springboot之hibernate查询进阶_第1张图片
springboot之hibernate查询进阶_第2张图片

离线条件检索
DetachedCriteria 翻译为离线条件查询,因为它是可以脱离Session来使用的一种条件查询对象,我们都知道Criteria对象必须由Session对象来创建。那么也就是说必须先有Session才可以生成Criteria对象。而DetachedCriteria对象可以在其他层对条件进行封装。
这个对象也是比较有用的,尤其在SSH整合以后这个对象经常会使用 。它的主要优点是做一些特别复杂的条件查询的时候,往往会在WEB层向业务层传递很多的参数,业务层又会将这些参数传递给DAO层。最后在DAO中拼接SQL完成查询。有了离线条件查询对象后,那么这些工作都可以不用关心了,我们可以在WEB层将数据封装好,传递到业务层,再由业务层传递给DAO完成查询。


/**
 * Hibernate中的查询方式:
 *         QBC查询:
 *             Query By Criteria  它是一种更加面向对象的查询方式。
 *             它把查询条件都用方法封装了。里面的参数全都需要使用实体类的属性名称。
 *         涉及的对象:
 *             Criteria
 *             DetachedCriteria
 *         获取的方式:
 *             session.createCriteria(Class clazz);参数指的是要查询的字节码
 *         添加条件的方法:
 *              Criteria的add方法。
 *         添加条件涉及的对象:
 *             Restrictions
 *
 * @author Switch
 */
public class TestQBCQuery {
    /**
     * 基本查询:查询所有
     *
     * 需求:
     *     查询所有客户
     */
    @Test
    public void test1(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        //1.获取Criteria对象
        Criteria criteria = session.createCriteria(Customer.class);
        //2.执行list方法,得到结果集
        @SuppressWarnings("unchecked")
        List customers = criteria.list();
        tx.commit();
        for (Customer customer : customers) {
            System.out.println(customer);
        }
    }
 
    /**
     * 条件查询
     *     需求:查询客户级别是23的,客户名称带有集字的
     */
    @Test
    public void test2(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        //1.获取Criteria对象
        Criteria criteria = session.createCriteria(Customer.class);
        // 添加条件
        criteria.add(Restrictions.eq("custLevel", "23"));
        criteria.add(Restrictions.like("custName", "%集%"));
        //2.执行list方法,得到结果集
        @SuppressWarnings("unchecked")
        List customers = criteria.list();
        tx.commit();
        for (Customer customer : customers) {
            System.out.println(customer);
        }
    }
 
    /**
     * 分页查询
     *
     * 涉及的方法:
     *         setFirstResult(int firstResult);
     *         setMaxResults(int maxResults);
     * 含义和HQL是一模一样的
     */
    @Test
    public void test3(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        //1.获取Criteria对象
        Criteria criteria = session.createCriteria(Customer.class);
        criteria.setFirstResult(0);
        criteria.setMaxResults(2);
        //2.执行list方法,得到结果集
        @SuppressWarnings("unchecked")
        List customers = criteria.list();
        tx.commit();
        for (Customer customer : customers) {
            System.out.println(customer);
        }
    }
 
    /**
     * 统计查询:
     *      使用QBC来添加聚合函数
     *
     * count() avg() min() max() sum()
     *
     * 涉及的方法:
     *         setProjections(Projection p ); 它可以加查询语句的结构。
     * 涉及的类:
     *         Projections
     *         该类中提供了一些静态方法
     */
    @Test
    public void test4(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        //1.获取Criteria对象
        Criteria criteria = session.createCriteria(Customer.class);
        criteria.setProjection(Projections.count("custId"));
 
        //2.执行uniqueResult方法,得到结果
        Long result = (Long) criteria.uniqueResult();
        tx.commit();
 
        System.out.println(result);
    }
 
    /**
     * 排序查询
     *
     * 涉及方法:
     *       Criteria的addOrder方法。该方法需要一个Order对象作为参数
     * Order对象有两个方法:
     *         desc(String propertyName):按照指定的属性名称,倒序排序。
     *         asc(String propertyName):按照自顶的属性名称,正序排序。
     */
    @Test
    public void test5(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        //1.获取Criteria对象
        Criteria criteria = session.createCriteria(LinkMan.class);
        criteria.addOrder(Order.desc("lkmId"));
 
        //2.执行list方法,得到结果集
        @SuppressWarnings("unchecked")
        List linkMans = criteria.list();
 
        tx.commit();
        for (LinkMan linkMan : linkMans) {
            System.out.println(linkMan);
        }
    }
 
 
    /**
     * 离线查询:
     *      在线对象:
     *         Criteria对象。它的获取必须要一个可用的Session来创建。如果Session不能用,则不能创建Criteria。
     *         我们使用Criteria进行的查询就是在线查询。
     *      离线对象:
     *         创建DetachedCriteria不需要一个可用的Session。
     *         用DetachedCriteria进行的查询就叫做离线查询
     * 涉及的对象
     *         DetachedCriteria
     * 如何获取
     *         DetachedCriteria.forClass(Class clazz);参数的含义:要查询的实体类
     * 如何设置查询条件:
     *         和Criteria是一样的
     *
     * 在实际开发中:多条件查询用此种方式
     */
 
    //Servlet的方法
    @Test
    public void doGet(){
        //1.获取请求参数
        String custLevel = "23";
        String custName = "集";
        //2.查询所有客户
        DetachedCriteria dCriteria = DetachedCriteria.forClass(Customer.class);
        dCriteria.add(Restrictions.eq("custLevel", custLevel));
        dCriteria.add(Restrictions.like("custName", "%"+custName+"%"));
 
        List cs = servicefindAllCustomer(dCriteria);
 
        for(Customer c : cs){
            //3.存入请求域中
            //4.转向列表页面
            System.out.println(c);
        }
    }
 
    //Service的方法
    public List servicefindAllCustomer(DetachedCriteria dCriteria){
        return daofindAllCustomer(dCriteria);
    }
 
    //Dao中的方法
    public List daofindAllCustomer(DetachedCriteria dCriteria){
        Session s = HibernateUtils.getCurrentSession();
        Transaction tx = s.beginTransaction();
        //1.把离线对象激活
        Criteria c = dCriteria.getExecutableCriteria(s);
        //3.执行list方法,得到结果集
        @SuppressWarnings("unchecked")
        List list = c.list();
        tx.commit();
        return list;
    }
}

原生SQL查询

采用HQL或QBC检索方式时,Hibernate生成标准的SQL查询语句,适用于所有的数据库平台,因此这两种检索方式都是跨平台的。但有的应用程序可能需要根据底层数据库的SQL方言,来生成一些特殊的查询语句。在这种情况下,可以利用Hibemate提供的原生SQL检索方式 。

session.beginTransaction();
String sql = "select id,username,userpwd from t_user";
List list = session.createSQLQuery(sql).list();
for(Object item : list){
Object[] rows = (Object[]) item;
System.out.println("id:" + rows[0] + "username:"
+ rows[1] + "userpwd:" + rows[2]);
}
session.getTransaction().commit();
addEntity()示例

session.beginTransaction();
String sql = "select id,username,userpwd from t_user";
// addEntity()可以告诉Hibernate你想要封装成对象的类型,然后自动为你封装
SQLQuery query = session.createSQLQuery(sql).addEntity(User.class);
List list = query.list();
for(User user : list){
System.out.println(user.getUserName());
}
session.getTransaction().commit();
uniqueResult示例

session.beginTransaction();
String sql = "select id,username,userpwd from t_user where id = 2";
SQLQuery query = session.createSQLQuery(sql).addEntity(User.class);
User user = (User) query.uniqueResult();
System.out.println(user.getUserName());
session.getTransaction().commit();

@Test
	public void testSQLQuery() {
		//查询所有的学生
		String sql="select * from t_student";//sql语句
		//.addEntity(Student.class) 要绑定实体,不然遍历不出来
		Query query=session.createSQLQuery(sql).addEntity(Student.class);
		List studentList=query.list();
		Iterator it=studentList.iterator();
		while(it.hasNext()){
			//强制转换为Student类型
			Student s=(Student)it.next();
			System.out.println(s);
		}		
	}
	
	@Test
	public void testSQLQuery2() {
		//模糊查询
		String sql="select * from t_student where student_name like :stuName and student_age=:stuAge";
		Query query=session.createSQLQuery(sql).addEntity(Student.class);
		query.setString("stuName", "张%");
		query.setInteger("stuAge", 13);
		List studentList=query.list();
		Iterator it=studentList.iterator();
		while(it.hasNext()){
			Student s=(Student)it.next();
			System.out.println(s);
		}		
	}
	



你可能感兴趣的:(springboot之hibernate查询进阶)