hibernate复习第五天


回顾:
    一对多的集合里存的是持久对象,叫实体;不是值类型;String/Integer等
    实体的特征是有自己的oid和映射文件;值类型是没有oid的,不能当成持久对象;一般作为持久对象的属性;
   
 一, 集合映射: (用的很少)

    Set是无序的,不能重复的;
    Bag是介于Set和List之间的,java里没有,Hibernate模拟的, 它是无序的,但是允许重复的;
    List是有序的,元素可以重复;
    Map的key是不能重复的,value可以重复;
   
  (1)set映射:
  
    Person 类:name,age,gender,aliases(外号/别名)
   
    <set name="aliases" table="t_aliases"> <!-- 只有集合本身的映射表 -->
           <key column="fid"></key> <!--外号表引用person表的主键 -->
           <element type="String" column="aliases"></element>
    </set>
   
    1,set是对集合本身的声明;table是集合元素(String类型)所存在的表;
       既不是po的表,也不是多对多的关联表;在集合映射中,set属性即集合本身对应一个表;
    2,fid,是set映射主表的主键上;
    3,element,不是PO不是一对多,多对多关系;element没有表明任何的基数关系,而是集合关系;
    4,type说明集合里的元素类型,column是元素在set映射表中的字段;
  
  (2)bag映射: 在java里用 List 模拟(不保存下标);       
   
    Indexs类 ---  Images 
   
     <idbag name="images" table="t_images">
        <collection-id  column="id" type="integer"><!-- 加了一个主键保证记录唯一 -->
            <generator class="increment" />
        </collection-id>
        <key column="fid"></key>  <!-- 外键也是可以重复的-->
        <element type="String"  column="image"></element> <!--集合里的元素是可以重复的 -->
     </idbag>
    
   (3)list映射:
  
    Word类 ---  descs ; 外键和list-index做联合主键;
   
    <list name="descs"  table="t_descs">
        <key column="fid"></key>    <!-- 外键可以重复-->
        <list-index  column="listIndex"></list-index>  <!--下标也是可以重复的 -->
        <element column="descri" type="string">   <!-- desc跟系统重名-->
    </list>
       
   (4)map映射:
  
   Dictionary类 ---  words    map-key是key,element是value,  (map.entry类型 key-value)
                                     外键和map-key做联合主键;
   <map name="words" table="t_words">
        <key column="fid"></key>
        <map-key column="word" type="string"></map-key>
        <element column="descs" type="string"></element>
   </map>  
 
 二, 组件映射:(用的很多)
  
    组件也属于值类型的一种,是用户自定义的;
           非PO;无oid,不需要单独写映射文件,资源利用很少;
   
    实体映射(PO):基数映射和继承映射;
    组件映射(非PO):寄居在实体中,细粒度,不需要单独持久化的对象;
 
  1, 一对一的组件映射: 
    first-name, last-name  变成一个组件===>  name
    NamePair:就是一个组件;
    可以使我们的代码更易读,更精细;
    在映射时作为po的一部分,和po放到一个表里;
   
    Account: aid,actNo,balance,owner, Address
       
         把地址当成寄居在Account里;因为别的类也不用;
         把Address的oid去掉;把一对一的关联关系,变成了组合关系;没有oid的非PO;
   
    Account.hbn.xml
       address属性的映射:
       <component  name="addr"  class="Address">
            <property name="postCode"></property>
            <property name="city"></property>
            <property name="street"></property>
       </component>
     能当组件看不当PO看,简单;

 2, 一对多的组件映射:
     集合映射和组件映射结合起来;
     在Account中加上一个Address集合;
     private  Set addrs=new HashSet();        
    
     映射文件:
     <set  name="addrs"  table="t_addrs">
            <key  column="fid" > <!-- 引用主表的主键作为外键 -->
            <composite-element  class="Address">  <!-- 集合里的元素是一个对象,不是普通的element-->
                <property name="postCode"></property>
                <property name="city"></property>
                <property name="street"></property>
            </composite-element>
     </set>
 
    注:  Hibernate的配置文件里.同一个类只能有一个映射文件;
   
 三, 获得session的方法:
 
   hibernate 3.1  在SessionFactory 中提供了一个方法;
   getCurrentSession() 获得当前线程的session;如果第一次调用,
                                会给你创建一个session;下次再用的话,直接得到这个session;
   跟显示调用ThreadLocal不同的是,当事务一结束,即提交或回滚时,自动关闭session;
   不需要显式关闭;  一事务一session;
   
    Session  s=(Session)sf.getCurrentSession();
    tran.commit();//提交后再用session的话,还会再创建一个;开始的是一个新的事务;
                        // 保证的是一个事务一个session
    Dao里不能提交(以方法为单位),放在Services里(以业务的原子操作为单位)提交;
    应用事务开启--数据库事务开启---应用事务关闭(数据库事务关闭)
   
    注:
    在hibernate的配置文件里需要配置绑定在哪里?JPA(分布式事务管理器)或session;
    <property name="current_session_context_class">thread</property>
 
 四, 查询:
 
   1, 有很多记录要查询时:
   public  static List  findByNames(List  l){
        Session  s=HbnUtil.getCurrentSession();
        Transaction  tran = null;
        List  result = null;
        tran=s.beginTransaction();
        Query  q=s.createQuery("from Account  a where a.owner  in(:namelist)");
        q.setParameterList("namelist", l );
        result = q.list();
        tran.commit();
        return result;
   }
  
   2,属性查询
       有时进行查询时不需要得到对象的所有属性,这时我们可以进行属性查询
         Query  query = session.createQuery(" select p.name  from  Person p " );
       利用这种HQL语句查询出来的结果中,就只包含需要的指定的属性值
       如果查询两个以上的属性值时,查询出来的结果会以数组的方式返回
       Query  query = session.createQuery(" select p.name , p.age  from  Person as p ");
       List   list = query.list();
       for(int i=0; i<list.size(); i++){
         Object obj[] = (Object[])list.get(i);
         System.out.println("name===="+ obj[0]);
         System.out.println("age ===="+ obj[1]);
        }
   3,实例化查询:
        实例化查询其实是对属性查询的一种改进,示例如下:
      Query  query = session.createQuery(" select  new Person(p.name , p.age) from  Person p");
      List   list =  query.list();
      for(int i=0; i<list.size(); i++){
       Person p = (Person)list.get(i);
       System.out.println("name===="+ p.getName() );
       System.out.println("age ===="+ p.getAge() );
      }
   4, 分页查询:
       利用hibernate提供的setFirstResult()和setMaxResults()两个方法可以很好的定位
       结果集中要查询记录的位置,是分页显示的一种较好的实现方案.
      public static List  readPage(int  start , int  num){
             Session  s=HbnUtil.getCurrentSession();
             Transaction  tran = null;
             List  result = null;
             tran=s.beginTransaction();
             Query query = session.createQuery(" from   实体类名 " );
          query.setFirstResult(start);  //设置查询记录开始行
          query.setMaxResults(num);     //设置查询的多少行记录
          return query.list() ; 
      }
    
     补充: rownum只能用<或<=; 可以用起别名的方式来达到目的;
       
        --查询第1-5条记录
           select * from (select rownum num, s_emp.*  from s_emp)
           where num >=1 and num <= 5;
       
        --按工资排序,五条一页,查找第二页
           select salary,first_name
              from(
               select s.*, rownum rm
               from (select *
                          from s_emp
                          order by salary desc
                  ) s
               )
            where rm between 6 and 10;
           
 复习:
 
 一, ORMapping:
   
    ORM:持久化,怎样?
    a.串行化(序列化):
    b.关系型数据库:
        关系:  jdbc类:(30)代码量大,不好移植,易出错;
                  EJB Entity:(60)功能太强大了,部署比较复杂,也不适合;
                  Hibernate:(80)功能刚好,也不是很复杂,具有移植性;
   
    xml文件, PO, 测试类;
    持久化对象的确定;
    xml文件的配置;
 二, 基数映射:
   1,一对一: day02
     共享主键,其中一个主键还做外键; 两个<one-to-one>
     引用外键, 一个<many-to-one>和一个<one-to-one>
    
     普通属性用<property>
     第一个特殊的属性就是<id>
     另外关联属性用 <many-to-one>等表示;
     <one-to-one>表示了一对一的对应关系;
   2,一对多:day03
     一的一方强的级联;多的一方弱的级联;cascade
     inverse=true;交给多的一方去处理关系;
   3, 多对多:day04
      有一个中间表
 三,继承映射:day04
 四,组件映射:day05
 五,状态:
    session: 一级缓存;保持同步;
    sessionFactory:二级缓存, 只读不写的话,可以把二级缓存打开,否则没用;


 作业:   
    类图: User  1 ----  m       Account  --- Address(改成组件映射)
           m   /                      /         \
         1 权限          m      Debit       Check       m
                                     /                \
                           1    in-policy          O-policy   1
                              (存款政策)          透支政策(一个透支政策可以给多个check使用)
     
        Account: 
                    <many-to-one>
                    <component>
                    <subclass>
  
  
   关键是多练习.大概知道是怎么回事就行了.
   只有写与不写的区别,没有会与不会的区别.
   五万行代码;
   明天讲html和javascript
  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值