hibernate的hql语句以及sql原生语句实现CRUD实例
Hql是什么,它跟Sql的区别是什么?
hql是Hibernate Query Language的缩写,是hibernate独有的查询语言特性。
sql是Structured Query Language的缩写,为独立于各种数据库之间的结构化查询语言,除了 SQL 标准之外,大部分 SQL 数据库程序都拥有它们自己的私有扩展。
HQL | SQL | |
结构 | 面向类名/属性 | 面向数据表/列 |
大/小写 | 对象部分区分大小写,关键字部分不区分 | 不区分大小写 |
别名 | 支持 | 支持 |
?占位符 | 参数赋值时下标从0开始(已过时) | 参数赋值时下标从1开始 |
命名参数:变量 | 支持命名参数方式实现参数绑定 | 不支持 |
抽象层次 | 面向对象 | 面向结构 |
查询部分
1.利用hql实现查询
1)查询结果集List<T>
String hql = "from Book";//如果时直接查询整个实体,hql可以直接省略select,用实体类名代替表名。 Query<Book> query = session.createQuery(hql, Book.class);//获取查询对象。 List<Book> list = query.list();//执行查询对象并且返回结果集。
2)查询单个结果T
String hql = "from Book as b where b.bookId=1";//hql支持sql关键字带条件查询。 Query<Book> query = session.createQuery(hql, Book.class); List<Book> list = query.list();
3)查询实体的多个属性返回的时List<Object[]>
String hql = "select bookId,bookName from Book";//hql查询列名统一用类的属性名来代替。 Query query = session.createQuery(hql); List list = query.list(); list.forEach(bk->{ System.out.println(Arrays.toString((Object[]) bk));//集合中每个元素都是Object[]数组,所以需要转换为数组,只返回所有的值(不返回列)。 });
4)利用new map()指定hql,必须要给列取上别名
String hql = "select new map(b.bookId as bid,b.bookName as bname) from Book as b";//取别名须要带上as。 Query query = session.createQuery(hql); List list = query.list(); list.forEach(bk->{ System.out.println(bk);//返回的集合中每个元素都是一个map对象。 });
5)new 构造函数(属性名)方式
String hql = "select new Book(bookId,bookName,price) from Book";//构造函数里面的属性必须与实体类中定义的属性顺序一致。 Query query = session.createQuery(hql); List list = query.list(); list.forEach(bk->{ System.out.println(bk); });
6)命名参数方式,注意:1.冒号不要使用中文。2.问号占位符的方式可以使用(不推荐),下标从0开始。3.使用命名参数传值,必须在执行之前赋值。
String hql = "select bookId,bookName,price from Book where bookId=:bid";
Query query = session.createQuery(hql);
//在执行hql之前完成参数赋值 //过时的方法:利用占位符?的方式,下标从0开始 //query.setInteger(0, 1);
//如果是多参数情况,比如from tbale where id in(?,?,?);
//String hql = "select bookId,bookName,price from Book where bookId in(:ids);
//执行之前设置参数集合,完成赋值,然后执行
//query.setParameterList("ids",Arrays.asList(new Integer[]{1,2,3}));
//推荐使用setParameter方法指定参数值
query.setParameter("bid", 1);
List list = query.list();
list.forEach(bk->{
System.out.println(Arrays.toString((Object[]) bk));
});
7)链接查询(可以使用List<Object[]>或new map()返回数据)
String hql = "select b.bookId,b.bookName,b.price,c.categoryName from Book b inner join b.categories c "; Query query = session.createQuery(hql); List list = query.list(); list.forEach(obj->{ System.out.println(Arrays.toString((Object[]) obj)); });
8)hql支持聚合函数
String hql = "select new map(sum(b.price) as sum,max(b.price) as max,min(b.price) as min,avg(b.price) as avg,count(b.price) as count) from Book b"; Query query = session.createQuery(hql); List list = query.list(); list.forEach(obj->{ System.out.println(obj); });
9)分页查询
//定义页码和行数 int page = 2; int rows = 4; String hql = "from Book"; Query<Book> query = session.createQuery(hql,Book.class); //在执行之前给参数赋值 query.setFirstResult((page-1)*rows);//设置记录开始位置 query.setMaxResults(rows);//设置展示行数 List<Book> list = query.list();//执行查询 list.forEach(System.out::println);
2.利用原生sql实现查询
1)查询返回List<T>
String sql = "select * from t_book_hb"; NativeQuery<Book> query = session.createNativeQuery(sql, Book.class);//创建sql的执行对象 List<Book> list = query.list(); list.forEach(System.out::println);
2)查询返回单个实体T
String sql = "select * from t_book_hb where book_id =:bid";//使用命名参数方式 NativeQuery<Book> query = session.createNativeQuery(sql, Book.class); //设置参数 query.setParameter("bid",1); List<Book> list = query.list(); list.forEach(System.out::println);
3)查询返回List<map>用于多表联查
String sql = "select bk.*,ch.category_name from t_book_hb bk,t_book_category_hb bc,t_category_hb ch " + "where bk.book_id=bc.bid and bc.cid=ch.category_id";//三表链接查询 NativeQuery query = session.createNativeQuery(sql); query.setResultTransformer(CriteriaSpecification.ALIAS_TO_ENTITY_MAP);//设置返回方式为map对象 List list = query.list(); list.forEach(obj->{ System.out.println(obj); });
4)视图(查询较多的联查语句创建视图方便查询)
String sql = "select * from v_book_category";//数据库创建视图v_book_category NativeQuery query = session.createNativeQuery(sql); query.setResultTransformer(CriteriaSpecification.ALIAS_TO_ENTITY_MAP);//设置返回map对象 List list = query.list();//执行 list.forEach(obj->{ System.out.println(obj); });
增删改部分
1)hibernate方式
public void updateBook(Book bk) {//打开session对象,SessionFactoryUtils封装了打开hibernate会话的方法 Session session = SessionFactoryUtils.openSession(); //打开事务 Transaction transaction = session.beginTransaction(); //执行增加操作(save),删除(delete),更新(update/merge) session.save(bk);//session.delete();/session.update();||session.merge(); //提交事务 transaction.commit(); //关闭会话 SessionFactoryUtils.closeSession(); }
2)原生sql方式
@SuppressWarnings({ "deprecation", "rawtypes" }) public void updateSql(Category ct) { String sql = "insert into t_category_hb(category_name)values(:cname)";//定义原生sql语句,update或是delete,使用命名参数方式赋值 //获取session对象 Session session = SessionFactoryUtils.openSession(); //开启并获取事务 Transaction tran = session.beginTransaction(); //创建原生sql对象 NativeQuery query = session.createSQLQuery(sql); //赋值 query.setParameter("cname", ct.getCategoryName()); query.executeUpdate();//执行sql,注意删除语句,一般需要自己手动解除关联关系。 //提交并关闭 tran.commit(); SessionFactoryUtils.closeSession(); }
总结
hql和sql各有优劣,hql对查询条件进行了面向对象封装,符合编程人员的思维方式,更加灵活便捷,但是对于多表联查来说配置繁琐。
而sql语句可以有更大的优化,多表联查的情况下更具优势,所以要结合实际中的使用场景使用不同的方式。