使用Hibernate进行对象的关系映射 (转)

本文详细介绍使用 Hibernate 进行对象关系映射的方法,包括一对一、一对多及多对多的映射方式,并提供了实际代码示例。文章还介绍了如何配置 Hibernate 并使用 XDoclet 和 Ant 自动生成映射文件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用Hibernate进行对象的关系映射 (转)[@more@]

使用hibernate进行对象的关系映射

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

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

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

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

4"冬眠"Hibernate
  就让我们现在开始吧,在这些"新鲜的"持久框架中我选择了Hibernate,同时当初我也把OJB列入我的选择之列,不过最后之所以选择Hibernate的原因要归功于它丰富的文档,我知道有许多其它的人使用OJB也取得过成功。不管怎么样,Hibernate和OJB都可以让你完全操纵持久层。
  请访问.NET/4.html">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以及如何进行开发,请再你自己书写的时候注意必要的模式和编码规范。

  然后我们看看我的例子中都有哪些对象,让们开始为他们建模吧,如下图:
 hibernate1.gif
  下图为数据表关系图:
 hibernate2.gif

4.2 配置Hibernate

  点击此处获得本文中的实例代码,这样你可以对本例有更深的了解。
 
  为了运行实例,请确信你已经下载过Hibernate和log4j的最新发布包,同时也要把数据库驱动放到classpath中。下载以后的压缩包中有example_schema.ddl文件用来生成数据库表。

  接下来作者给我们讲述了一个Hibernate.properties文件,它是在配置Hibernate的时候最先接触到的,它在应用程序启动的时候为我们进行初始化工作(译者注:有了hibernate.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 pool 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使用手册中你可以到得到每一个数据库的dialect.最后,hibernate.show_sql当设定为"真"的时候,我们可以在Hibernate的DEbug信息中看到HQL在执行的时候的SQL语句。
  剩下的属性元素是用来配置连接池的,这里使用的是用Jakarta DBCP(详细信息到Jakarta官方网站查看)来实现连接池,同样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是"姊妹篇",Xdoclet是这样一种工具:它通过和apache Ant一起来产生应用程序的部署描述符。因此除非你乐意书写xml映射文件,否要就会用到xdoclet(但是我还是建议初学者还是要给自己些机会手写**.hbm.xml)。 进入查看hibernatedoclet的详细信息,下面我们看看,这里是如果利用对象来产生映射文件的,下面,看看build.xml:

 <!-- this file uses Apache Ant 1.5.3 beta 1 --&gt
 
  
 
  <!-- The location where your xdoclet jar files reside --&gt
 
   


 
 
 
 
   
 
 
   
   
   
 
   
 
   
   
 
    description="Generates Hibernate class descriptor files."> 
     
   
   
   
   
   
 
  <!-- Execute the hibernatedoclet task --&gt
 
    destdir="." 
  excludedtags="@version,@author,@todo" 
  force="true" 
  verbose="true" 
  mergedir="${dist}">
 
 
   
 
 
   
 
   
   
 
   
   
   
   
 
 
 


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

 C:EclipseworkspaceHibernateExample>ant hibernate 
 Buildfile: build.xml 
 init: 
 clean: 
  [delete] Deleting directory C:eclipseworkspaceHibernateExampledist 
 prepare: 
  [echo] Creating required directories... 
  [mkdir] Created dir: C:eclipseworkspaceHibernateExampledist 
 
 hibernate: 
 [hibernatedoclet] Running  
 [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:eclipseworkspaceHibernateExample>
 

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

 <?xml version="1.0"?> 
 
 BR> 
  "-//Hibernate/Hibernate Mapping DTD//EN"
 
  "sourceforge.net/hibernate-mapping-2.0.dtd">http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"> 
 
  
    name="dbdemo.User" 
  table="Users"
  > 
 
    name="userID" 
  column="LogonID" 
  type="string" 
  > 
   
   
   
 
    name="address" 
  class="dbdemo.Address" 
  cascade="none" 
  outer-join="auto" 
  constrained="false" 
  /> 
 
    name="books" 
  table="Book_User_Link" 
  lazy="false" 
  inverse="true" 
  cascade="all" 
  sort="unsorted" 
  >
 
    column="UserID" 
  > 
   
 
    class="dbdemo.Book" 
  column="BookID" 
  /> 
 
   
 
    name="contacts" 
  table="Contacts" 
  lazy="false" 
  inverse="true" 
  cascade="all" 
  sort="unsorted" 
  >
    column="User_ID" 
  > 
   
 
    class="dbdemo.Contact" 
  /> 
 
   
 
    name="emailAddress" 
  type="string" 
  column="EmailAddress" 
  not-null="false" 
  unique="false" 
  /> 
 
    name="lastLogon" 
  type="date" 
  column="LastLogon" 
  not-null="false" 
  unique="false" 
  /> 
 
    name="password" 
  type="string" 
  column="Password" 
  not-null="false" 
  unique="false" 
  /> 
 
    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 merge dir. 
  --&gt
 
   
 
 


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

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

    你可以通过Mark Eagle(meagle@meagle.com)和作者联系。

   Jplateau 9/9/2003 


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10752043/viewspace-962425/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/10752043/viewspace-962425/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值