<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    GONE WITH THE WIND

    --tomorrow is another day

      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      30 隨筆 :: 19 文章 :: 0 評論 :: 0 Trackbacks

    構(gòu)造這樣一個例子,在測試過程中來說明一些Hibernate的高級配置及其相關(guān)機制:
    有三個類:Category.java,Prodcuct.java,ConfigurationTest.java,其中第三個類是用來測試的。
    Category.java代碼:
           

    package unsaved_value;    
    import ......    
    public class Category {    
        private Integer id;    
        private String name;    
        private String description;    
        private Set products;    
        public Category(){    
             id=null;    
             name=null;    
            description=null;    
            products=new HashSet ();    
         }    
         public void addProduct(Product p){    
             products.add(p);    
        }    
         //**********setter and getter    
        ........    
    }   


    Product.java代碼:


    package unsaved_value;      
    public class Product {      
        private Integer id;      
        private String name;      
        private Category category;      
        private String description;      
        public Product(){     
             
        }      
         //*******getter and setter      
         .........      
    }      

    ConfigurationTest.java

    public void testSave()throws Exception{    
            Category category=new Category();    
            category.setName("java編程書籍2");    
            category.setDescription("編程經(jīng)典書籍2");    
            Product pro=new Product();    
            pro.setName("java編程思想2");    
            pro.setDescription("第四版中文版2");     
            pro.setCategory(category);    
            category.addProduct(pro);    
            Transaction tx=session.beginTransaction();    
            assert (session!=null):("session is null");    
            session.save(category);    
            tx.commit();    
        }    

         
    Category代表產(chǎn)品目錄,而Product代表產(chǎn)品,顯然Category與Product是一對多的關(guān)系。Hibernate在映射一對多關(guān)系時,有兩種方式,一種是單向一對多,一種是雙向關(guān)系。兩者相比,雙向一對多的好處體現(xiàn)在兩方面:首先,也是很明顯的一點,由于是雙向關(guān)聯(lián),我們在實際業(yè)務(wù)邏輯時將更方便,例如我們可以檢索一個Category下的所有Product,同時還可以檢索出Product屬于哪個。其次,雙向關(guān)系相對單向關(guān)系而言,在數(shù)據(jù)庫的訪問方面更有優(yōu)勢。這一點留在后面講inverse時講
    。雙向關(guān)聯(lián)比單向關(guān)聯(lián)唯一的”劣勢“,就在于雙向關(guān)聯(lián)需要比單向關(guān)聯(lián)多寫一個映射文件,這不問題。使用雙向關(guān)聯(lián)實現(xiàn)這兩個類同數(shù)據(jù)庫的映射:

    Category.hbm.xml:  
    version="1.0" encoding="UTF-8"?>  

    " <hibernate-mapping package="unsaved_value">  
       <class name="Category" table="category">  
         <id name="id" column="id">  
           <generator class="native">generator>  
         id>  
         
         <property name="name" column="name"/>  
         <property name="description" column="description"/>


         <set name="products" table="product" lazy="true" inverse="true" cascade="all">  
             <key column="category"/>  
                <one-to-many class="Product"/>  
         set>  
         
       class>  
    hibernate-mapping>  
      
    Product.hbm.xml:


    version="1.0" encoding="UTF-8"?>    
    "
    <hibernate-mapping package="unsaved_value">    
    <class name="Product" table="product">    
         <id name="id" column="id" unsaved-value="null">    
             <generator class="native">generator>    
         id>    
             
         <property name="name" column="name"/>    
         <property name="description" column="description"/>    
           
         <many-to-one name="category"    
                      column="category"     
                      class="Category"    
         />    
       class>    
    hibernate-mapping>    
            
    現(xiàn)在把這個例子所牽涉到的知識一一展開:
    一.inverse
        該詞的譯意是“反轉(zhuǎn)”,反轉(zhuǎn)什么——反轉(zhuǎn)控制端,這項配置決定了由關(guān)聯(lián)雙方中的哪一方來維持關(guān)聯(lián)關(guān)系(在數(shù)據(jù)庫中表現(xiàn)為外鍵約束)。上述配置中,在Category.hbm.xml中將inverse設(shè)置為true,意思是說“我需要反轉(zhuǎn)(控制端)”,反轉(zhuǎn)的結(jié)果是由對方即Product來維持關(guān)聯(lián)關(guān)系。用單向關(guān)聯(lián)更容易說明”維持關(guān)聯(lián)關(guān)系“是什么意思:考慮用單向關(guān)系來實現(xiàn)這個映射關(guān)系的情況,即由Category關(guān)聯(lián)到Product,考慮下面的代碼:

    Product p=new Product();  
    ..setXXX  
    Category c=new Category();  
    ..設(shè)置Category的屬性  
    c.addProduct(p);//建立起了c和p的關(guān)聯(lián)關(guān)系  
    session.save(c);  

    會執(zhí)行三條SQL語句:兩條插入語句,分別插入c和p,然后還有一條update語句建立起c和p的關(guān)聯(lián)(更新p的外鍵)。上面,我們說由Category端控制關(guān)聯(lián),因此p.setCategory(c)這樣一句話是沒用的,它并不會導(dǎo)致在插入p的時候就設(shè)置p的外鍵以建立起兩者的關(guān)聯(lián)關(guān)系,從而節(jié)省一條update語句。同時我們還會看到,如果在數(shù)據(jù)庫模式中將p的外鍵設(shè)置成非空,這些代碼將不能執(zhí)行,因為在插入p時,由于c和p的關(guān)聯(lián)關(guān)系還未建立起來,因此p的外鍵為空。回到雙向關(guān)聯(lián)上來,為了更清楚地明白inverse在雙向關(guān)聯(lián)中到底起什么作用,我們分別將其值設(shè)為true和false,看看打印出的的SQL有何區(qū)別:

    inverse=true時的打印結(jié)果:

    Hibernate: insert into category (name, description) values (?, ?)  
    Hibernate: insert into product (name, description, category) values (?, ?, ?)   
    inverse=false時的打印結(jié)果:

    Hibernate: insert into category (name, description) values (?, ?)    
    Hibernate: insert into product (name, description, category) values (?, ?, ?)    
    Hibernate: update product set category=? where id=?   
           為什么inverse=true時會比inverse=false時少執(zhí)行一條SQL語句?這是由控制端的不同造成的。前者說"我要反轉(zhuǎn)控制,由Product來控制關(guān)聯(lián)",因此在將p對象insert時,p已經(jīng)設(shè)置了其category字段,從而建立了關(guān)聯(lián)關(guān)系,而后者說"我不反轉(zhuǎn)控制,由我自己來控制關(guān)聯(lián)",因此在將p對象insert后,c為了維持兩者的關(guān)聯(lián),還要去執(zhí)行一次update,以更新p的外鍵,從而建立起兩者的關(guān)聯(lián)關(guān)系。
    結(jié)論:對于一對多雙向關(guān)系,始終在“一”那一方將其inverse設(shè)置成true,這樣會提高性能。

    二.cascade
       級聯(lián)。當(dāng)關(guān)聯(lián)的"一"方進(jìn)行某種動作(更新,刪除)時,"多"方即使沒有顯式地進(jìn)行編碼,它也會自動進(jìn)行同樣的動作。cascade的可選值有:
    all : 所有情況下均進(jìn)行關(guān)聯(lián)操作。即是save-update + delete
    none:所有情況下均不進(jìn)行關(guān)聯(lián)操作。這是默認(rèn)值。
    save-update:在執(zhí)行save/update/saveOrUpdate時進(jìn)行關(guān)聯(lián)操作。
    delete:在執(zhí)行delete時進(jìn)行關(guān)聯(lián)操作。
    all-delete-orphan:A:級聯(lián)save-update B級聯(lián)delete C:刪除所有孤兒項(orphan孤兒)。先看看父子關(guān)系,例如在Customer和Order的模型中,這兩者便是父子關(guān)系,當(dāng)一個Customer的生命周期決定Order的生命周期,如果一個Customer不在了,其相關(guān)的Order繼續(xù)存在是毫無業(yè)務(wù)意義的。刪除所有孤兒項的意思即是,刪除所有與父對象失去關(guān)聯(lián)關(guān)系的子對象。

    三.lazy
        是否延遲加載。一般來說,應(yīng)該延遲加載,即將lazy設(shè)為true。延遲加載的相關(guān)點很多,這在另外的學(xué)習(xí)筆記中總結(jié)。

    四.unsaved-value
        以上是"一"方的重要配置,再看看"多"方的一個重要配置:unsaved-value,就像上面Product.hbm.xml中的設(shè)置那樣,這一項在id的配置中設(shè)置。這一設(shè)置是與級聯(lián)一起工作的。關(guān)于這一點,robbin講的很清楚:
    當(dāng)你顯式的使用session.save()或者session.update()操作一個對象的時候,實際上是用不到unsaved-value 的。某些情況下(父子表關(guān)聯(lián)保存),當(dāng)你在程序中并沒有顯式的使用save或者update一個持久對象,那么Hibernate需要判斷被操作的對象究竟是一個已經(jīng)持久化過的持久對象,是一個尚未被持久化過的內(nèi)存臨時對象。例如:
           Session session = ...;
    Transaction tx = ...;  
    Parent parent = (Parent) session.load(Parent.class, id);  
    Child child = new Child();  
    child.setParent(parent);  
    child.setName("sun");  
    parent.addChild(child);  
    s.update(parent);  
    s.flush();  
    tx.commit();  
    s.close();  
         在上例中,程序并沒有顯式的session.save(child); 那么Hibernate需要知道child究竟是一個臨時對象,還是已經(jīng)在數(shù)據(jù)庫中有的持久對象。如果child是一個新創(chuàng)建的臨時對象(本例中就是這種情況),那么Hibernate應(yīng)該自動產(chǎn)生session.save(child)這樣的操作,如果child是已經(jīng)在數(shù)據(jù)庫中有的持久對象,那么 Hibernate應(yīng)該自動產(chǎn)生session.update(child)這樣的操作。因此我們需要暗示一下Hibernate,究竟 child對象應(yīng)該對它自動save還是update。在上例中,顯然我們應(yīng)該暗示Hibernate對child自動save,而不是自動 update。那么Hibernate如何判斷究竟對child是save還是update呢?它會取一下child的主鍵屬性 child.getId() ,這里假設(shè)id是 java.lang.Integer類型的。如果取到的Id值和hbm映射文件中指定的unsave-value相等,那么Hibernate認(rèn)為 child是新的內(nèi)存臨時對象,發(fā)送save,如果不相等,那么Hibernate認(rèn)為child是已經(jīng)持久過的對象,發(fā)送update。unsaved-value="null" (默認(rèn)情況,適用于大多數(shù)對象類型主鍵 Integer/Long/String/...)
    當(dāng)Hibernate取一下child的Id,取出來的是null(在上例中肯定取出來的是null),和unsaved-value設(shè)定值相等,發(fā)送save(child)
    當(dāng)Hibernate取一下child的id,取出來的不是null,那么和unsaved-value設(shè)定值不相等,發(fā)送update(child)
       unsaved-value的可選配置有:
    none,any,null
    unsaved-value="none"和unsaved-value="any"主要用在主鍵屬性不是通過Hibernate生成,而是程序自己setId()的時候。unsaved-value="none"和unsaved-value="any"究竟有什么含義了。如果你非要用assigned不可,那么繼續(xù)解釋一下:
    unsaved-value="none" 的時候,由于不論主鍵屬性為任何值,都不可能為none,因此Hibernate總是對child對象發(fā)送update(child)
    unsaved-value="any" 的時候,由于不論主鍵屬性為任何值,都肯定為any,因此Hibernate總是對child對象發(fā)送save(child)
          大多數(shù)情況下,可以避免使用assigned,只有當(dāng)你使用復(fù)合主鍵的時候不得不手工setId(),這時候需要你自己考慮究竟怎么設(shè)置unsaved-value了,根據(jù)你自己的需要來定。
          關(guān)于為什么不要使主鍵帶有義務(wù)意義,robbin的解釋很清楚:還是以上面的例子打比方,如果我們將Category的某一個性質(zhì)(比如產(chǎn)品序號或者名稱)作為主鍵,如果后來由于業(yè)務(wù)需要,我們把這個性質(zhì)改了,那將不可僻免地要去修改與這個對象相關(guān)聯(lián)的所有數(shù)據(jù)的外鍵,而如果我們只要代理主鍵,這個問題就可完全僻免。


    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 亚洲国产高清美女在线观看| 国产成人综合久久精品免费| 日韩电影免费观看| 亚洲精品黄色视频在线观看免费资源 | 高清在线亚洲精品国产二区| 在线观看人成视频免费| 好男人看视频免费2019中文| 天天看免费高清影视| 女人被男人躁的女爽免费视频| 热久久精品免费视频| 亚洲日韩看片无码电影| 亚洲www77777| 亚洲youwu永久无码精品| 久久精品熟女亚洲av麻豆| 国产亚洲综合视频| 免费一级特黄特色大片| 一级中文字幕乱码免费| 久久精品成人免费观看97| 中文字幕成人免费高清在线| 成全高清在线观看免费| 免费看搞黄视频网站| 最近中文字幕完整版免费高清| 曰批视频免费30分钟成人| 四虎影院免费在线播放| 免费在线黄色网址| 亚洲国产美女精品久久久久∴| 亚洲好看的理论片电影| 亚洲乱码一二三四区国产| 亚洲AⅤ男人的天堂在线观看| 免费无码国产V片在线观看| 国产又黄又爽又大的免费视频| 成人爽a毛片免费| 亚洲成人免费电影| 午夜视频在线观看免费完整版| 免费一级毛片在级播放| 亚洲综合另类小说色区| 亚洲美女自拍视频| 亚洲av无码片vr一区二区三区| 国产成人无码精品久久久久免费 | 亚洲国产精品白丝在线观看| 亚洲午夜无码久久久久小说|