日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Hibernate中inverse属性与cascade属性

發布時間:2023/12/10 编程问答 52 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Hibernate中inverse属性与cascade属性 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Hibernate集合映射中,經常會使用到"inverse"和"cascade"這兩個屬性。對于我這樣,Hibernate接觸不深和語文水平夠爛的種種因素,發現這兩個屬性實在是難以理解,無奈只好將這個兩個屬性解釋工作交給了Google和Baidu,查看了許多牛人的解釋,加上自己在Eclipse上的調試,對"inverse"和"cascade"這兩個屬性有了一定的見解。

???"inverse"屬性探究

???"inverse"-直譯過來就是"反轉,使顛倒"的意思,書面化的解釋為"是否將關系維護的權力交給對方"(這個解釋真夠蛋疼的-_-!!,就是理解不了)。 Hibernate中的"inverse"屬性只有兩個值"true"和"false"。"true"表示將關系維護的權力交給對方,"false"表示不交出維護權力(默認值)。

???例如有兩張表,customer和orders,他們的關系是一對多,customer是一方,orders為多方。

  • ???drop?table?if?exists?customer; ?
  • ???drop?table?if?exists?orders; ?
  • ???create?table?customer ?
  • ???( ?
  • ???????id?varchar(255)?not?null, ?
  • ???????username?varchar(255), ?
  • ???????password?varchar(255), ?
  • ???????age?integer, ?
  • ???????register_time?datetime, ?
  • ???????primary?key?(id) ?
  • ???); ?
  • ???create?table?orders ?
  • ???( ?
  • ???????id?varchar(255)?not?null, ?
  • ???????orderNumber?varchar(255), ?
  • ???????balance?integer, ?
  • ???????customer_id?varchar(255), ?
  • ???????primary?key?(id) ?
  • ???);?
  • ???兩表對應的hbm文件,對應的POJO類:

    ? ? ? ? ? ? ? ? ? ?/*customer表對應的POJO類*/?

    ? ? ? ? ? ? ? ? ? ? public?class?Customer ?

          ? ?{ ?

          ? ? ? ?private?String?id; ?

    ?       ? ? ?private?String?username; ?

           ? ? ? private?String?password; ?

             ?private?Timestamp?registerTime; ?

    ? ? ? ? ? ? ? ? ? ? ? ? ?private?int?age;?

             ??private?Set<Order>?orders?=?new?HashSet<Order>();

             public?Customer() { ?

              ?} ?

  • ???????/*get?and?set?method*/?
  • ?} ?
  • ?

  • ???/*orders表對應的POJO類*/?
  • ?

  • ???public?class?Order ?
  • ???{ ?
  • ???????private?String?id; ?
  • ???????private?String?orderNumber; ?
  • ???????private?int?balance; ?
  • ???????private?Customer?customer; ?
  • ???????public?Order() ?
  • ???????{ ?
  • ?

  • ???????} ?
  • ???????/*?get?and?set?method*/?
  • ?

  • ???}?
  • ???

    ?

  • ???<!--Customer類的hbm文件--> ?
  • ???????<hibernate-mapping> ?
  • ???????????<class?name="com.suxiaolei.hibernate.pojos.Customer"?table="customer"> ?
  • ???????????????<id?name="id"?type="string"> ?
  • ???????????????????<column?name="id"></column> ?
  • ???????????????????<generator?class="uuid"></generator> ?
  • ???????????????</id> ?
  • ???????????????<property?name="username"?column="username"?type="string"></property> ?
  • ???????????????<property?name="password"?column="password"?type="string"></property> ?
  • ???????????????<property?name="age"?column="age"?type="integer"></property> ?
  • ???????????????<property?name="registerTime"?column="register_time"?type="timestamp"></property> ?
  • ?

  • ???????????????<set?name="orders"?inverse="true"?cascade="all"> ?
  • ???????????????????<key?column="customer_id"?></key> ?
  • ???????????????????<one-to-many?class="com.suxiaolei.hibernate.pojos.Order"/> ?
  • ???????????????</set> ?
  • ???????????</class> ?
  • ???????</hibernate-mapping> ?
  • ???<!--Order類的hbm文件--> ?
  • ???????<hibernate-mapping> ?
  • ???????????<class?name="com.suxiaolei.hibernate.pojos.Order"?table="orders"> ?
  • ???????????????<id?name="id"?type="string"> ?
  • ???????????????????<column?name="id"></column> ?
  • ???????????????????<generator?class="uuid"></generator> ?
  • ???????????????</id> ?
  • ???????????????<property?name="orderNumber"?column="orderNumber"?type="string"></property> ?
  • ???????????????<property?name="balance"?column="balance"?type="integer"></property> ?
  • ???????????????<many-to-one?name="customer"?class="com.suxiaolei.hibernate.pojos.Customer"> ?
  • ???????????????????<column?name="customer_id"></column> ?
  • ???????????????</many-to-one> ? ? ? ? ?
  • ???????????</class> ?
  • ?</hibernate-mapping>
  • 下面寫一些測試代碼測試"inverse"屬性的特性:

    ???情況一:將"inverse"設置為true,讓多方維護關系

  • ?try?
  • ???{ ?
  • ???????tx?=?session.beginTransaction(); ?
  • ???????/* ?
  • ????????*?創建Customer對象,并設置其屬性值 ?
  • ????????*/?
  • ???????Customer?customer?=?new?Customer(); ?
  • ???????customer.setUsername("zhangsan"); ?
  • ???????customer.setPassword("123456"); ?
  • ???????customer.setAge(22); ?
  • ???????customer.setRegisterTime(new?Timestamp(new?Date().getTime()));?
  • ???????/* ?
  • ????????*?創建Order對象order1,并設置其屬性值 ?
  • ????????*/?
  • ???????Order?order1?=?new?Order(); ?
  • ???????order1.setOrderNumber("a1a2a3"); ?
  • ???????order1.setBalance(1000); ?
  • ???????order1.setCustomer(customer);//將customer對象關聯到order1對象上 ?
  • ???????/* ?
  • ????????*?創建Order對象order2,并設置其屬性值 ?
  • ????????*/?
  • ???????Order?order2?=?new?Order(); ?
  • ???????order2.setOrderNumber("d3d2d1"); ?
  • ???????order2.setBalance(670); ?
  • ???????order2.setCustomer(customer);///將customer對象關聯到order2對象上 ?
  • ?             customer.getOrders().add(order1);//將order1對象關聯到customer對象上 ?

  • ???????customer.getOrders().add(order2);//將order2對象關聯到customer對象上 ?
  • ???????session.saveOrUpdate(customer); ?
  • ???????tx.commit(); ?
  • ???} ??catch?(Exception?e) ?{ ?
  • ???????if(tx?!=?null) ?
  • ???????{ ?
  • ???????????tx.rollback(); ?
  • ???????} ?
  • ???????e.printStackTrace(); ?
  • ???} ?
  • ???finally?
  • ???{ ?
  • ???????session.close(); ?
  • }?
  • ???數據庫中的數據更新為:

    ???customer表:?

    ???

    ???orders表:

    ???

    ???現在將order1.setCustomer(customer);這段代碼注釋掉,再次運行程序:

    ???customer表:

    ???

    ???orders表:

    ???

    ???可以到看到顯著地差別了,第一次保存"id"="402881e534ea7c750134ea7c76bc0001"的數據時,orders表中插入了兩條數據,他們的customer_id都為customer中對應記錄的主鍵值,而第二次保存記錄"id"="402881e534ea81be0134ea81bfea0001"的數據時,由于先前將原來的代碼段order1.setCustomer(customer);注釋掉了,此時order表中插入的數據中order1代表的那條記錄沒有customer_id值。

    ?從以上現象可以有助于理解"inverse"這個屬性。首先,"inverse"控制關系維護權力,那么什么是"關系"?,關系的具體體現是什么?在以上例子中,"關系"就是兩個表之間的關系,通常為"一對多","一對一","多對多"三種關系,而關系的具體體現為orders表中的 customer_id列,而"inverse"屬性就是告訴Hibernate哪一方有權力管理和維護這一列。上面的例子將"inverse"設置為 true那么customer_id這一列由多方(order對象)維護。這說明了,只有order對象對關系的操作會反映到數據庫中。(對象對關系的操作就是對關聯屬性的操作,例如order對象對自身的"customer"屬性操作,customer對象對自身的orders集合(Set<Order>)操作)

    ???例如,將id="402881e534ea7c750134ea7c76bc0001"的customer對象從數據庫中取出,獲取到該customer對象所關聯的order對象集合,將該customer對象所關聯的order對象刪除。

  • ???Customer?customer?=?(Customer)session.get(Customer.class,?"402881e534ea7c750134ea7c76bc0001"); ?
  • ???Order?order?=?(Order)session.get(Order.class,?"402881e534ea7c750134ea7c76ce0002"); ?
  • ???System.out.println("customer?association?order?count:"+customer.getOrders().size()); ?
  • ???customer.getOrders().remove(order); ?
  • ???System.out.println("customer?association?order?count:"+customer.getOrders().size()); ?
  • ???session.saveOrUpdate(customer);?
  • ???//Console Output:

    ???customer association order count:2
    customer association order count:1

    ???可以看到customer中關聯的order對象集合確實有對象被刪除了,若操作有效,表示該order對象與customer對象沒有關系了,反映到數據庫中應該將該order對象對應的customer_id設置為null。現在查看一下數據庫數據:

    ???

    ???看到了吧,剛剛那個操作就是個無用操作,不會反應到數據庫中。我們修改一下程序代碼:

  • ???Customer?customer?=?(Customer)session.get(Customer.class,?"402881e534ea7c750134ea7c76bc0001"); ?
  • ???Order?order?=?(Order)session.get(Order.class,?"402881e534ea7c750134ea7c76ce0002"); ?
  • ???order.setCustomer(null); ?
  • ???session.saveOrUpdate(customer);?
  • ???這次我們使用order對象來操作關系,將該order對象與customer對象脫離關系,若操作有效,則反映在數據庫中應該是該order對象的customer_id字段的值變成null,現在查看一下數據庫:

    ???

    ???可以看到,此次操作成功的反映到了數據庫中了。

    ???情況二:將"inverse"屬性設置為"false",雙方都維護關系(因為沒有一方交出權力,"inverse"的默認值為"false",而且"inverse"屬性只能在set、list、map等幾個標簽中設置,像many-to-one這一類的標簽都不能設置"inverse"這個屬性值,它們只能取值"false")

    ???這里會產生書中所說的性能問題(囧,這個也是理解了很久很久),這個不管怎么說你都可能理解不了,我就是這樣的(-_-!!),所以我建議使用第三方的軟件將Hibernate輸出的SQL語句的綁定值顯示出來(可以參考這里)。之所以會產生性能為題,當你操作關系是會無故多產生一些update語句,比如你使用上面的例子保存一個customer對象,它關聯了2個order對象,它不但會生成3條insert語句(用于插入數據),還會生成2條update語句(將關聯的order對象的customer_id更新為自己的主鍵值),你想想要是一個customer對象包含幾萬了order對象(購物狂),那么每次保存它得要多生成幾萬條update語句,這個就是很嚴重的性能問題了。

    ???為什么Hibernate會產生update語句呢?那是Hibernate太主動,太熱情,太負責的表現,它怕你出現錯誤,例如有幾萬個order對象需要關聯到customer對象上,這就需要調用order.setCustomer(customer);,幾萬個對象這不是人可以不放錯的完成的。所以Hibernate怕你出錯忘記調用這個方法,所以他將會在order對象保存完畢后將所有關聯對象的customer_id字段更新一遍,確保正確性,這樣也就產生上面的性能問題。

    ???將"inverse"設置為false后,你可以嘗試設置order1.setCustomer(null),它依然會正確的將customer的主鍵值完美的插入到order的customer_id字段上,只是會多一條update語句。

    ???"cascade"屬性

    ???"cascade"-直譯過來就是"級聯、串聯"的意思,書面化的解釋為"該屬性會使我們在操作主對象時,同時Hibernate幫助我們完成從屬對象相應的操作(比如,有Customer和Order這兩張表,關系為一對多,只使用JDBC刪除Customer表中的一行記錄時,我們還需要手動的將Order表中與之關聯的記錄全都刪除,使用Hibernate的'cascade'屬性后,當我們刪除一條Customer記錄時,Hibernate會幫助我們完成相應Order表記錄的刪除工作,方便了我們的工作)"。

    ???總 結

    ???使用"inverse"這個屬性時,要考慮清楚關系,不然你的系統就會有大的性能問題,書本上和一些牛人建議,關系一般由"多方"維護,當遇到"多對多"時怎么辦,其實多對多久是兩個"一對多",隨意設置一方"inverse"為"true"就可以了,不要兩方都設置或都不設置(囧,我開始就是死板這樣的設置)。而是用"cascade"屬性時,主對象(一方)一般設置為"all",而多方不建議設置包含delete操作的選項,建議設置多方為"save-update",這是因為你刪除一方,多方已經沒有存在的意義了,而刪除多方不能代表一方沒意義了(例如,消費者和訂單)。最后,"cascade"操作的是兩張表的記錄或兩端的對象,而"inverse"操作的是兩張表的關系或兩個對象的關系。

    轉載于:https://www.cnblogs.com/suding1188/archive/2013/01/04/2844575.html

    總結

    以上是生活随笔為你收集整理的Hibernate中inverse属性与cascade属性的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。