Hibernate技术(2)

我们可以看见,一个儿童可以具有很多玩具,这是一个明显的一对多关系,在Hibernate里面有这样的标签与之对应<one-to-many>,然后,我们可以为这两个类写mapping.xml文件了,在hibernate里面,每个要持久化的类都要求有相应的mapping文件,这样hibernate才会知道如何把java class property对应到table columns里面了,有的时候我们不用自己指明java某个属性的类型,hibernatereflection机制,它可以在运行时动态的察觉某个属性的类型,然后对应到相应的数据库类型中。

 

1、  配置hibernate.properties文件

你可以拷贝一份例子,然后稍加改动便可以使用了,关键在于以下几处:

配置数据库,如下

## Oracle

hibernate.dialect net.sf.hibernate.dialect.OracleDialect

hibernate.connection.driver_class oracle.jdbc.driver.OracleDriver

hibernate.connection.url jdbc:oracle:thin:@locahost:1521:oracle8i

hibernate.connection.username test

hibernate.connection.password test

 

设置开发模式

## print all generated SQL to the console

hibernate.show_sql true

这样,开发的时候可以看见实际运行的sql语句了。

 

2、  我们先建立一个名为Hibernate.cfg.xml的文件,这样,Hibernate就知道数据库的属性以及要加载的mapping文件的位置了。
文件内容如下:

<hibernate-configuration>

    <session-factory >

        <property name="dialect">net.sf.hibernate.dialect.OracleDialect</property>

        <mapping resource="hibernate/Child.hbm.xml"/>

        <mapping resource="hibernate/Toy.hbm.xml"/>

   </session-factory>

</hibernate-configuration>

 

我来解释一下,hibernate-configuration为顶级元素,然后的property dialect告诉了hibernate底层的数据库名称,对于不同的数据库hibernated都内建了相应的类来对应,这些类都在net.sf.hibernate.dialet包中,为什么这样哪?因为每种数据库都有不同的o/r mapping机制,况且处理主键的机制也很不相同,所以有必要这样做。其实切换数据库对于hibernate来说也非常的方便,只要更换这个属性就可以了。当然,如果你在其他的配置文件里面用到了数据库特定的配置,那么也必须做相应的修改。

       接下来的mapping resource=””就表示了每个持久化的类对应的mapping文件,当然,你也可以不用为每一个类写一个mapping 文件,如果可以的话,我建议为逻辑上相关的类或者一个包写一个mapping文件就可以了。这样显得比较紧凑,不会看见你的源代码里面到处都是xml文件了。当然,目前也有一个工具叫做xdoclet,可以自动帮助你产生mapping文件,但是我想那样的自动化处理毕竟不是十分的灵活,大部分使用hibernate的人都是采用自己手工写mapping文件的。所有我也推荐大家在学习hibernate的时候,不要偷懒,一开始就使用xdoclet来产生mapping文件,这样你的基础会很不牢靠。

       还有一点,就是这个resource=value里面的value是和package的名字相对应的。一般情况下,都把类和类的mapping文件放在一起。

 

3、  撰写mapping文件

大家或许比较关心到底hibernate是如何把java class对应到table column的哪?其实在hibernate的文档里面,这一点介绍的比较清楚,里面专门有一章来介绍mapping机制,因为这是应用hibernate的基础,以后你会发现,你的大部分时间都将花在mapping上面,而不是写sql语句了。

 

先看Child类的mapping文件

<hibernate-mapping>

  <class name="hibernate.Child" table="CHILD">  //java class对应到database table

    <id name="id" unsaved-value="0">//主键描述

      <generator class="sequence">//采用oraclesequence技术自动自增主键

        <param name="sequence">SEQ_CHILD</param>

      </generator>

    </id>

    <array name="toys" table="TOY" cascade="all">//描述和toy的一对多关系

      <key column="CHILD_ID"/>

      <index column="POSN"/>//之所以要写index,因为有array

      <one-to-many class="hibernate.Toy"/>

    </array>

  </class>

</hibernate-mapping>

 

里面需要注意的有以下几点:

1)         如果你采用了one-to-many的关系,并且使用了session.saveOrUpdate()方法,那么你最好让<id>属性有unsaved-value=”0”属性,否则会抛出违背外键的异常。

2)         注意,child-toy之间的one-to-many关系是通过外键关联上去的。这个外键就是toy表里面的child_id字段。

3)         由于我们采用array来实现one-to-many的关系,所以我们必须制定一个额外的字段来存储这个array的索引,这样你存进去的序号和你取出来的序号是一致的,当然,如果你不想让hibernate记住序号就不用这个字段了,可以使用<set><bag>等来替换<array>

4)         注意<array>里面的cascade属性,这个属性很重要,它表示,如果这个属性为all,那么当save,update,delete一个Child类的时候,其属性toys也会相应的得到save,update,或者delete,否则不会。当然你也可以使用实现hibernate自带的接口LifeCycle来实现这个功能。但是没有必要。  注意,这个功能有一点要注意,就是hibernate没有垃圾收集功能,当你删除了一个Child类里面的toys里面的某个toy的时候,实际上数据库中并没有删除这个记录,你必须手动的删除它。这是目前hibernate开发者们正在思考改进的一个问题。他们或许会采用JDO的机制<delete-orphan>来实现垃圾收集。

 

好了,再看Toy.hbm.xml文件

<hibernate-mapping>

  <class name="hibernate.Toy" table="TOY">

    <id name="toyId" column="TOY_ID" unsaved-value="0">

      <generator class="sequence">

        <param name="sequence">SEQ_TOY</param>

      </generator>

    </id>

    <property name="name"/>

  </class>

</hibernate-mapping>

 

相似的,Toy类制定了主键产生的方式,以及一个简单的属性name,由于数据库的字段名称和Java类的属性名称一致,所以不用制定property 里面的column属性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值