Hibernate HQL

 

HQL中关键字不区分大小写,属性和类名区分大小写

 

1、简单属性查询重要

    * 单一属性查询,返回的结果集是属性的列表,其元素类型和实体类中属性的类型一致

        List students = session.createQuery("select name from Student").list();

       

        for(Iterator it = students.iterator(); it.hasNext();)

            {

                String name = (String)it.next();

            }

           

    * 多个属性查询,返回的结果集是对象数组,数组元素中的类型与对应实体类中的属性类型一致,数组的长度和查询的属性个数一致

        List students = session.createQuery("select id, name from Student").list();

       

        Object[] o = (Object[])it.next();

        System.out.println(o[0] + "," +o[1]);

       

    * 如果认为返回的数组不够对象化,可以采用HQL动态实例化实体对象

        select new Student(id,name) from Student,可以返回Sudent对象

       

2、实体对象查询重要

    * N+1问题,在默认配置的情况下,使用query.iterate()操作,有可能有N+1问题。

      所谓N+1,指在查询对象数据的时候,发出了N+1SQL语句。

      1:首先发出了一条查询语句,查询对象的id列表

      n:根据id列表发出N条查询语句

    * List操作与Iterate操作的区别

        list在默认情况下,只向缓存(一级缓存,session级缓存)中放入数据,而不利用缓存中的数据

        Iterate在默认情况下有N+1问题,如果缓存中存在数据,那么会根据id到缓存中获取数据,也就是说iterate是利用缓存中的数据的

 

3、条件查询(重要)

    * 可以拼字符串的形式传递参数

        如:select id, name from Student where name like '%1%'

    * 可以用过?来传递参数(注意索引值是从0开始的,跟jdbc不同,jdbc是从1开始的)

        如:select id, name from Student where name like ?

* 可以使用方法链,通过 . 导航

        session.createQuery(

                    "select id,name from Student where name like ?")

                    .setParameter(0, "%1%").list()

        传递的参数值不需要用单引号引起来

       

    * 可以通过 【:参数名】 来传递参数(即命名参数方式)

        如:List students = session.createQuery("select id, name from Student where name like :myname").setParameter("myname", "%1%").list();

    * 如果对应的参数值是多个,可以调用setParamterList()方法开传递

        如:select id, name from Student where name like :myname and id=:myid

    * 支持in,采用setParameterList进行参数传递

        session.createQuery(

                    "select id,name from Student where id in(:myids)")

                    .setParameterList("myids", new Object[] { 1, 2, 3, 4, 5 })

                    .list();

 

    * HQL中可以使用数据库的函数,如MySQL中的date_format()

        session.createQuery("select id,name from Student where date_format(createDate,'%Y-%m')=?")

                    .setParameter(0, "2007-02").list();

 

4hibernate也支持直接使用原生sql进行查询

       如:List students = session.createSQLQuery("select * from t_student").list();

      

5、外置的命名查询

    * 在映射文件中通过<query>标签定义HQL

        <query name="searchStudent">

            <![CDATA[

                select s from Student s where s.id<? 

]]>

        </query>

    * 在程序中使用session.getNameQuery()方法获得这个查询

        如:session.getNamedQuery("searchStudent")

   

6、查询过滤器

    * 在映射文件中定义过滤器参数

        <filter-def name="filtertest">

            <filter-param name="myid" type="integer"/>

        </filter-def>

    * 在类映射文件<class>标签中使用这些参数

        <filter name="filtertest" condition="id &lt; :myid"/>

    * session中启用过滤器

        session.enableFilter("filtertest")

                       .setParameter("myid", 10);

                  

7、分页查询

    * setFirstResult(), 数据的起始位置,从0开始

    * setMaxResults(), 每页显示多少条数据

   

8、对象导航查询,在HQL中,进行导航重要

    * 可以使用“.”的方式进行对象导航

select s.name from Student s where s.classes.name='班级1'

 

9、连接查询

    * 内连接

    * 外连接(左连接/右连接)

 

10、统计查询重要

    统计查询中支持 *

    返回的可以是Long包装类型

    * Long count = (Long)session.createQuery("select count(*) from Student").uniqueResult();

 

 

 

hibernate一级缓存

1、缓存的作用主要用来提高性能,可以简单的理解成一个Map;使用缓存涉及到三个操作:把数据放入缓存、从缓存中获取数据、删除缓存中的无效数据

2save,update,saveOrUpdate,load,get,list,iterate,lock这些方法都会将对象放在一级缓存中,一级缓存不能控制缓存的数量,所以要注意大批量操作数据时可能造成内存溢出;可以用evict,clear方法清除缓存中的内容

    3、一级缓存生命周期很短,它和session的生命周期一致,一级缓存也叫session级缓存,也称事务级缓存  

    4、一级缓存它缓存的是实体对象,不缓存属性

    5、一级缓存如何管理

        一级缓存机制无法取消,但可以管理

        * session.clear() 

* session.evict()

只是把缓存里的数据删除了,数据库里的数据没有删

    6、如何避免一次性大批量实体数据插入内存溢出的问题?

        * 先执行flush,在用clear清除缓存

    7、如果在现实工作中遇到了大规模的数据,建议使用JDBC导入,或者使用数据库特定工具导入

 

hibernate二级缓存

二级缓存相当于WEB Application

    二级缓存中存储的也是实体对象

    二级缓存也称进程级缓存或SessionFactory级缓存,二级缓存可以被所有session共享

    二级缓存的生命周期和SessionFactory生命周期一致,SessionFactory可以管理二级缓存

   

二级缓存的配置与使用

    1、 将ehcache.xml配置文件拷贝到src下,针对不同的策略配置缓存

    2、 启用二级缓存,默认是启用的

        <property name="hibernate.cache.use_second_level_cache">true</property>

    3、 指定缓存产品提供商,如:

        <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>

    4、 指定哪些实体类使用二级缓存(两种方式)

        (1)、 在hibernate.cfg.xml(推荐)

                如:<class-cache class="com.bin.hibernate.Student" usage="read-only"/>

        (2)、在映射文件中指定

                如:<cache usage="read-only"/>

 

hibernate查询缓存

(1)、查询缓存是缓存普通属性结果集的

(2)、对实体对象的结果集只缓存id

(3)、查询缓存的生命周期:当关联的表发生修改,那么查询缓存的生命周期结束。

(5)、查询缓存的配置和使用:

        * hibernate.cfg.xml文件中启用查询缓存: <property name="hibernate.cache.use_query_cache">true</property>

       * 在程序中必须手动启用查询缓存,如:

         query.setCacheable(true)

(6)、查询缓存只对query.list()起作用,对query.iterate()不起作用

        query.iterate()不使用查询缓存

 

事务

1session context和事务边界

current_session_context_class属性来定义context(用sessionFactory.getCurrentSession()来获得session),其值为:

 

(1).threadThreadLocal来管理Session实现多个操作共享一个Session,避免反复获取Session,并控制事务边界,此时session不能调用closecommitrollback的时候session会自动关闭(connection.release_mode:after_transaction)

        Open session in view:在生成(渲染)页面时保持  session打开。

(2).jta:由JTA事务管理器来管理事务(connection.release_mode:after_statement)