• Hibernate之HQL


    1. 什么是hql
    HQL是Hibernate Query Language的缩写

    2. hql和sql区别/异同

       HQL                                                                           SQL

       类名/属性                                                                   表名/列名

       区分大小写,关键字不区分大小写                               不区分大小写

       别名                                                                           别名

      ?,从下标0开始计算位置(hibernate5之后不支持)     ?,从顺序1开始计算位置

      :命名参数                                                                   不支持:命名参数

      面向对象的查询语言                                                   面向结构查询语言

    基本功能演示:

    package com.chenjiahao.five.test;
    
    import java.util.Arrays;
    import java.util.List;
    import java.util.Map;
    
    import org.hibernate.Session;
    import org.hibernate.Transaction;
    import org.hibernate.query.Query;
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    
    import com.chenjiahao.four.entity.Book;
    import com.chenjiahao.two.util.SessionFactoryUtils;
    
    public class HqlTest {
    	private Session session;
    	private Transaction transaction;
    	
    	@Before
    	public void before() {
    		session = SessionFactoryUtils.openSession();
    		transaction = session.beginTransaction();
    	}
    	
    	@After
    	public void after() {
    		transaction.commit();
    		session.close();
    	}
    	
    	/**
    	 * 返回对象(多个)用实体类
    	 */
    	@Test
    	public void testList1() {
    		Query query = session.createQuery("from Book");
    		List<Book> list = query.list();
    		for (Book b : list) {
    			System.out.println(b);
    		}
    	}
    	
    	/**
    	 * 返回单个列段,用字符串就可以接受
    	 */
    	@Test
    	public void testList2() {
    		Query query = session.createQuery("select b.bookName as ss from Book b");
    		List<String> list = query.list();
    		for (String b : list) {
    			System.out.println(b);
    		}
    	}
    	
    	/**
    	 * 查两个列段及以上,默认返回的是Object【】
    	 * b.bookId, b.bookName
    	 */
    	@Test
    	public void testList3() {
    		Query query = session.createQuery("select b.bookId,b.bookName as ss from Book b");
    		List<Object[]> list = query.list();
    		for (Object[] b : list) {
    			System.out.println(Arrays.toString(b));
    		}
    	}
    	
    	/**
    	 * 注意map是函数,所以不区分大小写,返回的是map集合
    	 *  new Map(b.bookId as bid, b.bookName as bname)
    	 */
    	@Test
    	public void testList4() {
    		Query query = session.createQuery("select new mAp(b.bookId,b.bookName) from Book b");
    		List<Map> list = query.list();
    		for (Map b : list) {
    			System.out.println(b);
    		}
    	}
    	
    	/**
    	 * 查两个列段及以上,也可返回对象,前提是有对应的构造函数
    	 *  new 构造方法(attr1,attr2)
         *  new Book(b.bookId, b.price)
    	 */
    	@Test
    	public void testList5() {
    		Query query = session.createQuery("select new Book(b.bookId,b.bookName) from Book b");
    		List<Book> list = query.list();
    		for (Book b : list) {
    			System.out.println(b);
    		}
    	}
    	
    	/**
    	 * HQL语句支持占位符
    	 *    ?占位符
    	 *    从下标0开始计算位置
         *    hibernate5之后不再支持?占位符(会出现sql攻击)
    	 *    sql攻击比如:
    	 *    select * from xxx where bid=?
    	 *    pst.setString(1,"1 and name="zs"")
    	 */
    	@Test
    	public void testList6() {
    //		Query query = session.createQuery("from Book where bookId = :bookId");
    //		query.setParameter("bookId", 1);
    //		Book b = (Book) query.getSingleResult();
    //		System.out.println(b);
    		//:bookIds==:命名参数 
    		//数组
    		Query query = session.createQuery("from Book where bookId in (:bookIds)");
    		query.setParameterList("bookIds", new Integer[] {1,2,4});
    		//集合
    //		List<Integer> params = new ArrayList<Integer>();
    //		params.add(1);
    //		params.add(2);
    //		params.add(4);
    //		query.setParameterList("bookIds", params);
    		List<Book> list = query.list();
    		for (Book b : list) {
    			System.out.println(b);
    		}
    	}
    	
    	/**
    	 * HQL支持连接查询
    	 */
    	@Test
    	public void testList7() {
    		//以前的写法是:select * from t_hibername_order o,t_hibernate_order_item oi where o.order_id=oi.oid
    		Query query = session.createQuery("select o.orderNo,oi.quantity from Order o,OrderItem oi where o = oi.order");
    		List<Object[]> list = query.list();
    		for (Object[] b : list) {
    			System.out.println(Arrays.toString(b));
    		}
    	}
    	
    	/**
    	 * HQL支持聚合函数
    	 */
    	@Test
    	public void testList8() {
    		//  还支持sum avg  max min
    		Query query = session.createQuery("select count(*) from Book");
    		//getSingleResult是用来获取单条记录的
    		Long singleResult = (Long) query.getSingleResult();
    		System.out.println(singleResult);
    	}
    	
    	/**
    	 * HQL分页
    	 * 
    	 * sql:
    	 * sql limit 起始位置,结束
    	 * 
    	 * hql:
    	 * 同样的可以自动根据数据库方言生成分页语句
    	 *        setFirstResult:设置起始下标
    	 *        setMaxResults:设置偏移量
    	 *  mysql:hql limit 起始位置,结束
    	 *  oracle : select * from (select t.*,rownum rn hql t where t.rn>5)t1 where t1.rn < 10
    	 *  
    	 */
    	@Test
    	public void testList9() {
    		Query query = session.createQuery("from Book");
    		//设置起始记录下标
    		query.setFirstResult(2);
    		// 设置返回的最大结果集     
    		query.setMaxResults(3);
    		List<Book> list = query.list();
    		for (Book b : list) {
    			System.out.println(b);
    		}
    	}
    }
    

      HQL通用分页查询:

     

     工具类:PageBean(分页的实体类)

    package com.chenjiahao.five.util;
    
    import java.util.Map;
    
    import javax.servlet.http.HttpServletRequest;
    
    /**
     * 分页工具类
     *
     */
    public class PageBean {
    
    	private int page = 1;// 页码
    
    	private int rows = 3;// 页大小
    
    	private int total = 0;// 总记录数
    
    	private boolean pagination = true;// 是否分页
    	// 获取前台向后台提交的所有参数
    	private Map<String, String[]> parameterMap;
    	// 获取上一次访问后台的url
    	private String url;
    
    	/**
    	 * 初始化pagebean
    	 * 
    	 * @param req
    	 */
    	public void setRequest(HttpServletRequest req) {
    		this.setPage(req.getParameter("page"));
    		this.setRows(req.getParameter("rows"));
    		// 只有jsp页面上填写pagination=false才是不分页
    		this.setPagination(!"fasle".equals(req.getParameter("pagination")));
    		this.setParameterMap(req.getParameterMap());
    		this.setUrl(req.getRequestURL().toString());
    	}
    
    	public int getMaxPage() {
    		return this.total % this.rows == 0 ? this.total / this.rows : this.total / this.rows + 1;
    	}
    
    	public int nextPage() {
    		return this.page < this.getMaxPage() ? this.page + 1 : this.getMaxPage();
    	}
    
    	public int previousPage() {
    		return this.page > 1 ? this.page - 1 : 1;
    	}
    
    	public PageBean() {
    		super();
    	}
    
    	public int getPage() {
    		return page;
    	}
    
    	public void setPage(int page) {
    		this.page = page;
    	}
    
    	public void setPage(String page) {
    		this.page = StringUtils.isBlank(page) ? this.page : Integer.valueOf(page);
    	}
    
    	public int getRows() {
    		return rows;
    	}
    
    	public void setRows(int rows) {
    		this.rows = rows;
    	}
    
    	public void setRows(String rows) {
    		this.rows = StringUtils.isBlank(rows) ? this.rows : Integer.valueOf(rows);
    	}
    
    	public int getTotal() {
    		return total;
    	}
    
    	public void setTotal(int total) {
    		this.total = total;
    	}
    
    	public void setTotal(String total) {
    		this.total = Integer.parseInt(total);
    	}
    
    	public boolean isPagination() {
    		return pagination;
    	}
    
    	public void setPagination(boolean pagination) {
    		this.pagination = pagination;
    	}
    
    	public Map<String, String[]> getParameterMap() {
    		return parameterMap;
    	}
    
    	public void setParameterMap(Map<String, String[]> parameterMap) {
    		this.parameterMap = parameterMap;
    	}
    
    	public String getUrl() {
    		return url;
    	}
    
    	public void setUrl(String url) {
    		this.url = url;
    	}
    
    	/**
    	 * 获得起始记录的下标
    	 * 
    	 * @return
    	 */
    	public int getStartIndex() {
    		return (this.page - 1) * this.rows;
    	}
    
    	@Override
    	public String toString() {
    		return "PageBean [page=" + page + ", rows=" + rows + ", total=" + total + ", pagination=" + pagination
    				+ ", parameterMap=" + parameterMap + ", url=" + url + "]";
    	}
    
    }
    

     工具类:StringUtils:

    package com.chenjiahao.five.util;
    
    public class StringUtils {
    	// 私有的构造方法,保护此类不能在外部实例化
    	private StringUtils() {
    	}
    
    	/**
    	 * 如果字符串等于null或去空格后等于"",则返回true,否则返回false
    	 * 
    	 * @param s
    	 * @return
    	 */
    	public static boolean isBlank(String s) {
    		boolean b = false;
    		if (null == s || s.trim().equals("")) {
    			b = true;
    		}
    		return b;
    	}
    	
    	/**
    	 * 如果字符串不等于null或去空格后不等于"",则返回true,否则返回false
    	 * 
    	 * @param s
    	 * @return
    	 */
    	public static boolean isNotBlank(String s) {
    		return !isBlank(s);
    	}
    
    }
    

      BaseDao:

    package com.chenjiahao.five.util;
    
    import java.util.Collection;
    import java.util.List;
    import java.util.Map;
    import java.util.Map.Entry;
    import java.util.Set;
    
    import org.hibernate.Session;
    import org.hibernate.query.Query;
    
    
    
    /**
     * 1.设置参数问题
     * 2.分页代码重复的问题
     * 
     * getCountSql(sql)
     * select count(1) from (sql) t
     * 
     * getCountHql(hql)
     * hql = " from Book where bookName like :bookName"
     * hql ="select * from new Book(bid,bookName) where bookName like :bookName"
     * 
     * @author dell
     *
     */
    public class BaseDao {
    	     
    	
             /**
              * 同用的参数设值方法
              * @param map    参数键值对集合
              * @param query  处理hql对象
              */
             public void setParam(Map<String, Object> map,Query query) {
            	 if(map !=null && map.size() > 0) {
            		 Object value = null;
            		 Set<Entry<String, Object>> entrySet = map.entrySet();
            		 for (Entry<String, Object> entry : entrySet) {
            			 //有的时候它并不是单纯的字符串,可能是数组比如爱好,也可能是集合
    					value=entry.getValue();
    					if (value instanceof Object[]) {
    						query.setParameterList(entry.getKey(), (Object[])value);
    					}else if(value instanceof Collection) {
    						query.setParameterList(entry.getKey(), (Collection)value);
    					}else {
    						query.setParameter(entry.getKey(), value);
    					}
    				}
            	 }
            	 
            	 
            	 
             }
             
             public String getCountHql(String hql) {
            	 // hql = " from Book where bookName like :bookName"
            		//	  hql ="select * from new Book(bid,bookName) where bookName like :bookName"
            	 //截取from后面的hql语句
            		int index = hql.toUpperCase().indexOf("FROM");	 
            		
            	 return " select count(*) " + hql.substring(index);
             }
    	     
             /**
              * 同用查询方法
              * @param session
              * @param map
              * @param hql
              * @param pageBean
              * @return
              */
             public List executeQuery(Session session,Map<String, Object> map,String hql,PageBean pageBean) {
            	 List list=null;
            	 if(pageBean != null && pageBean.isPagination()) {
            		 String countHql = getCountHql(hql);
            		 Query createQuery = session.createQuery(countHql);
            		 this.setParam(map, createQuery);
            		 pageBean.setTotal(createQuery.getSingleResult().toString());
            		 Query query = session.createQuery(hql);
            		 //给预定hql语句执行对象中的参数赋值,有多少赋值多少
            		 this.setParam(map, query);
            		 // 设置分页起始记录下标
            		 query.setFirstResult(pageBean.getStartIndex());
            		 //设置分页返回的最大结果集  
            		 query.setMaxResults(pageBean.getRows()); 
            		 list=query.list() ;
            		 
            	 }else {
            		 Query query = session.createQuery(hql);
            		 //给预定hql语句执行对象中的参数赋值,有多少赋值多少
            		 this.setParam(map, query);
            		 list=query.list();
            	 }
            	 
            	 
            	 return list;
             }
    	     
    	 
    	
    }
    

      BookDao:

        Bookdao继承Basedao

    package com.chenjiahao.four.dao;
    
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import org.hibernate.Hibernate;
    import org.hibernate.Session;
    import org.hibernate.Transaction;
    import org.hibernate.query.Query;
    
    import com.chenjiahao.five.util.BaseDao;
    import com.chenjiahao.five.util.PageBean;
    import com.chenjiahao.five.util.StringUtils;
    import com.chenjiahao.four.entity.Book;
    import com.chenjiahao.four.entity.Category;
    import com.chenjiahao.two.util.SessionFactoryUtils;
    
    
    
    public class BookDao extends BaseDao{
    public List<Book> list2(Book book , PageBean pageBean){
    		Session session = SessionFactoryUtils.openSession();
    		Transaction transaction = session.beginTransaction();
    		
    		
    	
    		String bookName = book.getBookName();
                    Map<String, Object> map=new HashMap<>();      
    		String hql="from Book where 1=1";
    		if (StringUtils.isNotBlank(bookName)) {
    			hql += " and bookName like :bookName";
    			map.put("bookName",bookName);
    		}
    		
    		List<Book> list=super.executeQuery(session, map, hql, pageBean);
    		transaction.commit();
    		session.close();
    		
    		return list;
    	}
    	
    }
    

      测试:

    @Test
    	public void testList2() {
    		Book book=new Book();
    		PageBean pageBean=new PageBean();
    		//查询页数
    		//pageBean.setPage(2);
    		//不分页
    		pageBean.setPagination(false);
    		//查询条件
    		//book.setBookName("%西%");
    		List<Book> list = this.bookDao.list2(book, pageBean);
    		for (Book b : list) {
    			System.out.println(b);			
    		}
    	}
    	
    

      

  • 相关阅读:
    ASP.NET -- repeater控件的使用
    在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误。未找到或无法访问服务器。请验证实例名称是否正确并且 SQL Server 已配置为允许远程连接。 (provider: 命名管道提供程序, error: 40
    错误提示:在此上下文中不允许使用名称 "***"。有效表达式包括常量、 常量表达式和变量(在某些上下文中),不允许使用列名。
    mongodb 性能提高之利用索引, 待续
    工程化 经历的 4 个阶段
    把连续的字符 变成 一个
    sort 排序详解
    理解正则 的 ?! ?:
    [ 订单查询 ] 性能 高并发 : 分表 与 用户id%1024 存放表
    搭建LNMP基础框架
  • 原文地址:https://www.cnblogs.com/chenjiahao9527/p/11209315.html
Copyright © 2020-2023  润新知