Hibernate的一對多關聯實例
??????
??????我的例子是一個全國省和市的數據表,省為一個表,市為一個表,所使用的數據庫是MySQL 4.1.11。表的結構如下:
?1
CREATE
?
TABLE
?
IF
?
NOT
?
EXISTS
?Province
?2
(
?3
???Guid???????????????????????????
INT
????????????????????????????
NOT
?
NULL
?AUTO_INCREMENT,
?4
???Provincename???????????????????
VARCHAR
(
16
)????????????????????
NOT
?
NULL
,
?5
???
PRIMARY
?
KEY
?(Guid)
?6
)?TYPE
=
InnoDB;
?7
?8
CREATE
?
TABLE
?
IF
?
NOT
?
EXISTS
?City
?9
(
10
???Guid???????????????????????????
INT
????????????????????????????
NOT
?
NULL
?AUTO_INCREMENT,
11
???Cityname???????????????????????
VARCHAR
(
32
)????????????????????
NOT
?
NULL
,
12
???ProvinceID?????????????????????
INT
????????????????????????????
NOT
?
NULL
,
13
???
PRIMARY
?
KEY
?(Guid)
14
)?TYPE
=
InnoDB;
15
16
ALTER
?
TABLE
?City?
ADD
?
CONSTRAINT
?CityRFProvince?
FOREIGN
?
KEY
?(ProvinceID)?
17
???
REFERENCES
?Province?(Guid)?
ON
?
DELETE
?
CASCADE
?
ON
?
UPDATE
?
RESTRICT
;
Province表做為主控方,City表做為被控方,兩者之間是雙向的一對多關系。用Middlegen生成的Province.hbm.xml文件,修改后的內容如下:
?1
<?
xml?version="1.0"
?>
?2
<!
DOCTYPE?hibernate-mapping?PUBLIC
?3
????"-//Hibernate/Hibernate?Mapping?DTD?2.0//EN"
?4
????"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"?
>
?5
????
?6
<
hibernate-mapping
>
?7
<!--
?
?8
????Created?by?the?Middlegen?Hibernate?plugin?2.1
?9
10
????http://boss.bekk.no/boss/middlegen/
11
????http://www.hibernate.org/
12
-->
13
14
<
class?
15
????
name
="com.xxx.hibernate.Province"
?
16
????table
="Province"
17
>
18
????
<
meta?
attribute
="class-description"
?inherit
="false"
>
19
???????@hibernate.class
20
????????table="Province"
21
????
</
meta
>
22
23
????
<
id
24
????????
name
="guid"
25
????????type
="int"
26
????????column
="Guid"
27
????
>
28
????????
<
meta?
attribute
="field-description"
>
29
???????????@hibernate.id
30
????????????generator-class="native"
31
????????????type="int"
32
????????????column="Guid"
33
34
35
????????
</
meta
>
36
????????
<
generator?
class
="native"
?
/>
37
????
</
id
>
38
39
????
<
property
40
????????
name
="provincename"
41
????????type
="java.lang.String"
42
????????column
="Provincename"
43
????????not-null
="true"
44
????????length
="16"
45
????
>
46
????????
<
meta?
attribute
="field-description"
>
47
???????????@hibernate.property
48
????????????column="Provincename"
49
????????????length="16"
50
????????????not-null="true"
51
????????
</
meta
>
????
52
????
</
property
>
53
54
????
<!--
?Associations?
-->
55
??
56
????
<!--
?bi-directional?one-to-many?association?to?City?
-->
57
????
<
set
58
????????
name
="cities"
59
????????lazy
="true"
60
????????inverse
="true"
61
????????cascade
="save-update"
62
????
>
63
????????
<
meta?
attribute
="field-description"
>
64
???????????@hibernate.set
65
????????????lazy="true"
66
????????????inverse="true"
67
????????????cascade="save-update"
68
69
???????????@hibernate.collection-key
70
????????????column="ProvinceID"
71
72
???????????@hibernate.collection-one-to-many
73
????????????class="com.xxx.hibernate.City"
74
????????
</
meta
>
75
????????
<
key
>
76
????????????
<
column?
name
="ProvinceID"
?
/>
77
????????
</
key
>
78
????????
<
one-to-many?
79
????????????
class
="com.xxx.hibernate.City"
80
????????
/>
81
????
</
set
>
82
83
</
class
>
84
</
hibernate-mapping
>
85
????set節點有以下屬性(摘自Hibernate文檔):
(1) |
name 集合屬性的名稱 |
(2) |
table (可選——默認為屬性的名稱)這個集合表的名稱(不能在一對多的關聯關系中使用) |
(3) |
schema (可選) 表的schema的名稱, 他將覆蓋在根元素中定義的schema |
(4) |
lazy (可選——默認為false) lazy(可選--默認為false) 允許延遲加載(lazy initialization )(不能在數組中使用) |
(5) |
inverse (可選——默認為false) 標記這個集合作為雙向關聯關系中的方向一端。 |
(6) |
cascade (可選——默認為none) 讓操作級聯到子實體 |
(7) |
sort (可選)指定集合的排序順序, 其可以為自然的(natural)或者給定一個用來比較的類。 |
(8) |
order-by (可選, 僅用于jdk1.4) 指定表的字段(一個或幾個)再加上asc或者desc(可選), 定義Map,Set和Bag的迭代順序 |
(9) |
where (可選) 指定任意的SQL where條件, 該條件將在重新載入或者刪除這個集合時使用(當集合中的數據僅僅是所有可用數據的一個子集時這個條件非常有用) |
(10) |
outer-join (可選)指定這個集合,只要可能,應該通過外連接(outer join)取得。在每一個SQL語句中, 只能有一個集合可以被通過外連接抓取(譯者注: 這里提到的SQL語句是取得集合所屬類的數據的Select語句) |
(11) |
batch-size (可選, 默認為1) 指定通過延遲加載取得集合實例的批處理塊大小("batch size")。 |
(12) |
access (可選-默認為屬性property):Hibernate取得屬性值時使用的策略 |
??????由于在建立外鍵的時候就聲明了ON DELETE CASCADE,所以在xml的配置文件中cascade聲明為save-update。如果聲明為all,那么在刪除Province表的數據時,會無謂的多出一條刪除City的delete語句出來,這將會影響程序的性能。
??????City.hbm.xml的內容如下:
1<?xml?version="1.0"?>
?2<!DOCTYPE?hibernate-mapping?PUBLIC
?3????"-//Hibernate/Hibernate?Mapping?DTD?2.0//EN"
?4????"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"?>
?5????
?6<hibernate-mapping>
?7<!--?
?8????Created?by?the?Middlegen?Hibernate?plugin?2.1
?9
10????http://boss.bekk.no/boss/middlegen/
11????http://www.hibernate.org/
12-->
13
14<class?
15????name="com.xxx.hibernate.City"?
16????table="City"
17>
18????<meta?attribute="class-description"?inherit="false">
19???????@hibernate.class
20????????table="City"
21????</meta>
22
23????<id
24????????name="guid"
25????????type="int"
26????????column="Guid"
27????>
28????????<meta?attribute="field-description">
29???????????@hibernate.id
30????????????generator-class="native"
31????????????type="int"
32????????????column="Guid"
33
34
35????????</meta>
36????????<generator?class="native"?/>
37????</id>
38
39????<property
40????????name="cityname"
41????????type="java.lang.String"
42????????column="Cityname"
43????????not-null="true"
44????????length="32"
45????>
46????????<meta?attribute="field-description">
47???????????@hibernate.property
48????????????column="Cityname"
49????????????length="32"
50????????????not-null="true"
51????????</meta>????
52????</property>
53
54????<!--?Associations?-->
55??
56????<!--?bi-directional?many-to-one?association?to?Province?-->
57????<many-to-one
58????????name="province"
59????????class="com.xxx.hibernate.Province"
60????????cascade="none"
61????????outer-join="auto"
62????????update="true"
63????????insert="true"
64????????access="property"
65????????not-null="true"
66????>
67????????<meta?attribute="field-description">
68???????????@hibernate.many-to-one
69????????????cascade="none"
70????????????outer-join="auto"
71????????????update="true"
72????????????insert="true"
73????????????access="property"
74????????????not-null="true"
75???????????@hibernate.column?name="ProvinceID"?????????
76????????</meta>
77????????<column?name="ProvinceID"?/>
78????</many-to-one>
79
80</class>
81</hibernate-mapping>
82
(1) | name: 屬性名。 |
(2) | column (可選): 字段名。 |
(3) | class (可選 - 默認是通過反射得到屬性類型): 關聯的類的名字。 |
(4) | cascade(級聯) (可選): 指明哪些操作會從父對象級聯到關聯的對象。 |
(5) | outer-join(外連接) (可選 - 默認為 自動): 當設置hibernate.use_outer_join的時候,對這個關聯允許外連接抓取。 |
(6) | update, insert (可選 - defaults to true) 指定對應的字段是否在用于UPDATE 和/或 INSERT的SQL語句中包含。如果二者都是false,則這是一個純粹的“外源性(derived)”關聯,它的值是通過映射到同一個(或多個)字段的某些其他屬性得到的,或者通過trigger(除法器),或者是其他程序。 |
(7) | property-ref: (可選) 指定關聯類的一個屬性,這個屬性將會和本外鍵相對應。如果沒有指定,會使用對方關聯類的主鍵。 |
(8) | access (可選 - 默認是 property): Hibernate用來訪問屬性的策略。 |
cascade 屬性允許下列值: all, save-update, delete, none。設置除了none以外的其它值會傳播特定的操作到關聯的(子)對象中。參見后面的“Lifecycle Objects(自動管理生命周期的對象)”。
outer-join 參數允許下列三個不同值:
-
auto (默認) 使用外連接抓取關聯(對象),如果被關聯的對象沒有代理(proxy)
-
true 一直使用外連接來抓取關聯
-
false 永遠不使用外連接來抓取關聯
??????用hbm2java生成對應的對應的Java類:hbm2java *.xml --output=xxx。
??????Hibernate的配置文件hibernate.cfg.xml內容如下:
1<?xml?version="1.0"?encoding="utf-8"?>
?2<!DOCTYPE?hibernate-configuration
?3????PUBLIC?"-//Hibernate/Hibernate?Configuration?DTD//EN"
?4????"http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">
?5
?6<hibernate-configuration>
?7????<session-factory>
?8
?9????????<!--?local?connection?properties?-->
10????????<property?name="hibernate.connection.url">jdbc:mysql://127.0.0.1/xxx?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true</property>
11????????<property?name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
12????????<property?name="hibernate.connection.username">root</property>
13????????<property?name="hibernate.connection.password">123456</property>
14????????<!--?property?name="hibernate.connection.pool_size"></property?-->
15
16????????<!--?dialect?for?MySQL?-->
17????????<property?name="dialect">net.sf.hibernate.dialect.MySQLDialect</property>
18
19????????<property?name="hibernate.show_sql">true</property>
20????????<property?name="hibernate.use_outer_join">true</property>
21????????<property?name="hibernate.transaction.factory_class">net.sf.hibernate.transaction.JDBCTransactionFactory</property>
22????????
23????????<mapping?resource="com/xxx/hibernate/City.hbm.xml"/>
24????????<mapping?resource="com/xxx/hibernate/Province.hbm.xml"/>
25
26????</session-factory>
27</hibernate-configuration>
JUnit的測試用例程序片斷如下:



?2



?3

?4

?5

?6

?7

?8

?9

10

11

12

13

14

15

16



17

18



19

20

21

運行測試程序,可以看到輸出了兩條insert語句,省的值和市的值都插入到了表中。