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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

hibernate 一对多(one-to-many)双向关联

發布時間:2025/6/15 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 hibernate 一对多(one-to-many)双向关联 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一對多(one-to-many)雙向關聯實例(Department- Employee)

這里的一對多雙向關聯是在域模型(實體對象模型)上的概念,在關系數據庫中,只存在外鍵參照關系,而且總是由"many"方參照"one"方,因為這樣才能消除冗余數據,因上關系數據庫實際上只支持多對一或一對一的單向關聯.在實體(類與類之間)各種各樣的關系中,數多對一的的單向關聯關系與數據庫中的外鍵參照關系最匹配了.

在我的前一篇文章多對一的基礎上進行修改。

1.修改Department實體類:

Java代碼 ?
  • package?com.reiyen.hibernate.domain??
  • public?class?Department?{??
  • ??
  • ????private?int?id;??
  • ????private?String?name;??
  • ????private?Set<Employee>?emps;???
  • ??
  •    //setter和getter方法??
  • }??
  • ?2.修改Department.hbm.xml文件:

    Xml代碼 ?
  • <?xml?version="1.0"?>??
  • <!DOCTYPE?hibernate-mapping?PUBLIC???
  • ????"-//Hibernate/Hibernate?Mapping?DTD?3.0//EN"??
  • ????"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">??
  • <hibernate-mapping?package="com.reiyen.hibernate.domain">??
  • ????<class?name="Department"?>??
  • ????????<id?name="id"?>??
  • ????????????<generator?class="native"?/>??
  • ????????</id>??
  • ????????<property?name="name"?/>??
  • ????????<set?name="emps">??
  • ????????<key?column="depart_id"?/>??
  • ????????<one-to-many?class="Employee"/>??
  • ????????</set>??
  • ????</class>??
  • </hibernate-mapping>??
  • <set>元素的屬性name:設定待映射的持久化類的屬性名,這里為Depatment類的emps屬性.

    <set>元素的兩個子元素:

    <key>:設定與所關聯的持久化類對應的表的外鍵,此處為Employee表的depart_id字段.

    <one-to-many>:設定所關聯的持久化類,此處為Employee.

    Hibernate根椐以上配置信息獲得如下信息:

    <set>元素表明Department類的emps屬性為java.util.Set集合類型.

    <class>子元素表明emps集合中存放的是一組Employee對象

    <key>子元素表明employee表是通過外鍵depart_id參照department表的.

    ?

    ?3. 其余的保持原樣,測試類如下:

    Java代碼 ?
  • public?class?Many2One?{??
  • ??
  • ????/**?
  • ?????*?@param?args?
  • ?????*/??
  • ????public?static?void?main(String[]?args)?{??
  • ????????Department?depart?=?add();??
  • ????????Department?department?=?queryDepart(depart.getId());??
  • ????????????????//department.getEmps();3??
  • //?System.out.println("emp?size:"?+?department.getEmps().size());4????
  • ????}??
  • ??
  • ????static?Department?queryDepart(int?departId)?{??
  • ????????Session?s?=?null;??
  • ????????Transaction?tx?=?null;??
  • ????????try?{??
  • ????????????s?=?HibernateUtil.getSession();??
  • ????????????tx?=?s.beginTransaction();??
  • ????????????Department?depart?=?(Department)?s.get(Department.class,?departId);??
  • ?????????????System.out.println("emp?size:"?+?depart.getEmps().size());//1????????
  • ?????????????????????????//?System.out.println("emps?class:"?+?depart.getEmps().getClass());???//2???
  • ?????????????????????????//?Hibernate.initialize(depart.getEmps());??
  • ????????????tx.commit();??
  • ????????????return?depart;??
  • ????????}?finally?{??
  • ????????????if?(s?!=?null)??
  • ????????????????s.close();??
  • ????????}??
  • ????}??
  • ??
  • ????static?Department?add()?{??
  • ????????Session?s?=?null;??
  • ????????Transaction?tx?=?null;??
  • ????????try?{??
  • ????????????Department?depart?=?new?Department();??
  • ????????????depart.setName("department?name");??
  • ??????????????
  • ????????????Employee?employee1?=?new?Employee();??
  • ????????????employee1.setDepartment(depart);?//?對象模型:建立兩個對象的關聯???
  • ????????????employee1.setName("employee1?name2");??
  • ??????????????
  • ????????????Employee?employee2?=?new?Employee();??
  • ????????????employee2.setDepartment(depart);?//?對象模型:建立兩個對象的關聯???
  • ????????????employee2.setName("employee2?name2");??
  • ??
  •        // Set<Employee>?set?=?new?HashSet<Employee>();??
  • ????????????//????set.add(employee1);??
  • ????????????//??set.add(employee2);??
  • ????????????//??depart.setEmps(set);??
  • ??????????????
  • ????????????s?=?HibernateUtil.getSession();??
  • ????????????tx?=?s.beginTransaction();??
  • ????????????s.save(depart);??
  • ????????????s.save(employee1);??
  • ????????????s.save(employee2);??
  • ????????????tx.commit();??
  • ????????????return?depart;??
  • ????????}?finally?{??
  • ????????????if?(s?!=?null)??
  • ????????????????s.close();??
  • ????????}??
  • ????}??
  • }??
  • ?控制臺打印信息如下:

    Hibernate: insert into Department (name) values (?)
    Hibernate: insert into Employee (name, depart_id) values (?, ?)
    Hibernate: insert into Employee (name, depart_id) values (?, ?)
    Hibernate: select department0_.id as id1_0_, department0_.name as name1_0_ from Department department0_ where department0_.id=?
    Hibernate: select emps0_.depart_id as depart3_1_, emps0_.id as id1_, emps0_.id as id2_0_, emps0_.name as name2_0_, emps0_.depart_id as depart3_2_0_ from Employee emps0_ where emps0_.depart_id=?

    emp size:2

    數據庫中記錄如下所示:

    mysql> select * from employee;
    +----+-----------------+-----------+
    | id | name??????????? | depart_id |
    +----+-----------------+-----------+
    |? 1 | employee1 name2 |???????? 1 |
    |? 2 | employee2 name2 |???????? 1 |
    +----+-----------------+-----------+
    2 rows in set (0.00 sec)

    mysql> select * from department;
    +----+-----------------+
    | id | name??????????? |
    +----+-----------------+
    |? 1 | department name |
    +----+-----------------+
    1 row in set (0.00 sec)

    ?

    雖然對象模型修改了,但數據庫關系模型并沒有改變。

    ?

    如果把測試程序中注釋部分去掉,同時將注釋為“建立對象模型”這兩句程序注釋掉,雖然也能正確運行,但控制臺會多打印出兩條更新語句,說明數據庫多執行了兩次更新操作,效率上有影響,如下所示:

    Hibernate: insert into Department (name) values (?)
    Hibernate: insert into Employee (name, depart_id) values (?, ?)
    Hibernate: insert into Employee (name, depart_id) values (?, ?)
    Hibernate: update Employee set depart_id=? where id=?
    Hibernate: update Employee set depart_id=? where id=?

    Hibernate: select department0_.id as id1_0_, department0_.name as name1_0_ from Department department0_ where department0_.id=?
    Hibernate: select emps0_.depart_id as depart3_1_, emps0_.id as id1_, emps0_.id as id2_0_, emps0_.name as name2_0_, emps0_.depart_id as depart3_2_0_ from Employee emps0_ where emps0_.depart_id=?
    emp size:2

    ?

    4.懶加載分析:

    (1)如果將程序中標記為1的程序注釋掉,控制臺打印信息如下:

    Hibernate: select department0_.id as id0_0_, department0_.name as name0_0_ from Department department0_ where department0_.id=?

    此時只是將Department對象查詢出來了,而對應的Employee并沒有進行查詢。

    (2)如果將程序中標記為1的程序注釋掉,同時將標記為2的前面的注釋去掉,運行程序,控制臺打印信息如下:

    Hibernate: select department0_.id as id0_0_, department0_.name as name0_0_ from Department department0_ where department0_.id=?
    emps class:class org.hibernate.collection.PersistentSet

    此時可以看到其實Hibernate將hashset替換成了它自己寫的PersistentSet,所以才能實現懶加載功能。同時可以發現當調用department.getEmps();hibernate只是獲取了集合代理對象的引用,它并沒有去查詢數據庫來填充集合對象。你還可以進一步測試來驗證這個問題。如果你將程序中標記為1的程序注釋掉,同時去掉標記為3的語句前面的注釋,你會發現程序能正常運行,但如果去掉標記為4的語句前面的注釋,運行程序,則會拋出如下異常:

    ?org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.reiyen.hibernate.domain.Department.emps, no session or session was closed

    (3)當進行department對象查詢時,從department的表結構中也不能判斷這個Department對象是否有對應的Employee,那為什么它不像一對一查詢時,也一次性把相關聯的對象查詢出來呢??這是因為如果將關聯的對象查詢出來的話,因為數據較多,它會嚴重影響效率,而不像一對一時,反正從對象只有一個,一次性查詢出來影響也不是太大,所以hibernate就假定你有相對應的Employee,直接創建了一個集合代理對象的返回給你(把對象引用先給你),等你需要數據的時候再去查詢數據庫,以提高效率!

    ?

    總結

    以上是生活随笔為你收集整理的hibernate 一对多(one-to-many)双向关联的全部內容,希望文章能夠幫你解決所遇到的問題。

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