<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 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      30 隨筆 :: 19 文章 :: 0 評論 :: 0 Trackbacks

    構造這樣一個例子,在測試過程中來說明一些Hibernate的高級配置及其相關機制:
    有三個類: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("編程經典書籍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代表產品目錄,而Product代表產品,顯然Category與Product是一對多的關系。Hibernate在映射一對多關系時,有兩種方式,一種是單向一對多,一種是雙向關系。兩者相比,雙向一對多的好處體現在兩方面:首先,也是很明顯的一點,由于是雙向關聯,我們在實際業務邏輯時將更方便,例如我們可以檢索一個Category下的所有Product,同時還可以檢索出Product屬于哪個。其次,雙向關系相對單向關系而言,在數據庫的訪問方面更有優勢。這一點留在后面講inverse時講
    。雙向關聯比單向關聯唯一的”劣勢“,就在于雙向關聯需要比單向關聯多寫一個映射文件,這不問題。使用雙向關聯實現這兩個類同數據庫的映射:

    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>    
            
    現在把這個例子所牽涉到的知識一一展開:
    一.inverse
        該詞的譯意是“反轉”,反轉什么——反轉控制端,這項配置決定了由關聯雙方中的哪一方來維持關聯關系(在數據庫中表現為外鍵約束)。上述配置中,在Category.hbm.xml中將inverse設置為true,意思是說“我需要反轉(控制端)”,反轉的結果是由對方即Product來維持關聯關系。用單向關聯更容易說明”維持關聯關系“是什么意思:考慮用單向關系來實現這個映射關系的情況,即由Category關聯到Product,考慮下面的代碼:

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

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

    inverse=true時的打印結果:

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

    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時少執行一條SQL語句?這是由控制端的不同造成的。前者說"我要反轉控制,由Product來控制關聯",因此在將p對象insert時,p已經設置了其category字段,從而建立了關聯關系,而后者說"我不反轉控制,由我自己來控制關聯",因此在將p對象insert后,c為了維持兩者的關聯,還要去執行一次update,以更新p的外鍵,從而建立起兩者的關聯關系。
    結論:對于一對多雙向關系,始終在“一”那一方將其inverse設置成true,這樣會提高性能。

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

    三.lazy
        是否延遲加載。一般來說,應該延遲加載,即將lazy設為true。延遲加載的相關點很多,這在另外的學習筆記中總結。

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

    主站蜘蛛池模板: 四虎成人免费网址在线| 亚洲av纯肉无码精品动漫| 182tv免费观看在线视频| 日韩毛片免费一二三| 狠狠色香婷婷久久亚洲精品| 国产AV无码专区亚洲AV手机麻豆| 又黄又爽无遮挡免费视频| 四虎国产精品免费视| 亚洲国产精品高清久久久| 亚洲AV无码1区2区久久| 亚洲丶国产丶欧美一区二区三区 | 免费黄色毛片视频| 91手机看片国产永久免费| 国产又大又粗又长免费视频| 亚洲国产成人久久精品99 | 国产h肉在线视频免费观看| 亚洲香蕉免费有线视频| 亚洲精品老司机在线观看| 亚洲国产成人综合| 国产精品网站在线观看免费传媒| A片在线免费观看| 日韩伦理片电影在线免费观看| 亚洲国产成人久久综合一| 农村寡妇一级毛片免费看视频| 我们的2018在线观看免费高清| 狠狠亚洲婷婷综合色香五月排名| 亚洲无码一区二区三区| 国产亚洲日韩在线a不卡| 综合在线免费视频| 亚洲av网址在线观看| 中文在线免费不卡视频| 亚洲国产精品碰碰| 在线观看亚洲免费| 精品免费国产一区二区| 亚洲国产精品yw在线观看| 青青草无码免费一二三区| 亚洲精品国产成人片| 抽搐一进一出gif免费视频| 亚洲一级特黄大片在线观看| 无码久久精品国产亚洲Av影片| 一个人看www免费高清字幕|