内蒙古java团队

j2se,j2ee开发组
posts - 139, comments - 212, trackbacks - 0, articles - 65
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

Hibernate的一对多关联实例

Posted on 2007-01-09 16:14 帅子 阅读(1859) 评论(1)  编辑  收藏 所属分类: j2se技术专区

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

many-to-one节点有以下属性(摘自Hibernate文档):
(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&amp;characterEncoding=UTF-8&amp;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的测试用例程序片断如下:

 1      public   void  testInsert()  {
 2          try   {
 3             Province province  =   new  Province();
 4             province.setProvincename( " 广东 " );
 5             
 6             City city  =   new  City();
 7             city.setCityname( " 深圳 " );
 8             
 9             city.setProvince(province);
10             province.setCities( new  HashSet());
11             province.getCities().add(city);
12             
13             Transaction tx  =  session.beginTransaction();
14             session.save(province);
15             tx.commit();
16         }
  catch  (HibernateException e)  {
17             e.printStackTrace();
18         }
  catch  (Exception ex)  {
19             ex.printStackTrace();
20         }

21     }

运行测试程序,可以看到输出了两条insert语句,省的值和市的值都插入到了表中。


评论

# re: Hibernate的一对多关联实例  回复  更多评论   

2007-01-16 17:33 by ss
不错,收了。

谢谢

只有注册用户登录后才能发表评论。


网站导航: