hibernate 多对一(Many-to-one)单向关联
多對(duì)一實(shí)例(Employee-Department)
1. E-R圖:
2. 實(shí)體類:
Department類:
Java代碼 ??Employee類:
Java代碼 ??3. 實(shí)體映射文件:
Department.hbm.xml如下:
Xml代碼 ??Employee.hbm.xml如下:
Xml代碼 ??<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代碼 ??4. 測(cè)試:
Java代碼 ??運(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代碼 ??調(diào)換測(cè)試類兩句程序的順序,如下所示:
?
Java代碼 ?則控制臺(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
這句話很重要,如果沒有這句話,則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代碼 ??測(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代碼 ?否則,就不初始化代理對(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)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Hibernate4多对多关系映射
- 下一篇: hibernate 一对多(one-to