凯旋人生 发表于 2013-1-27 05:07:42

hibernate应用笔记

mySql数据库的隔离级别
Mysql:
查询隔离级别:  select @@tx_isolation;     REPEATABLE-READ  (可重复读)
 
更改隔离级别:  set transaction isolation level read uncommitted;(未提交读, 没commit也能读到)
 
 
 
cascade="all"   级联操作
inverse="true"  控制反转
 
◆继承映射

1)父、子类在一个表中:
 
<class name="Animal" package="extendsMapping" table="t_animal">
   <id name="id">
     <generator class="native"/>
   </id>
  <!--鉴别器要紧挨着放到id下面这个string是hibernate类型,也可以-->
  <discriminator column="type" type="string"/>用java类型  
   <property name="name"/>
   <property name="sex"/>
   <subclass name="Pig" discriminator-value="P">
       <property name="weight"/>
   </subclass>
   <subclass name="Bird" discriminator-value="B">
       <property name="height">
   </subclass>
</class>
 
2)每个父、子类在一个表中:
<class name="Animal" package="extendsMapping" table="t_animal">
   <id name="id">
     <generator class="native"/>
   </id>
   <property name="name"/>
   <property name="sex"/>
    <joined-subclass name="Pig">
      <key column="pid"/>
      <property name ="weight"/>
   </joined-subclass>
   <joined-subclass name="Bird">
     <key column="bid"/>
      <property name="height"/>
  </joined-subclass>
</class>
 
3)父类无表(有,设成抽象也不导出的),每个子类都对应一张表:(子类间id不能从)
<class name="Animal" package="extendsMapping" table="t_animal" abstract="true">
   <id name="id">
     <generator class="assigned"/><!--主键不能重复需要手动分配-->
   </id>
   <property name="name"/>
   <property name="sex"/>
   <union-subclass name="Pig" tabble="t_pig">
         <property name="weight"/>
  </union-subclass>
 
<union-subclass name="Bird" tabble="t_birg">
         <property name="height"/>
  </union-subclass>
</class>
 
◆component 映射:
       在hibernate中,component是实体对象的逻辑组成部分,component与实体对象的本质区别是它没有oid,
 
       component的好处,它实现了对象的层次细粒度划分,层次分明,利于复用
 
   <hibernate-mapping>
      <class name="mapping.User">
           <id name="id">
              <generator class="native"/>
           </id>
           <property name="name">
            <component name="contact">
                    <property name="contactTel"/>
                    <property name="email"/>
                    <property name="zipCode"/>                        
                    <property name="address"/>
            </component>
   </hibernate-mapping>
 
◆复合主键(联合主键)映射
通常将复合主键相关的属性,放到单独的实体类中
    该实体类
            ● 必须实现序列化接口 implements Serializable
            ● 必须重写equals和hashcode方法
<hibernate-mapping>
    <class name="ormapping.FiscalYearPeriod" table="t_fiscal_year_period">
       <composite-id name="fiscalYearPeriodPK">
             <key-property name="fiscalYear"/>
             <key-property name="fiscalPeriod"/>
       </composite-id>
       <property name="beginDate"/>
       <property name="endDate"/>
       <property name="periodSts"/>
      </class>
</hiberante-mapping>
 
◆集合映射映射
         ●set
         ●list
         ●array
         ●map
 
<hibernate-mapping>
   <class name="ormapping.CollectionMapping">
     <id name="id">
          <generator class="native"/>
     </id>
     <property name="name"/>
      
      <set name="setValues" table="t_setvalues">
         <key column="setid"/>

          <element type="string" column="value"></element>
       </set>
 
      <list name="listValues" table="t_listvalues">
         <key cloumn="lid"/>
         <list-index column="list_index"/><!--维护list的顺序-->
         <element type="string" column="value"/>
      </list>
 
     <array name="arrayValues" table="t_arrayvalues">
         <key column="arrayid"/>
         <list-index column="array_index"/>
          <element type="string" column="value"/>
          <!--如果不是普通属性用<composite-element>-->

     </array>
 
      <map name="mapValues" table="t_mapvalues">
           <key column="mapid">
           <map-key type="string" column="key"/>
           <element type="string"  column="value"/>

      </map>
   </class>
</hibernate-mapping>
 
◆树的映射,
     节点-父节点  many-to-one, 节点-子节点  one-to-many
   <hibernate-mapping>
      <class name="ormapping.Node" table="t_node">
          <id name="id">
                <generator class="native"/>
          </id>
           <porperty name="name"/>
           <property name="levle"/>
           <property name="leaf"/>
             <!--<many-to--one>在多的一段加个外键指向一的一端,这个例子中就一个表,加的外键指向本表,即自关联-->
           <many-to-one name="parent" column="pid"/>
           <set name="children" lazy="extra" inverse ="true">
                  <key column="pid"/>
                   <one-to-many class="ORMapping.Node" >
           </set>
 
      </class>
   </hibernate-mapping>
 
 
◆hibernate中的锁
悲观锁:其实现一般依赖于数据库提供的机制,在整个处理过程中数据将处于锁定状态
 
例如: select * from user for update
        select * from user for update nowait(oracle用)
 
hibernate中用  load(Class theClass,Serializable id,LockMode lockMode),<a href="../../org/hibernate/LockMode.html#UPGRADE_NOWAIT" />
<a href="../../org/hibernate/Session.html#load(java.lang.Class, java.io.Serializable, org.hibernate.LockMode)" />
lockMode: UPGRADE(ORACLE用 UPGRADE_NOWAIT)
 
乐观锁:大多数是基于数据版本记录机制实现(version),一般在数据库中加一个version字段
         读取数据时连同版本号一同读出,之后更新是版本号加一,如果提交数据小于当前版本
         号则认为数据是过期的否则才能更新。(也有用时间戳实现的。)
<hibernate-mapping>
   <class name="ormapping.user" optimistic-lock="version"><!--不写也可以默认就是version-->
          <id name="id">
                <generator class="uuid"/>
          </id>
          <version name="version"/>
           <property name="name"/>
              ...
   </class>
</hibernate-mappin>
 
 
 
 
 
 
hibernate的 lazy(延迟加载):
lazy的策略可以用在:
   ● <class>标签上,可以去值:true/false
   ● <property>标签上,可以取:true/false,这个属性需要类增强工具
   ● <set><list>等集合上,可以去值:true/false/extra
   ● <one-to-one>和<many-to-one>(单端关联)等标签上,可以取:false/proxy/noproxy
 
概念:
   ● lazy是只有需要的时候才发出sql语句
   ● hibernate支持lazy策略,只有session打开状态才有效可以用 ThreadLocale和Filter->OpenSessionInView来解  决。
    hibernate在class级别的lazy可以控制什么时候加载这些普通属性(property),但不能控制many-to-one one-to-many等。
 
 
 hibernate在集合上的lazy策略,可以取值ture/false/extra (智能推荐)
 
 hibernate在单端关联的lazy策略<one-to-one>和<many-to-one>,可以取值: false/proxy/noproxy(noproxy需要类增强工具)
 
 
◆ HQL查询
1 简单属性查询
 
 ●单个属性查询,返回结果集为单个属性的集合。
   List students= session.createQuery("select name from Student").list();
   //students 为name对应的类型String集合List<String>
    for(Iterator iter=students.iterator();iter.hasNext()){
       String  name =(String)iter.next();
    }
 
 ●多个属性查询,返回结果为对象数组的集合,对象数组的长度取决于查询属性的个数,类型取决于属性类型
   List students = session.createQuery("select id,name from Student").list();
 
     for(Iterator iter=students.iterator();iter.hasNext()){
         Object[] objs=(Object[])iter.next();
    }
 
 ●多个属性查询,用hql动态实例化对象返回
   List students = session.createQuery("select new Strudent (id,name) from Student").list();
 
     for(Iterator iter=students.iterator();iter.hasNext()){
       Student student = iter.next();
    }
 
 ●别名
   List students = session.createQuery("select s.id, s.name from Student s").list();
   或
   List students = session.createQuery("select s.id, s.name from Student as s").list();
 
2 查询实体对象
 
●查询实体对象 可以忽略select,但如果用select了必须使用别名,hql不支持*,支持count(*)
   List students = session.createQuery("from Student").list();
 //List students = session.createQuery("select s from Student as s").list();
    for(Iterator iter=students.iterator();iter.hasNext()){
       Student student = iter.next();
    }
   ●)n+1问题,在默认情况下使用query .iterate()查询,可能会引发n+1问题,所为n+1是指在查询
   对象的时候发出了n+1条查询语句
   1:首先发出查询实体对象id列表的sql
   n:根据id在缓存中查询,如果缓存中有与之匹配的数据,那么就区缓存中的数据,否则依次根据id发出查询语句。
 
   ●)query.list()默认只往缓存中放不从缓存中读。
     发出 select student0_.id as id1_,student0_.name as name1,.... from t_student as   student0_
    query.iterate(),会利用缓存读取查询,第一次查询 会发出n+1条select语句,1为先查id的sql语句,然后根据id 查
     n为记录的总数,如果第2回就不会了....
  select student0_.id as col_0_0_ from t_student as student0_
 
  select student0_.id as col_0_0_,student0_.name as name1,....from t_student as student0_ where student0_.id = ?
 
3 条件查询
  可以拼HQL串,
    List students = session.createQuery("select s.id ,s.name from Student s where s.name like '%1%'").list();
  方法链编程,传递参数不需要''号
    ●采用?传递参数
   List students = session.createQuery("select s.id ,s.name from Student s where s.name like ?").setParameter(0,"%1%").list();
     ●采用 :参数名传递
   List students = session.createQuery("select s.id ,s.name from Student s where s.name like :myname
").setParameter("myname","%1%").list();
 
    ● 条件查询支持in ,通常用setParameterList来赋值
   List students = session.createQuery("select s.id ,s.name from Student s where s.id in (:myids) ")
           .setParameterList("myname",new Objects[]{1,3,5}).list();
    ●between
   List students = session.createQuery("select s.id ,s.name from Student s where s.createTime
between ? and ? order by s.id ").setParameterList(0,mydateformat.parse("2008/08/01")).setParameterList(1,dateformat.parse("2008/08/25")).list();
   ●调用数据库的函数
   List students = session.createQuery("select s.id ,s.name from Student s where date_format(s.createTime,'%Y-%m')=? order by s.id ")。setParameterList(1,"2008/08/25").list();
 
4 外置命名查询
   ● 在映射文件中采用<query>类定义hql
<hibernate-mapping>
  <class name=...>
  ...
  </class>
  <query><![CDTA[
             select s from Student s where s.di <?
  ]]>
  </query>
</hibernate-mapping>
   ●在程序中使用session.getNamedQuery()方法来得到查询(query对象)


5 查询过滤器
   ●定义过滤器参数
   ●在类映射文件中使用过滤参数
   ●在程序中启用过滤器
<hibernate-mapping>
  <class name=...>
  ...
  <!--在类映射文件中使用过滤参数-->
 <filter name="filtertest" condition="id < :myid " />
  </class>
 
     <!--定义过滤器参数-->
    <filter-def name="filtertest">
         <filter-param name="myid" type="integer">
    </filter-def>
<hiberante-mappingapping>
 
 //在程序中启用过滤器,并设置参数
 session.enableFileter("filtertest").setParameter("myid",10);
 
6.hibernate3开始支持原生sql查询
  //返回结果是对象数组的集合,顺序同数据库中表的顺序
   session.createSqlQuery("select * from t_student").list();
     for(Iterator iter=students.iterator();iter.hasNext()){
         Object[] objs=(Object[])iter.next();
    }
 
7分页查询
   session.createQuery("from student").setFirstResult(0).setMaxResults(2).list();
 
8 对象导航查询 在hql中,使用.进行导航
   session.createQuery("select s from student s where s.classes.id <5")
 
9 连接查询
   ●内连接
     session.createQuery("select c.name, s.name from Student s join s.classes c").list();
   ●外连接(左连接/右连接)
     左连接 把所有班级都显示出来
     session.createQuery("select c.name, s.name from Classes c left join c.students s").list();
     右连接 把所有学生都显示出来
      session.createQuery("select c.name, s.name from Classes c right join c.students s").list();
 
10.统计查询
     List students=session.createQuery("select count(*) from Student").list();
     Long count = (Long)students.get(0);
 
     Long count=session.createQuery("select count(*) from Student").uniqueResult();
 
     session.createQuery("select c.name,count(s) from Student s join s.class c
     group by c.name order by c.id").uniqueResult();
 
 
hibernate的一级缓存
  一级缓存的生命周期和session一致,随着session的关闭而销亡。
    ●get/load/iterate(查询实体对象)使用一级缓存
  一级缓存缓存的是实体对象。   
  如何管理一级缓存
    ●session.clear/session.evict
 
  如何避免一次性大批量的实体数据插入
    ●先flush,在clear清除缓存
 
hibernate的二级缓存
   二级缓存也是缓存实体类
   二级缓存也称进程级缓存或叫SessionFactory级缓存,它可以被所有session共享
   二级缓存的生命周期伴随SessionFactory的生命周期存在和销往
   SessionFactory可以管理二级缓存
   二级缓存的配置和使用:
      ●将ehcache.xml文件拷贝到src下
      ●在hibernate.cfg.xml中配置启用二级缓存,默认就是开启
 
     <hibernate-configuration>
         <session-factory>
                    ...
          <!--是否启用二级缓存-->
          <property name="hibernate.cache.use_second_level_cache">true</property>
          <!--指定使用的二级缓存产品-->
          <property name="hibernate.cache.EhCacheProvider_class"
         </session-factory>
     </hibernate-configuration>
    ●指定哪些实体类使用二级缓存
     1)可以在hibernate.xml配置文件中定义
     <class-cache class="xxx" usage="read-only"/>
     2)可以在映射文件中配置缓存策略
      <hibernate-mapping>
         <class name="xxx">
           <cache usage="read-only"/>
         </class>
      </hibernate-mapping>
 
    ●一二级缓存的交互,通过setCacheMode(Cache.Mode.GET)(PUT)默认读写
hibernate的查询缓存
    查询缓存是针对普通属结果集的缓存
    对实体对象的结果集只缓存主键id.
 
    查询缓存的生命周期,当查询关联的表发生修改,那么查询缓存的生命周期结束。
 
    查询缓存的配置和使用:()
           在hibernate.cfg.xml文件中加入
           <property name="hibernate.cache.use_query_cache">true</property>
 
           在程序中显式开启查询缓存
           query.setCacheable(true);            
 
说明:转义字符应以“&”开头,以“;”结尾。
HTML常用转义字符:            
字符
转义字符
描述
&
&

<
<
小于号
>
>
大于号
"
"
双引号
 
 
空格
©
©
版权符
®
®
注册符
XML常用转义字符:
字符
转义字符
描述
&
&

<
<
小于号
>
>
大于号
"
"
双引号
'
'
单引号
页: [1]
查看完整版本: hibernate应用笔记