欢迎浏览 Java 工程师 SSH 教程从零打造在线网盘系统系列教程, 本系列教程将会使用 SSH(Struts2+Spring+Hibernate) 打造一个在线网盘系统, 本系列教程是从零开始, 所以会详细以及着重地阐述 SSH 三个框架的基础知识, 第四部分将会进入项目实战, 如果您已经对 SSH 框架有所掌握, 那么可以直接浏览第四章, 源码均提供在 GitHub/SSH-network-hard-disk 上供大家参阅
本章学习目标
掌握标准查询 API 的使用
掌握 QBE
掌握 HQL
掌握 SQL
本篇前言
在前面两篇文章中我们基本会使用 Hibernate 操作数据库, 但是基本都是使用的是 Session 接口进行操作, 像这种根据索引进行检索数据库局限性非常大. 为此 Hibernate 提供了很强大的查询技术, 例如标准查询 API,QBE,HQL,SQL 等
标准查询 API
要想使用标准查询 API 就要用到 Hibernate 的 org.hibernate.Criteria 接口, 通过 Session.createCriteria 既可以创建 Criteria 对象
- public static void main(String[] args) {
- Session session = HibernateSessionFactory.getSession();
- Criteria criteria = session.createCriteria(Product.class);
- criteria.setMaxResults(2);
- List list = criteria.list();
- for (Object var : list) {
- System.out.print(var.toString());
- }
- session.close();
- }
在使用标准 API 进行查询的时候增加约束条件是一个 SimpleExpression 对象, 由 org.hibernate.criterion.Restrictions 类的静态方法可以获得相应的 SimpleExpression 对象.
criteria.add(Restrictions.eq("name", "中药"));
我们同样可以进行模糊匹配
criteria.add(Restrictions.like("name", "% 中 %"));
使用 MatchMode 类静态常量, 模糊匹配我们也可以这样也是一样的
criteria.add(Restrictions.like("name", "中", MatchMode.ANYWHERE));
在增加查询的约束条件的时候我们会这样使用, 查询成绩大于 90 的学生并且是女生, 或者怎么怎么样...., 我们可以使用 LogicalExpression 改变他们的逻辑
- public static void main(String[] args) {
- Session session = HibernateSessionFactory.getSession();
- Criteria criteria = session.createCriteria(Product.class);
- SimpleExpression id1 = Restrictions.eq("id", 1);
- SimpleExpression id11 = Restrictions.eq("id", 11);
- LogicalExpression logicalExpression = Restrictions.or(id1, id11);
- criteria.add(logicalExpression);
- List list = criteria.list();
- for (Object var : list) {
- System.out.print(var.toString());
- }
- session.close();
- }
可以看到使用 LogicalExpression 逻辑变得非常臃肿, Hibernate 提供了更便捷的解决方案, 那就是使用 Conjunction 生成 And 关系, 使用 Disjunction 生成 or 关系
- Disjunction disjunction = Restrictions.disjunction();
- disjunction.add(id1);
- disjunction.add(id11);
- criteria.add(disjunction);
- Conjunction conjunction = Restrictions.conjunction();
- conjunction.add(id1);
- conjunction.add(id11);
- criteria.add(conjunction);
那么如何使用标准查询 API 进行分页查询呢? 得益于 Hibernate 对不同数据库的封装, 我们可以很便捷地进行分页, 例如 xxxxx limit0, 10 这样的 SQL 我们平时经常见到, 我们可以使用 Criteria 接口两条语句即可实现分页功能
- criteria.setFirstResult(0);
- criteria.setMaxResults(10);
您阅读到这里的时候可以发现 Criteria 接口返回的都是 List 对象, 如果我们知道一条索引 id, 我们根绝这个 id 去进行去进行查找, 就没必要返回给我一个 List 集合了吧? 同样我们可以使用 uniqueResult 方法返回一个 Object 对象
- Session session = HibernateSessionFactory.getSession();
- Criteria criteria = session.createCriteria(Product.class);
- criteria.add(Restrictions.eq("id",1));
- Product product = (Product) criteria.uniqueResult();
在处理多个实体 Bean 关联的情况下我们需要处理多个 Criteria 之间的关联, 我们可以通过 Criteria 创建另一个 Criteria 对象, 参数是一个属性名
- Session session = HibernateSessionFactory.getSession();
- Criteria productCriteria = session.createCriteria(Product.class);
- Criteria productDetailCriteria = productCriteria.createCriteria("productDetail");
- productDetailCriteria.add(Restrictions.eq("detatil", "肯定匹配不到我"));
- List list = productCriteria.list();
我们可以使用 AggregateProjection 类进行聚合操作查询, 例如查询一个表中的记录数
- public static void main(String[] args) {
- Session session = HibernateSessionFactory.getSession();
- Criteria criteria = session.createCriteria(Product.class);
- criteria.setProjection(Projections.rowCount());
- Long count = (Long) criteria.uniqueResult();
- }
- QBE(Query By Example)
除了使用标准查询 API, 我们还可以使用 QBE 进行查询
- public static void main(String[] args) {
- Session session = HibernateSessionFactory.getSession();
- Criteria criteria = session.createCriteria(Product.class);
- Product product = new Product();
- product.setName("中药");
- criteria.add(Example.create(product));
- List list = criteria.list();
- }
- HQL(Hibernate Query Language)
HQL 是 Hibernate 框架提供的另一种操作数据的方式, 其语法非常接近 SQL, 但却是面向对象的也就是说 HQL 所操作的都是持久化对象, 而不是数据表
- public static void main(String[] args) {
- Session session = HibernateSessionFactory.getSession();
- Query from_product = session.createQuery("from Product");
- List list = from_product.list();
- }
我们在进行复杂的查询 HQL 都是游刃有余的
- public static void main(String[] args) {
- Session session = HibernateSessionFactory.getSession();
- Query from_product = session.createQuery("select name from Product where id>0 or id<10");
- List list = from_product.list();
- }
HQL 和 JDBC 一样是支持占位符查询的
- public static void main(String[] args) {
- Session session = HibernateSessionFactory.getSession();
- Query from_product = session.createQuery("select name from Product where id> :id");
- from_product.setInteger("id", 0);
- List list = from_product.list();
- }
HQL 进行分页查询跟标准查询 API 很是相似
- public static void main(String[] args) {
- Session session = HibernateSessionFactory.getSession();
- Query from_product = session.createQuery("from Product");
- from_product.setFirstResult(0);
- from_product.setMaxResults(10);
- List list = from_product.list();
- }
HQL 同样支持聚合查询
- public static void main(String[] args) {
- Session session = HibernateSessionFactory.getSession();
- Query from_product = session.createQuery("select count(*) from Product");
- Long count = (Long) from_product.uniqueResult();
- }
HQL 作为一种查询语言同样支持 Update/Delete/Insert
- Query from_product = session.createQuery("xxxxxxx");
- from_product.executeUpdate();
- SQL
虽然 HQL 可以完成大多数的操作, 但是 HQL 并不支持数据库的所有特性, 因此在需要的时候我们还是需要直接使用 SQL 操作数据库
- public static void main(String[] args) {
- Session session = HibernateSessionFactory.getSession();
- NativeQuery sqlQuery = session.createSQLQuery("select * from products p");
- sqlQuery.addEntity("p", Product.class);
- List<Product> list = sqlQuery.list();
- }
本篇总结
掌握 Hibernate 的查询与更新技术, 能在 Hibernate 框架的任意场景中熟练运用各种查询与更新技术
来源: https://www.cnblogs.com/jimisun/p/9939831.html