Hibernate配置文件HQL、QBC查询详解(四)

HQL简介

HQL(Hibernate Query Language)描写对象操作的一种查询语言,Hibernate特有HQL的语法和SQL语法基本一致,不同的是HQL是面向对象的查询,查询的是对象和对象中的属性,HQL的关键字不区分大小写,但类名和属性区分大小写

语法示例
  • SELECT 别名/属性名/表达式
  • FROM 实体AS别名
  • WHERE 过滤条件
  • HAVING 分组后的结果的查询条件
  • ORDER BY 排序条件

查询案例

投影查询

不能把结果封装成对象,如果强制转换会报java.lang.ClassCastException异常错误

 List list = (List) session.createQuery("select s.id,s.username from Student s").list();
        for (int i = 0; i < list.size(); i++) {
            Object[] objs = list.get(i);
            for (int j = 0; j < objs.length; j++) {
                System.out.println("------------------");
                Object obj = objs[j];
                System.out.println(obj);
            }
        }
排序查询(desc降序、asc升序)
  List list = (List) session.createQuery("select s.id,s.username from Student s order by s.id desc").list();
        for (int i = 0; i < list.size(); i++) {
            Object[] objs = list.get(i);
            for (int j = 0; j < objs.length; j++) {
                System.out.println("------------------");
                Object obj = objs[j];
                System.out.println(obj);
            }
        }
聚合函数和分组查询
  • 聚合函数,总记录数 注意返回的结果是long类型
Query query = session.createQuery("select count(*) FROM Student");
        long count = (long) query.uniqueResult();
        System.out.println(count);
  • 平均数
   Query query = session.createQuery("select avg(s.id) FROM Student s");
        double avg = (double) query.uniqueResult();
        System.out.println(avg);
  • 分组
 Query query = session.createQuery("select o.customer,count(o) from Order o group by Customer having count (o) > 2");
        List list = query.list();
        for (int i = 0; i < list.size(); i++) {
            Object[] objs = list.get(i);
            System.out.println("-------------------------------");
            for (int j = 0; j < objs.length; j++) {
                System.out.println(objs[j]);
            }
            System.out.println("-------------------------------");
        }
image.png
连接查询

INNER JOIN 在表中存在至少一个匹配时,INNER JOIN关键字返回行 LEFT OUT JOIN 关键字会从左表(table-name)返回所有的行即便右表(table-name)中没有匹配的行
RIGHT OUTER JOIN:关键字会在右表(table-name)返回所有的行,即使在左表(table-name)中没有匹配到行


image.png
隐式内连接,等效SQL隐式内连接
  Query query = session.createQuery("from Customer c,Order o where c = o.customer");
        List list = query.list();
        for (int i = 0; i < list.size(); i++) {
            Object[] objs = list.get(i);
            System.out.println("----------------------");
            for (int j = 0; j < objs.length; j++) {
                Object obj = objs[j];
                System.out.println(obj);
            }

        }
        System.out.println(query.list());
内连接
 List list = session.createQuery("from Customer c inner join c.orders").list();
        for (int i = 0; i < list.size(); i++) {
            System.out.println("---------------------");
            Object[] objects = list.get(i);
            for (int j = 0; j < objects.length; j++) {
                Object obj = objects[j];
                System.out.println(obj);
            }
        }
迫切内连接
        List customers = session.createQuery("from Customer c inner join fetch c.orders").list();
        for (int i = 0; i < customers.size(); i++) {
            System.out.println("---------------");
            Customer customer = customers.get(i);
            if (customer.getOrders().size() == 0) {
                System.out.println(customer);
            }else{
                Iterator iterator = customer.getOrders().iterator();
                while (iterator.hasNext()) {
                    Order order = iterator.next();
                    System.out.println(customer +":" + order);
                }
            }
        }
案例8,命名查询把HQL写在映射文件的query标签
  • HQL语句写在Java文件中,有时候不灵活,如果要修改语句,要重新编译项目打包
  • 我们可以在*hbm.xml中命名查询语句,然后Java会从hbm.xml取出hql语句,这样之后开发,可以直接找hbm.xml进行配置
    把HQL写在映射文件中比较灵活,HQL写入映射文件有两种方式
    第一种:写在类Class标签里面,HQL是局部【name赋值前面要加包名+类名】
    Customer.hbm.xml

        
            
        
        
        
            
            
        
        from Customer
    

代码示例: 查询语句【包名+类名+查询name的赋值】

    Query query = session.getNamedQuery("com.zzx.hibernate.domain.Customer.hql1");
        List list = query.list();
        for (int i = 0; i < list.size(); i++) {
            System.out.println("--------------");
            Iterator iterator = list.get(i).getOrders().iterator();
            while (iterator.hasNext()) {
                Order order = iterator.next();
                System.out.println(list.get(i) + ":" +order);
            }
        }

第二种:写在hibernate-mapping的标签,HQL是全局的
Customer.hbm.xml


    
        
            
        
        
        
            
            
        
    
    from Customer where name=?

代码示例:查询语句直接写入hbm.xml query标签name的赋值即可

    Query query = session.getNamedQuery("hql1");
    query.setParameter(0,"鲁智深");
    Customer customer = (Customer) query.uniqueResult();
    System.out.println(customer.getName()+":" + customer.getOrders());

QBC查询

关于QBC查询,Hibernate系列章节一有讲QBC查询链接

离线查询

Detached Criteria离线查询对象,不需要使用session就可以拼凑查询条件,一般使用在web层或service层拼凑,将此对象传递给DAO层,此时将与Session进行绑定执行查询

   DetachedCriteria dc = DetachedCriteria.forClass(Order.class);
        dc.add(Restrictions.ge("id",2));
        Criteria criteria = dc.getExecutableCriteria(session);
        List orders = criteria.list();
        for (Order order : orders) {
            System.out.println("-------------------");
            System.out.println(order);
        }

Hibernate的常见配置

整合C3P0连接池

第一步导入C3P0 Jar包工程
默认Hibernate提供的框架中有C3P0包
第二步:配置C3P0 查找Hibernate.properties

        2
        2
        500
        100
        3000
        2
        org.hibernate.connection.C3P0ConnectionProvider
事务的隔离级别
  • 原子性:整体【原子性是指事务包含的所有操作要么全部成功,要么全部失败】
  • 一致性:数据【一个事务执行之前和执行之后都必须处于一致性状态】
  • 隔离性:并发【对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后才开始,这样每个事务都感觉不到其他事务在并发的执行】
  • 持久性:结果【持久性是指一个事务一旦被提交了,要么对数据库中的数据的改变是永久性的】
隔离问题
  • 脏读:一个事务读到另外一个事务未提交的内容【读取提交的内容】,在读隔离级别,所有事务都可以看到其他未提交事务的执行结果,本隔离级别很少用于实际应用,因为它的性能也比不了其他的级别
  • 不可重复读:一个事务读到另外一个已经提交的内容(insert)【读取提交内容】这个大多数数据库系统默认隔离级别(但不是MYSQL默认的)它满足了隔离的简单定义,一个事务只能看见已经提交事务所作的改变
  • 虚读(幻读):一个事务读到另外一个已经提交的事务的内容(update)这个MYSQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取的问题,幻读,简单的说,幻读指当用户读取某一些范围的数据行时,另一个事务又在该范围内插入一行新的行,当用户再读取该范围的数据行时,才会发现新的幻读行
  • Serializable (可串行化)
    这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读的问题,简言之,它是在每个读的数据行上加入共享锁,在这个级别,可能导致大量的超时现象和锁竞争
    read uncommitld 读未提交,存在三个问题
    read committed 读已提交,解决,脏读存在两个问题
    Serializable 串行化,单事务,没有问题
Hibernate中设置隔离级别
4

你可能感兴趣的:(Hibernate配置文件HQL、QBC查询详解(四))