新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论Java, J2SE, J2ME, J2EE, 以及Eclipse, NetBeans, JBuilder等Java开发环境,还有JSP, JavaServlet, JavaBean, EJB以及struts, hibernate, spring, webwork2, Java 3D, JOGL等相关技术。
    [返回] 中文XML论坛 - 专业的XML技术讨论区计算机技术与应用『 Java/Eclipse 』 → 使用Hibernate进行对象的关系映射[转帖] 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 10887 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: 使用Hibernate进行对象的关系映射[转帖] 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     admin 帅哥哟,离线,有人找我吗?
      
      
      
      威望:9
      头衔:W3China站长
      等级:计算机硕士学位(管理员)
      文章:5255
      积分:18406
      门派:W3CHINA.ORG
      注册:2003/10/5

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给admin发送一个短消息 把admin加入好友 查看admin的个人资料 搜索admin在『 Java/Eclipse 』的所有贴子 点击这里发送电邮给admin  访问admin的主页 引用回复这个贴子 回复这个贴子 查看admin的博客楼主
    发贴心情 使用Hibernate进行对象的关系映射[转帖]


    原文连接:http://www.meagle.com:8080/hibernate.jsp

        Hibernate是业界比较推崇的ORM(o/r mapping),目前的版本已经非常稳定和成熟,
    而且的他的文档也极其丰富。
        Http://www.jdon.com和http://www.chinaxp.com 这两个技术网站对hibernate的讨论
    很多也很精到。
        这篇文章是一篇让出学者入门的文章。现意译如下,英文好的可以跳过直接阅读原文。
              --译者按


    在Java技术中有许多方法可以对数据进行持久化,持久层也是Java应用程序中最重要的部分
    之一。在当今关系型数据库仍为如主流数据库的时候,我个人认为持久层技术常常并没有得
    到应用的重视。在这篇文章里将涉及到几个著名的以Java技术实现的持久性框架,随后我们
    会谈到一些最新的持久性框架譬如:Hibernate,让我们就从那些著名的框架以极其通用API
    s开是这次旅行吧。

    1.JDBC
       大多数Java开发员都是用JDBC来和数据库进行通信,它可以通过DAO(Data Access
    Object)模式来进行改善和提高,然而,这种方式在大型应用程序中则会造成维护的"高消费
    "。不过大多数的开发员对于JDBC的操作以及其API都是非常熟悉,因此,我相信不管怎样它
    仍然是目前最被广泛应用的数据持久技术之一。( 不要着急"噩梦马上就要结束了",译者
    注)

    2.EJB
       据调查EJB通常是在数据持久技术上的第二个选择,它是通过entity
    beans来对数据进行持久化,这听起来就好像是Java持久框架界中的"银单"一样(真的有银
    弹??),我的意思是在巨大的市场下(潜在的一块大蛋糕?)。然而事实上并不是这样的
    :首先你需要购买一个价位合理的EJB容器--J2EE应用服务器,采用开源项目的免费EJB容器
    是一种不错的选
    择:),比如JBOSS(恕我直言);其次全面采用entity
    bean需要花"大量"的时间来理解EJB规范。在采用EJB之前你通常想在熟练掌握它的API;再
    有就是,你需要知道在每一个容器除了ejb-jar.xml以外所专有的部署描述符,而且很多商
    业EJB容器的性能和技术支持也不敢恭维。对于JAVA开发员,在EJB中实现JDBC也比较复杂。
    EJB中最为被关注
    的可能是无状态的会话BEAN(stateless-Session beans)和消息驱动BEAN(messaging driver
    beans)

    3.更多持久框架

    通过对前面两种规范一阵"游移不定和踌躇"以后,你可能发现它们都不是完美的解决方案。
    JDO的出现似乎有了一些改观,但是JDO1.0不论是从操作方式上还是其功能上对于Java开发
    员来说似乎"天还是灰蒙蒙的","而且没有一个好的免费的产品",终究JDO1.0仍然没有带来
    太大改变,人们
    仍停留在用它来学习的阶段,这种情况有待JDO的成熟来解决。(目前SUN已经加入JDOCENTOR
    L.COM来着手JDO2.0,我们唯有等待那丝曙光了。)

    那么我们该怎么做呢?如果你抛开主流于非主流的概念,你会发现你将有更多的选择(也许
    是更好的?),如果是这样,你不会不注意到这样两个名字"Hibernate"和"OJB",这两种持
    久框架跟前面的提到的JDBC、EJB和JDO在某些方面有很大的不同,它们不需要任何容器,提
    供简单易用并符合ODMG3-style APIs,而且它们免费、开源、有丰富的文档和稳定的开发背
    景。
    也许你所要做的仅仅是选择?

    4"冬眠"Hibernate
       就让我们现在开始吧,在这些"新鲜的"持久框架中我选择了Hibernate,同时当初我也把
    OJB列入我的选择之列,不过最后之所以选择Hibernate的原因要归功于它丰富的文档,我知
    道有许多其它的人使用OJB也取得过成功。不管怎么样,Hibernate和OJB都可以让你完全操
    纵持久层。
       请访问http://hibernate.blumears.net/4.html来获得Hibernate的功能介绍。
       下面我想首先说一下我的运行环境:Hibernate 2.0 RC1 (2.0 beta 5)+ Tomcat 4.1.18
    +WebSphere Application Server
    5.0.1(请到相应的官方网站获取各个的最新版本,译者注),我的例子在其他的容器中也
    能正常的运行,不过我没有进行这方面的测试。Hibernate网站有关于在Jboss下的配置信息
    ,通常几乎所有的应用服务器和数据库都能整合Hibernate。

    4.1 Mapping Relationships with Hibernate

    下面我们开讨论如何使用Hibernate进行对象的关系映射。我将介绍如何使用Hibernate进行
    "一对一"、"一对多"、"多对多"的映射。在我提供的代码中只是为了测试而没有考虑到更多
    的"模式啦规则啦"等等,这就说这里的例子只是一个启蒙,让我们从代码中学习Hibernate
    的API以及如何进行开发,请再你自己书写的时候注意必要的模式和编码规范。

        然后我们看看我的例子中都有哪些对象,让们开始为他们建模吧,如下图:

           下图为数据表关系图:


    4.2 配置Hibernate

        点击此处获得本文中的实例代码,这样你可以对本例有更深的了解。

        为了运行实例,请确信你已经下载过Hibernate和log4j的最新发布包,同时也要把数据
    库驱动放到classpath中。下载以后的压缩包中有example_schema.ddl文件用来生成数据库
    表。

        接下来作者给我们讲述了一个Hibernate.properties文件,它是在配置Hibernate的时
    候最先接触到的,它在应用程序启动的时候为我们进行初始化工作(译者注:有了hibernat
    e.cfg.xml,Hibernate.properties变的可有可无了,不是吗?)

    hibernate.connection.driver_class=COM.ibm.db2.jdbc.net.DB2Driver

    hibernate.connection.url=jdbc:db2://server1/sample

    hibernate.connection.username=db2admin

    hibernate.connection.password=password

    hibernate.default_schema=db2admin

    hibernate.dialect=net.sf.hibernate.dialect.DB2Dialect

    hibernate.show_sql=true



    # The maximum number of active connections that can be allocated # from this po
    ol at the same time, or zero for no limit.

    hibernate.dbcp.maxActive 100

    # Action to take in case of an exhausted DBCP statement pool

    # ( 0 = fail, 1 = block, 2= grow)

    hibernate.dbcp.whenExhaustedAction 1

    hibernate.dbcp.maxWait 120000

    # The maximum number of active connections that can remain

    # idle in the pool, without extra ones being released, or zero

    # for no limit.

    hibernate.dbcp.maxIdle 10



    # The SQL query that will be used to validate

    # connections from this pool before returning them to the caller.

    # hibernate.dbcp.validationQuery=TODO

    ## prepared statement cache

    hibernate.dbcp.ps.maxActive 100

    # Action to take in case of an exhausted DBCP statement

    #pool ( 0 = fail, 1 = block, 2= grow)

    hibernate.dbcp.ps.whenExhaustedAction 1

    # The maximum number of milliseconds that the pool will

    # wait (when there are no available connections) for a connection

    # to be returned before throwing an exception, or -1 to

    # wait indefinitely.

    hibernate.dbcp.ps.maxWait 120000

    hibernate.dbcp.ps.maxIdle 100


        上边的代码中,首先指明了和数据连接有关的属性元素:database driver、JDBC
    URL、用户账号和密码、dialect("数据库"方言、土语、地方话)等等,dialect为我们使
    用的每一个数据库进行最佳优化,在Hibernate使用手册中你可以到得到每一个数据库的dia
    lect.最后,hibernate.show_sql当设定为"真"的时候,我们可以在Hibernate的DEBUG信息
    中看到HQL在执行
    的时候的SQL语句。
        剩下的属性元素是用来配置连接池的,这里使用的是用Jakarta DBCP(详细信息到Jaka
    rta官方网站查看)来实现连接池,同样Hibernate也可以用其它的方式来实现此功能,如:
    C3PO(没听说过,呵呵。。)。详细信息进入Hibernate文档。

    4.3 创建持久对象


    在Hibernate运行环境搭起来以后,我们开始创建持久对象或是映射文件来开始我们的工作
    。(通常创建对象和创建映射文件做其一即可,另一个可以通过做好的来自动完成),这里
    我们从创建持久对象开始,下面是完成以后的代码,Hibernate所需要的"持久对象"符合我
    们经常写的对象的规范,它们没什么差别:

    package dbdemo;
    import java.util.Date;
    import java.util.Set;
      /**

      * @hibernate.class table="Users"
      *
      * @author MEagle
      *
      * Represents a User
      */
    public class User {

           private String userID;
           private String userName;
           private String password;
           private String emailAddress;
           private Date lastLogon;
           private Set contacts;
           private Set books;
           private Address address;

           /**
            * @hibernate.property column="EmailAddress" type="string"
            * @return String
            */

           public String getEmailAddress() {
                 return emailAddress;
           }

           /**
            * @hibernate.property column="LastLogon" type="date"
            * @return Date
            */

           public Date getLastLogon() {
                 return lastLogon;
           }

           /**
            * @hibernate.property column="Password" type="string"
            * @return String
            */

           public String getPassword() {
                 return password;
           }

           /**
            * @hibernate.id generator-class="assigned" type="string"
            *                      column="LogonID"
            * @return String
            */

           public String getUserID() {
                 return userID;
           }



           /**
            * @hibernate.property column="Name" type="string"
            * @return String
            */

           public String getUserName() {
                 return userName;
           }

           /**
            * @param string
            */

           public void setEmailAddress(String string) {
                 emailAddress = string;
           }



           /**
            * @param string
            */

           public void setLastLogon(Date date) {
                 lastLogon = date;
           }

           /**
            * @param string
            */

           public void setPassword(String string) {
                 password = string;
           }

           /**
            * @param string
            */

           public void setUserID(String string) {
                 userID = string;
           }

           /**
            * @param string
            */

           public void setUserName(String string) {
                 userName = string;
           }



           /**
            * @hibernate.set role="contacts" table="Contacts"
            *                        cascade="all" readonly="true"
            * @hibernate.collection-key column="User_ID"
            * @hibernate.collection-one-to-many class="dbdemo.Contact"
            * @return java.util.Set
            */

           public Set getContacts() {
                 return contacts;
           }



           /**
            * @param set
            */

           public void setContacts(Set set) {
                 contacts = set;
           }



           /**
            * @hibernate.set role="books" table="Book_User_Link"
            *                            cascade="all" eadonly="true"
            * @hibernate.collection-key column="UserID"
            * @hibernate.collection-many-to-many
            *                            class="dbdemo.Book" column="BookID"
            * @return java.util.Set
            */
           public Set getBooks() {
                 return books;
           }

           /**
            * @param set
            */

           public void setBooks(Set set) {
                 books = set;
           }

           /**
            * @hibernate.one-to-one class="dbdemo.Address"
            * @return dbdemo.Address
            */

           public Address getAddress() {
                 return address;
           }

           /**
            * @param address
            */

           public void setAddress(Address address) {
                 this.address = address;
           }

    }



    4.4 Ant and XDoclet

        如果你仔细看了上边的代码,你会发现它有一点和我们以前的"不太一样",它javadoc
    中多了许多特定的javadoc,是的,那是Hibernatedoclet。它和Xdoclet是"姊妹篇",Xdocle
    t是这样一种工具:它通过和Apache
    Ant一起来产生应用程序的部署描述符。因此除非你乐意书写xml映射文件,否要就会用到xd
    oclet(但是我还是建议初学者还是要给自己些机会手写**.hbm.xml)。 进入查看hibernated
    oclet的详细信息,下面我们看看,这里是如果利用对象来产生映射文件的,下面,看看bui
    ld.xml:

    <!-- this file uses Apache Ant 1.5.3 beta 1 -->

    <project name="Hibernate Example" default="about" basedir=".">

           <!-- The location where your xdoclet jar files reside -->

           <property name="xdoclet.lib.home" value="c:/java_api/xdoclet-1.2b3/lib"/>



           <target name="clean" depends="init" description="removes all directories
    related to this build">

                 <delete dir="${dist}"/>

           </target>


           <target name="init" description="Initializes properties that are used by
    other targets.">
                 <property name="dist" value="dist"/>
           </target>

           <target name="prepare" depends="init,clean" description="creates dist dir
    ectory">
                 <echo message="Creating required directories..."/>
                 <mkdir dir="${dist}"/>
           </target>

           <target name="hibernate" depends="prepare"
             description="Generates Hibernate class descriptor files.">
                 <taskdef name="hibernatedoclet"                 classname="xdoclet.
    modules.hibernate.HibernateDocletTask">                  <classpath>
                       <fileset dir="${xdoclet.lib.home}">
                           <include name="*.jar"/>
                       </fileset>
                     </classpath>
                 </taskdef>

                 <!-- Execute the hibernatedoclet task -->

                 <hibernatedoclet
                       destdir="."
                       excludedtags="@version,@author,@todo"
                       force="true"
                       verbose="true"
                       mergedir="${dist}">

                       <fileset dir=".">
                           <include name="**/dbdemo/*.java"/>
                       </fileset>

                       <hibernate version="2.0"/>

                 </hibernatedoclet>
           </target>

           <target name="about" description="about this build file" depends="init">
                 <echo message="  Use this format for the arguments:"/>
                 <echo message="      ant hibernate"/>
                 <echo message=""/>
           </target>

    </project>


       下面试运行时模拟的一个结果:

    C:\eclipse\workspace\HibernateExample>ant hibernate
    Buildfile: build.xml
    init:
    clean:
        [delete] Deleting directory C:\eclipse\workspace\HibernateExample\dist
    prepare:
          [echo] Creating required directories...
         [mkdir] Created dir: C:\eclipse\workspace\HibernateExample\dist

    hibernate:
    [hibernatedoclet] Running <hibernate/>
    [hibernatedoclet] Generating mapping file for dbdemo.Contact.
    [hibernatedoclet] Generating mapping file for dbdemo.Book.
    [hibernatedoclet] Generating mapping file for dbdemo.Address.
    [hibernatedoclet] Generating mapping file for dbdemo.User.
    BUILD SUCCESSFUL
    Total time: 2 seconds
    C:\eclipse\workspace\HibernateExample>


       接下来然我们看看,"生成"了什么样的映射文件(*.hbm.xml):

    <?xml version="1.0"?>

    <!DOCTYPE hibernate-mapping PUBLIC

           "-//Hibernate/Hibernate Mapping DTD//EN"

           "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">

    <hibernate-mapping>
           <class
                 name="dbdemo.User"
                 table="Users"
           >

               <id
                       name="userID"
                       column="LogonID"
                       type="string"
                 >
                       <generator class="assigned">
                       </generator>
               </id>

             <one-to-one
                 name="address"
                       class="dbdemo.Address"
                       cascade="none"
                       outer-join="auto"
                       constrained="false"
               />

                 <set
                       name="books"
                       table="Book_User_Link"
                       lazy="false"
                       inverse="true"
                       cascade="all"
                       sort="unsorted"
                 >

                       <key
                             column="UserID"
                       >
                       </key>

                       <many-to-many
                             class="dbdemo.Book"
                             column="BookID"
                       />

               </set>

                 <set
                       name="contacts"
                       table="Contacts"
                       lazy="false"
                       inverse="true"
                       cascade="all"
                       sort="unsorted"
                 >
                       <key
                             column="User_ID"
                       >
                       </key>

                       <one-to-many
                             class="dbdemo.Contact"
                       />

               </set>

             <property
                 name="emailAddress"
                 type="string"
                 column="EmailAddress"
                 not-null="false"
                       unique="false"
                 />

             <property
                 name="lastLogon"
                 type="date"
                 column="LastLogon"
                 not-null="false"
                       unique="false"
                 />

             <property
                 name="password"
                 type="string"
                 column="Password"
                 not-null="false"
                       unique="false"
                 />

             <property
                 name="userName"
                 type="string"
                 column="Name"
                 not-null="false"
                       unique="false"
                 />

               <!--
                       To add non XDoclet properties, create a file named
                           hibernate-properties-User.xml
                       containing the additional properties and place it in your mer
    ge dir.
               -->

           </class>

    </hibernate-mapping>


          一旦创建完映射文件(放在classpath 中,并且和对象是"一对一"关系),你就可以
    通过Hibernate的接口和方法来操纵系统对象。


    最后说一下,本文中例子下载包中的内容,每一个单独的例子都有main方法来运行:第一个
    例子:HibernateDemo.java,增加两个users,并且和address相关联("一对一");第二个
    例子:HibernateDemoOneToMany.java,学习用Hibernate进行"一对多"映射;最后,第三个
    例子:HibernateDemoManyToMany.java,学习用Hibernate进行"多对多"映射。建议你按照
    顺序运行,如果你没有使用DB2 (e.g. sequences).的话,你也可以跟改数据库。例子包中
    还有一个例子:HibernateDemoHQL利用前面的例子产生的数据来说明如何用HQL来操纵数据


          作者提供的例子中很简单,但对于初学者却是非常好的一个学习的机会(希望初学者
    对作者的代码进行运行尝试,有许多东西本文并没有说,不过你可以通过作者的代码得到答
    案)。希望你能在学习Hibernate的时候从此处得到些帮助。

       收藏   分享  
    顶(0)
      




    ----------------------------------------------

    -----------------------------------------------

    第十二章第一节《用ROR创建面向资源的服务》
    第十二章第二节《用Restlet创建面向资源的服务》
    第三章《REST式服务有什么不同》
    InfoQ SOA首席编辑胡键评《RESTful Web Services中文版》
    [InfoQ文章]解答有关REST的十点疑惑

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2005/3/1 17:30:00
     
     japanpigkiller 帅哥哟,离线,有人找我吗?
      
      
      等级:大一新生
      文章:2
      积分:62
      门派:XML.ORG.CN
      注册:2005/3/31

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给japanpigkiller发送一个短消息 把japanpigkiller加入好友 查看japanpigkiller的个人资料 搜索japanpigkiller在『 Java/Eclipse 』的所有贴子 引用回复这个贴子 回复这个贴子 查看japanpigkiller的博客2
    发贴心情 
    很好,谢谢,如果完整,就更好了。
    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2005/3/31 10:51:00
     
     haoyun 帅哥哟,离线,有人找我吗?
      
      
      等级:大一新生
      文章:1
      积分:60
      门派:XML.ORG.CN
      注册:2005/4/3

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给haoyun发送一个短消息 把haoyun加入好友 查看haoyun的个人资料 搜索haoyun在『 Java/Eclipse 』的所有贴子 引用回复这个贴子 回复这个贴子 查看haoyun的博客3
    发贴心情 
    不错,部分解释都不错。
    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2005/4/3 11:23:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 Java/Eclipse 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/4/30 3:52:08

    本主题贴数3,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    6,080.078ms