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

HQL简介

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

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

查询案例

投影查询

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

 List<Object[]> list = (List<Object[]>) 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<Object[]> list = (List<Object[]>) 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<Object[]> 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<Object[]> 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<Object[]> 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<Customer> 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<Order> 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
<class name="Customer" table="t_customer">
        <id name="id">
            <generator class="native"></generator>
        </id>
        <property name="name"></property>
        <set name="orders" inverse="false" cascade="save-update,delete" batch-size="2">
            <key column="customer_id"></key>
            <one-to-many class="Order"></one-to-many>
        </set>
        <query name="hql1">from Customer</query>
    </class>

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

    Query query = session.getNamedQuery("com.zzx.hibernate.domain.Customer.hql1");
        List<Customer> list = query.list();
        for (int i = 0; i < list.size(); i++) {
            System.out.println("--------------");
            Iterator<Order> 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

<hibernate-mapping package="com.zzx.hibernate.domain">
    <class name="Customer" table="t_customer">
        <id name="id">
            <generator class="native"></generator>
        </id>
        <property name="name"></property>
        <set name="orders" inverse="false" cascade="save-update,delete" batch-size="2">
            <key column="customer_id"></key>
            <one-to-many class="Order"></one-to-many>
        </set>
    </class>
    <query name="hql1">from Customer where name=?</query>
</hibernate-mapping>

代码示例:查询语句直接写入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<Order> orders = criteria.list();
        for (Order order : orders) {
            System.out.println("-------------------");
            System.out.println(order);
        }

Hibernate的常见配置

整合C3P0连接池

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

        <property name="hibernate.c3p0.max_size">2</property>
        <property name="hibernate.c3p0.min_size">2</property>
        <property name="hibernate.c3p0.timeout">500</property>
        <property name="hibernate.c3p0.max_statements">100</property>
        <property name="hibernate.c3p0.idle_test_period">3000</property>
        <property name="hibernate.c3p0.acquire_increment">2</property>
        <property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
事务的隔离级别
  • 原子性:整体【原子性是指事务包含的所有操作要么全部成功,要么全部失败】
  • 一致性:数据【一个事务执行之前和执行之后都必须处于一致性状态】
  • 隔离性:并发【对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后才开始,这样每个事务都感觉不到其他事务在并发的执行】
  • 持久性:结果【持久性是指一个事务一旦被提交了,要么对数据库中的数据的改变是永久性的】
隔离问题
  • 脏读:一个事务读到另外一个事务未提交的内容【读取提交的内容】,在读隔离级别,所有事务都可以看到其他未提交事务的执行结果,本隔离级别很少用于实际应用,因为它的性能也比不了其他的级别
  • 不可重复读:一个事务读到另外一个已经提交的内容(insert)【读取提交内容】这个大多数数据库系统默认隔离级别(但不是MYSQL默认的)它满足了隔离的简单定义,一个事务只能看见已经提交事务所作的改变
  • 虚读(幻读):一个事务读到另外一个已经提交的事务的内容(update)这个MYSQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取的问题,幻读,简单的说,幻读指当用户读取某一些范围的数据行时,另一个事务又在该范围内插入一行新的行,当用户再读取该范围的数据行时,才会发现新的幻读行
  • Serializable (可串行化)
    这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读的问题,简言之,它是在每个读的数据行上加入共享锁,在这个级别,可能导致大量的超时现象和锁竞争
    read uncommitld 读未提交,存在三个问题
    read committed 读已提交,解决,脏读存在两个问题
    Serializable 串行化,单事务,没有问题
Hibernate中设置隔离级别
<property name="hibernate.connection.isolation">4</property>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353

推荐阅读更多精彩内容