日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

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

發(fā)布時(shí)間:2025/6/15 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 hibernate 一对多(one-to-many)双向关联 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一對(duì)多(one-to-many)雙向關(guān)聯(lián)實(shí)例(Department- Employee)

這里的一對(duì)多雙向關(guān)聯(lián)是在域模型(實(shí)體對(duì)象模型)上的概念,在關(guān)系數(shù)據(jù)庫(kù)中,只存在外鍵參照關(guān)系,而且總是由"many"方參照"one"方,因?yàn)檫@樣才能消除冗余數(shù)據(jù),因上關(guān)系數(shù)據(jù)庫(kù)實(shí)際上只支持多對(duì)一或一對(duì)一的單向關(guān)聯(lián).在實(shí)體(類與類之間)各種各樣的關(guān)系中,數(shù)多對(duì)一的的單向關(guān)聯(lián)關(guān)系與數(shù)據(jù)庫(kù)中的外鍵參照關(guān)系最匹配了.

在我的前一篇文章多對(duì)一的基礎(chǔ)上進(jìn)行修改。

1.修改Department實(shí)體類:

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:設(shè)定待映射的持久化類的屬性名,這里為Depatment類的emps屬性.

    <set>元素的兩個(gè)子元素:

    <key>:設(shè)定與所關(guān)聯(lián)的持久化類對(duì)應(yīng)的表的外鍵,此處為Employee表的depart_id字段.

    <one-to-many>:設(shè)定所關(guān)聯(lián)的持久化類,此處為Employee.

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

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

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

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

    ?

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

    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);?//?對(duì)象模型:建立兩個(gè)對(duì)象的關(guān)聯(lián)???
  • ????????????employee1.setName("employee1?name2");??
  • ??????????????
  • ????????????Employee?employee2?=?new?Employee();??
  • ????????????employee2.setDepartment(depart);?//?對(duì)象模型:建立兩個(gè)對(duì)象的關(guān)聯(lián)???
  • ????????????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();??
  • ????????}??
  • ????}??
  • }??
  • ?控制臺(tái)打印信息如下:

    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

    數(shù)據(jù)庫(kù)中記錄如下所示:

    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)

    ?

    雖然對(duì)象模型修改了,但數(shù)據(jù)庫(kù)關(guān)系模型并沒(méi)有改變。

    ?

    如果把測(cè)試程序中注釋部分去掉,同時(shí)將注釋為“建立對(duì)象模型”這兩句程序注釋掉,雖然也能正確運(yùn)行,但控制臺(tái)會(huì)多打印出兩條更新語(yǔ)句,說(shuō)明數(shù)據(jù)庫(kù)多執(zhí)行了兩次更新操作,效率上有影響,如下所示:

    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)如果將程序中標(biāo)記為1的程序注釋掉,控制臺(tái)打印信息如下:

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

    此時(shí)只是將Department對(duì)象查詢出來(lái)了,而對(duì)應(yīng)的Employee并沒(méi)有進(jìn)行查詢。

    (2)如果將程序中標(biāo)記為1的程序注釋掉,同時(shí)將標(biāo)記為2的前面的注釋去掉,運(yùn)行程序,控制臺(tái)打印信息如下:

    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

    此時(shí)可以看到其實(shí)Hibernate將hashset替換成了它自己寫(xiě)的PersistentSet,所以才能實(shí)現(xiàn)懶加載功能。同時(shí)可以發(fā)現(xiàn)當(dāng)調(diào)用department.getEmps();hibernate只是獲取了集合代理對(duì)象的引用,它并沒(méi)有去查詢數(shù)據(jù)庫(kù)來(lái)填充集合對(duì)象。你還可以進(jìn)一步測(cè)試來(lái)驗(yàn)證這個(gè)問(wèn)題。如果你將程序中標(biāo)記為1的程序注釋掉,同時(shí)去掉標(biāo)記為3的語(yǔ)句前面的注釋,你會(huì)發(fā)現(xiàn)程序能正常運(yùn)行,但如果去掉標(biāo)記為4的語(yǔ)句前面的注釋,運(yùn)行程序,則會(huì)拋出如下異常:

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

    (3)當(dāng)進(jìn)行department對(duì)象查詢時(shí),從department的表結(jié)構(gòu)中也不能判斷這個(gè)Department對(duì)象是否有對(duì)應(yīng)的Employee,那為什么它不像一對(duì)一查詢時(shí),也一次性把相關(guān)聯(lián)的對(duì)象查詢出來(lái)呢??這是因?yàn)槿绻麑㈥P(guān)聯(lián)的對(duì)象查詢出來(lái)的話,因?yàn)閿?shù)據(jù)較多,它會(huì)嚴(yán)重影響效率,而不像一對(duì)一時(shí),反正從對(duì)象只有一個(gè),一次性查詢出來(lái)影響也不是太大,所以hibernate就假定你有相對(duì)應(yīng)的Employee,直接創(chuàng)建了一個(gè)集合代理對(duì)象的返回給你(把對(duì)象引用先給你),等你需要數(shù)據(jù)的時(shí)候再去查詢數(shù)據(jù)庫(kù),以提高效率!

    ?

    總結(jié)

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

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。