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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

hibernate 多对一(Many-to-one)单向关联

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

多對(duì)一實(shí)例(Employee-Department)

1. E-R圖:

2. 實(shí)體類:

Department類:

Java代碼 ?
  • package?com.reiyen.hibernate.domain??
  • ????public?class?Department?{??
  • ??
  • ????????private?int?id;??
  • ????????private?String?name;??
  • ??????????//setter和getter方法....??
  • ????}??
  • ?

    ?Employee類:

    Java代碼 ?
  • ??????package?com.reiyen.hibernate.domain??
  • public?class?Employee?{??
  • ??
  • ????private?int?id;??
  • ????private?String?name;??
  • ????private?Department?department;??
  • ????//setter和getter方法??
  • }??
  • ?

    ?3. 實(shí)體映射文件:

    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"?/>??
  • ????????</class>??
  • ????</hibernate-mapping>??
  • ?

    ?Employee.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="Employee">??
  • ????????????<id?name="id">??
  • ????????????????<generator?class="native"?/>??
  • ????????????</id>??
  • ????????????<property?name="name"?/>??
  • ????????????<!--?name="department"?這個(gè)名稱必須與Employee中的屬性名一致.?-->??
  • ????????????<many-to-one?name="department"?column="depart_id"?class="Department"?/>??
  • ????????</class>??
  • ????</hibernate-mapping>??
  • ?

    ?<many-to-one name=”department” column=”depart_id” />這種缺省情況,
    hibernate會(huì)默認(rèn)去department對(duì)象中查找主鍵值,因?yàn)閔ibernate默認(rèn)的是外鍵對(duì)應(yīng)另一個(gè)表中的主鍵的,
    如果想對(duì)應(yīng)department中的其它屬性,如”name”,則可以使用<many-to-one name=”department” column=”depart_id” property-ref=”name”/>也可以使用<many-to-one name=”department” />,這與 <many-to-one name=”depart” column=”depart_id” />的唯一區(qū)別就是它的column名也為department了,而不是depart_id.

    <many-to-one >元素建立了department屬性和employee表的外鍵depart_id之間的映射.

    name: 設(shè)定待映射的持久化類的屬性名,此外為employee類的department屬性.

    column: 設(shè)定和持久化類的屬性對(duì)應(yīng)的表的外鍵,此外為employee表的外鍵depart_id.

    class(可選):設(shè)定持久化類的屬性的類型,此處設(shè)定department的類型是Department類.

    not-null(可選):如果為true,表示department屬性不能為null,該屬性的默認(rèn)值為false.當(dāng)為true時(shí),生成的employee表中depart_id外鍵會(huì)設(shè)置not-null約束,所以當(dāng)Hibernate保存Employee對(duì)象時(shí),會(huì)先檢查它的department屬性是否為null,如果為null,則會(huì)拋出異常.

    3. 將兩個(gè)實(shí)體映射文件在hibernate.cfg.xml配置文件中注冊(cè):(hibernate.cfg.xml在我一篇文章:第一個(gè)Hibernate實(shí)例中有)

    Xml代碼 ?
  • <mapping?resource="com/reiyen/hibernate/domain/Department.hbm.xml"?/>??
  • <mapping?resource="com/reiyen/hibernate/domain/Employee.hbm.xml"?/>??
  • ?4. 測(cè)試:

    Java代碼 ?
  • public?class?Many2One?{??
  • public?static?void?main(String[]?args)?{??
  • ????????Department?depart?=?add();??
  • ????????System.out.println("depart?name:?"?+?depart.getName());??
  • ????}??
  • static?Department?add()?{??
  • ????????Session?s?=?null;??
  • ????????Transaction?tx?=?null;??
  • ????????try?{??
  • ????????????Department?depart?=?new?Department();??
  • ????????????depart.setName("department?name");??
  • ????????????Employee?employee?=?new?Employee();??
  • ???????????????employee.setDepartment(depart);?//?對(duì)象模型:建立兩個(gè)對(duì)象的關(guān)聯(lián)??
  • ???????????????????????employee.setName("employee?name");??
  • ????????????s?=?HibernateUtil.getSession();??
  • ????????????tx?=?s.beginTransaction();??
  • ????????????s.save(depart);??
  • ????????????????????s.save(employee);??
  • ????????????tx.commit();??
  • ????????????return?depart;??
  • ????????}?finally?{??
  • ????????????if?(s?!=?null)??
  • ????????????????s.close();??
  • ????????}??
  • ????}??
  • }??
  • ?運(yùn)行后,控制臺(tái)打印信息如下:

    Hibernate: insert into Department (name) values (?)
    Hibernate: insert into Employee (name, depart_id) values (?, ?)
    depart name: department name

    查看Employee數(shù)據(jù)庫表的創(chuàng)建語句如下:(注意紅色部分)

    ??? DROP TABLE IF EXISTS `test`.`employee`;
    ??? CREATE TABLE? `test`.`employee` (
    ??? ? `id` int(11) NOT NULL AUTO_INCREMENT,
    ??? ? `name` varchar(255) DEFAULT NULL,
    ??? ? `depart_id` int(11) DEFAULT NULL,
    ??? ? PRIMARY KEY (`id`),
    ??? ? KEY `FK4AFD4ACEA3E9AC0F` (`depart_id`),
    ??? ? CONSTRAINT `FK4AFD4ACEA3E9AC0F` FOREIGN KEY (`depart_id`) REFERENCES `department` (`id`))
    ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

    ?表中插入記錄如下:

    Sql代碼 ?
  • mysql>?select?*?from?employee;??
  • +----+---------------+-----------+??
  • |?id?|?name??????????|?depart_id?|??
  • +----+---------------+-----------+??
  • |??1?|?employee?name?|?????????1?|??
  • +----+---------------+-----------+??
  • 1?row?in?set?(0.00?sec)??
  • ??
  • mysql>?select?*?from?department;??
  • +----+-----------------+??
  • |?id?|?name????????????|??
  • +----+-----------------+??
  • |??1?|?department?name?|??
  • +----+-----------------+??
  • 1?row?in?set?(0.00?sec)??
  • ?調(diào)換測(cè)試類兩句程序的順序,如下所示:

    ?

    Java代碼 ?
  • s.save(employee);??
  • s.save(depart);??
  • 則控制臺(tái)的信息如下所示:(多了一條更新語句)

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

    Java代碼 ?
  • employee.setDepartment(depart);?//?對(duì)象模型:建立兩個(gè)對(duì)象的關(guān)聯(lián)??
  • 這句話很重要,如果沒有這句話,則Department和Employee之間就沒有任何關(guān)系了。

    如果你在Employee.hbm.xml中配置了

    <many-to-one name="department" column="depart_id" not-null="true"/>

    則必須先保存department再保存employee,否則會(huì)拋出:

    org.hibernate.PropertyValueException: not-null property references a null or transient value異常!

    查詢測(cè)試:

    Java代碼 ?
  • public?class?Many2One?{??
  • ????public?static?void?main(String[]?args)?{??
  • ????????Department?depart?=?add();??
  • ????????Employee?employee?=?query(1);??
  • ????????//?System.out.println("depart?name:"?+?employee.getDepartment().getName());?//?2??
  • ????}??
  • ??
  • ????static?Employee?query(int?empId)?{??
  • ????????Session?s?=?null;??
  • ????????Transaction?tx?=?null;??
  • ????????try?{??
  • ????????????s?=?HibernateUtil.getSession();??
  • ????????????tx?=?s.beginTransaction();??
  • ????????????Employee?emp?=?(Employee)?s.get(Employee.class,?empId);??
  • ????????????System.out.println("depart?name:"?+?emp.getDepartment().getName());?//?1??
  • ??????????????//?System.out.println("depart?class:"?+?emp.getDepartment().getClass());?//?4???
  • ?????????????//System.out.println("depart?id:"?+?emp.getDepartment().getId());??//5???????
  • ????????????//?Hibernate.initialize(emp.getDepartment());?//?3??
  • ????????????tx.commit();??
  • ????????????return?emp;??
  • ????????}?finally?{??
  • ????????????if?(s?!=?null)??
  • ????????????????s.close();??
  • ????????}??
  • ????}??
  • }??
  • ?測(cè)試程序運(yùn)行后,控制臺(tái)打印出的sql如下:
    Hibernate: select employee0_.id as id2_0_, employee0_.name as name2_0_, employee0_.depart_id as depart3_2_0_ from Employee employee0_ where employee0_.id=?
    Hibernate: select department0_.id as id1_0_, department0_.name as name1_0_ from Department department0_ where department0_.id=?

    depart? name:department name

    當(dāng)相關(guān)聯(lián)的session沒有關(guān)閉時(shí),訪問這些懶加載對(duì)象(代理對(duì)象)的屬性(getId和getClass除外)時(shí),hibernate會(huì)初始化這些代理,所以將Employee對(duì)象和Department對(duì)象都查詢出來了。相當(dāng)于在數(shù)據(jù)庫中執(zhí)行兩次查詢:
    首先執(zhí)行select * from employee where employee.id = ?
    然后再執(zhí)行select * from department where department.id = ?

    ?

    如果將測(cè)試程序中標(biāo)記為2的語句前的注釋去掉,同時(shí)把標(biāo)記為1的語句注釋掉,再運(yùn)行剛會(huì)出現(xiàn)如下所示的異常:

    org.hibernate.LazyInitializationException: could not initialize proxy - no Session

    解決辦法是把標(biāo)記為3的語句前的注釋去掉,即初始化懶加載的代理對(duì)象。(可以給query方法再傳遞一個(gè)參數(shù),如boolean isInit,如果是true的話就初始化代理對(duì)象,即調(diào)用

    Java代碼 ?
  • Hibernate.initialize(emp.getDepartment())??
  • 否則,就不初始化代理對(duì)象)。

    ?

    5.懶加載說明:

    many-to-one(元素)懶加載:1).lazy!=false 2).fetch=select

    能夠懶加載的對(duì)象都是被改寫過的代理對(duì)象,當(dāng)相關(guān)聯(lián)的session沒有關(guān)閉時(shí),訪問這些懶加載對(duì)象(代理對(duì)象)的屬性(getId和getClass除外)時(shí),hibernate會(huì)初始化這些代理,或用Hibernate.initialize(proxy)來初始化代理對(duì)象;
    當(dāng)相關(guān)聯(lián)的session關(guān)閉后,再訪問懶加載的對(duì)象將會(huì)出現(xiàn)異常。

    (1)把標(biāo)記為1的語句注釋掉,同時(shí)去掉標(biāo)記為4的語句前面的注釋,進(jìn)行測(cè)試,控制臺(tái)打印信息如下所示:

    Hibernate: select employee0_.id as id1_0_, employee0_.name as name1_0_, employee0_.depart_id as depart3_1_0_ from Employee employee0_ where employee0_.id=?
    depart class:class com.itcast.hibernate.domain.Department$$EnhancerByCGLIB$$b412e7fa

    說明實(shí)現(xiàn)了懶加載,它只查詢出Employee對(duì)象,而沒有去查詢相應(yīng)的Department對(duì)象;同時(shí)可以看出,返回的是改寫過的代理對(duì)象,而不是實(shí)體類Department.

    (2)把標(biāo)記為1的語句注釋掉,同時(shí)去掉標(biāo)記為5的語句前面的注釋,進(jìn)行測(cè)試,控制臺(tái)打印信息如下所示:

    Hibernate: select employee0_.id as id1_0_, employee0_.name as name1_0_, employee0_.depart_id as depart3_1_0_ from Employee employee0_ where employee0_.id=?
    depart id:1

    當(dāng)相關(guān)聯(lián)的session沒有關(guān)閉時(shí),訪問這些懶加載對(duì)象(代理對(duì)象)getId和getClass屬性,hibernate不會(huì)初始化這些代理。

    總結(jié)

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

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