`
pf_miles
  • 浏览: 134664 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

hibernate3.2由hbm文件生成pojo和ddl以及相关问题的一点讨论

阅读更多

利用hibernateTools里的相关工具类,使得java实体类(POJO)、hbm映射文件、数据库表(Schema)之间可以相互转化。也就是说,只要有其中一样,就可以通过各种途径得到其它两样。

如果手里已经有了其中一样东西,要想最快建立起应用的途径自然是通过它来生成其它两样了。不过,我想在这里讨论的是那种从无到有,从想法到实现的那种建立全新应用的情况。那么,自然而然就会有一个问题:“从哪里开始?”。实体类?hbm?数据库表?先应该建立哪一个,再通过它生成其它两个?

这个问题我觉得应该从Hibernate框架的产生的初忠来考虑:为了解决“面向对象模型”与“关系模型”之间的“阻抗不匹配”。简而言之,就是说在我们的类图和E-R关系图中各元素的对应关系很难把握,而且容易让人产生概念的混淆,如“每一个数据库表对应一个实体类”等错误想法,很容易让人在设计实体时不知不觉扔掉很多面向对象模型的优秀思想。其实并不能说哪一个模型是错,只是因为他们描述问题的方向不同。那么,Hibernate框架就是把这两个模型“映射”了起来,让程序员可以在面向对象的世界里完成对数据库的查询,而不必关心底层的数据库表的结构。

说了那么多,直接了当地讲,我不赞成“先建立数据表,再通过这个数据表生成POJO和hbm文件”这种方案。道理很简单:如果先就去考虑数据库,那么我们随后的设计势必会受到这个数据库的影响,不利于精确地描述我们的应用,Hibernate框架的好处也就体现不出来了(先就把数据库搞定了还要Hibernate来干什么),生成的POJO不用说——内容多半很别扭——因为你企图从一个非面向对象的框框里硬抽象出面向对象模型来(也许你会认为这是可以通过经验来避免的,是的,确实是,不过你不觉得这样一来工作复杂化了吗?要考虑的东西增多了)。

面向对象模型是用来精确而自然地描述问题的,这是我的看法,它提供了包含、继承等等机制,几乎能把这个世界上的所有事物之间的关系精确地描述出来——它好比一门语言——怎么方便你就怎么说。那么,先数据库再POJO的做法就好比是先规定了你只能用哪些词语之后让你说话,而先POJO再数据库就好比是让你随便说随便发挥了,自然后者要好得多。

从软件工程的角度讲,需求——用例——实体这样一趟走下来,POJO出现在数据库前面是很自然的,在OOA阶段就考虑数据库是很不可取的做法(绝对一点讲——是错误的)。

OK,剩下的POJO和hbm文件之间应该先生成哪个呢?我觉得先生成谁都无所谓,都不会对我们的工程产生不利影响了。

hbm文件作为POJO和数据库之间的桥梁,从它入手的话会有一举两得的感觉,全是干净的XML文件。当然,貌似利用xDoclet标签在我们写POJO代码的时候自动生成hbm也是很不错的感觉,这个下次再讨论吧,现在给出一个完整可用而且最简单的hbm生成POJO和Schema的示例:

准备:

下载ant工具,我用的是apache-ant-1.7.0,当然,你要会用ant,怎么使用请参考别处,这里不介绍了。

下载hibernate-3.2.1.ga.zip,以及HibernateTools-3.2.0.beta9a.zip,这两个压缩包在hibernate官网上有:http://www.hibernate.org/6.html

数据库的jdbc驱动程序,本例使用mysql,驱动程序为mysql-connector-java-5.0.4。

布置实验场所:

建立“test”文件夹(其实叫什么都无所谓),再在test文件夹下建立4个文件夹:config、java、schema、lib。

解压hibernate-3.2.1.ga.zip,把里面的hibernate-3.2文件夹放在你建立的lib文件夹里面。

解压HibernateTools-3.2.0.beta9a.zip,找出hibernate-tools.jar,位置在:

\HibernateTools-3.2.0.beta9a\plugins\org.hibernate.eclipse_3.2.0.beta9a\lib\tools;

在与hibernate-tools.jar同样的位置下找出freemarker.jar;

把hibernate-tools.jar和freemarker.jar都放入你建立的lib文件夹里。

最后把数据库驱动程序:mysql-connector-java-5.0.4-bin.jar也放进lib文件夹里,

这样,所需要的类资源都准备好了。

进入config文件夹,首先写hibernate config文件,文件名:hibernate.cfg.xml:

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
          "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
 <session-factory>
  <property name="connection.username">root</property>
  <property name="connection.password">XXXXXXXXXX</property><!--Your DB password here.-->
  <property name="connection.url">jdbc:mysql://localhost:3306/courseChoosing</property>
  <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
  <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
  <mapping resource="Student.hbm.xml" />
  <mapping resource="Course.hbm.xml" />
 </session-factory>
</hibernate-configuration>

以上代码不用过多解释,就是hibernate的配置文件,其中有连接数据库的重要信息。只是connection.password属性注意修改成你自己的密码就行了。那两个mapping元素是本例要创建的两个hbm文件,待会儿我们再实际地创建它,现在不用管。

好了,hibernate配置文件写好了之后,我们现在该讨论一下我们将要进行的这个例子的与“业务”相关的话题了:

很简单——我就拿“学生选课”这件事来做这个例子,具体描述是这样的:“一门课可以被多个学生选,一个学生也可以选择多门课。”很显然,这是一个多对多关系。画出实体类图应该是这样的(PowerDesigner12):

 

也就是说,在“学生”这个类中会有一个set,保存了这个学生所选的所有的课;同时,在“课程”这个类中也会有一个set,保存了所有要上这门课的学生。

弄清楚了类图之后,让我们用hbm文件来分别描述这两个类:

还是在config文件夹下,建立Course.hbm.xml和Student.hbm.xml,

Course.hbm.xml的内容如下:

<?xml version = "1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package = "courseChoosing">
 <class name = "Course" table = "course">
  <id name = "id" column = "id" type = "long">
   <generator class = "native" />
  </id>
  <property name = "name" type = "string" length = "50" />
  <property name = "credit" type = "integer" />
  <property name = "totalClasses" type = "integer" />
  <set name = "students" table = "courseChoosing" inverse = "true">
   <key column = "courseId" />
   <many-to-many class = "Student" column = "studentId" />
  </set>
 </class>
</hibernate-mapping>

Student.hbm.xml的内容如下:

<?xml version = "1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package = "courseChoosing">
 <class name = "Student" table = "student">
  <id name = "id" column = "id" type = "long">
   <generator class = "native" />
  </id>
  <property name = "stuNo" type = "string" length = "10" />
  <property name = "name" type = "string" length = "20" />
  <property name = "gender" type = "character" />
  <set name = "courses" table = "courseChoosing" inverse = "false">
   <key column = "studentId" />
   <many-to-many class = "Course" column = "courseId" />
  </set>
 </class>
</hibernate-mapping>

这两个文件是纯粹的hbm文件描述实体类的方式,看上去很简洁,层次很清晰。需要仔细看明白的是其中的那个set元素:

name属性是这个set的名字,也就是最后生成的java代码中的这个set的名字;table属性是这个set对应的数据库表的名字,由于这个是多对多关系,所以需要另外建立一个表来存储学生和课程之间的选择关系,不过这种细节不用管,hibernatetools会做好一切。最重要的是那个inverse属性,它决定了多对多关系的两边到底由谁来管理双方的关系数据。inverse设为“true”的一方将不负责维护双方的关系数据,本例中考虑实际情况,决定让“学生”类来维护这个选课关系(因为从来只有学生选课或退出选课,而没有课选学生或课踢除学生的情况),于是将Course类里的set的inverse属性设为“true”,Student里的inverse为“false”。顺便提一句,如果不指明inverse属性,那么默认为false。many-to-many元素说明了他们之间的关系,class属性指明了当前set中对象的类型,column属性指明了关系表(courseChoosing)中的外码名。

到此为止,与业务相关的东西已经描述完毕,剩下的就是编写ant脚本来实际生成ddl和java文件了。

在test文件夹下,建立build.xml文件,其内容如下:

<?xml version="1.0"?>
<project name = "test" default = "hbm2java">
 <property name = "configuration-files.dir" value = "config" />
 <property name = "java.code.dir" value = "java" />
 <property name = "schema.dir" value = "schema" />
 <property name = "lib.dir" value = "lib" />
 <property name = "hibernate3.dir" value = "${lib.dir}/hibernate-3.2" />

 <path id = "hibernate3.path">
  <pathelement location = "${hibernate3.dir}/hibernate3.jar" />
  <fileset dir = "${hibernate3.dir}">
   <include name = "**/*.jar" />
  </fileset>
 </path>
 <path id = "mysql.jdbc.driver.path">
  <pathelement location = "${lib.dir}/mysql-connector-java-5.0.4-bin.jar" />
 </path>
 <path id = "hibernate-tools.path">
  <pathelement location = "${lib.dir}/hibernate-tools.jar" />
 </path>
 <path id = "freemarker.path">
  <pathelement location = "${lib.dir}/freemarker.jar" />
 </path>
 <path id = "all-in-one.path">
  <path refid = "hibernate3.path" />
  <path refid = "mysql.jdbc.driver.path" />
  <path refid = "hibernate-tools.path" />
  <path refid = "freemarker.path" />
  <pathelement location = "${configuration-files.dir}" />
 </path>

 <target name = "hbm2java">
  <taskdef name = "hbm2java" classname = "org.hibernate.tool.ant.HibernateToolTask" classpathref = "all-in-one.path" />
  <hbm2java destdir = "${java.code.dir}">
   <configuration configurationfile = "${configuration-files.dir}/hibernate.cfg.xml" />
   <hbm2java jdk5 = "true" />
  </hbm2java>
 </target>
 <target name = "hbm2ddl">
  <taskdef name = "hbm2ddl" classname = "org.hibernate.tool.ant.HibernateToolTask" classpathref = "all-in-one.path" />
  <hbm2ddl destdir = "${schema.dir}">
   <configuration configurationfile = "${configuration-files.dir}/hibernate.cfg.xml" />
   <hbm2ddl export="true" console="false" create="true" update="false" drop="false" outputfilename="courseChoosing.sql" />
  </hbm2ddl>
 </target>

</project>

很平常的ant脚本,需要注意的是那两个特殊的任务:hbm2java和hbm2ddl,这两个任务是hibernatetools里带的,需要定义出来,就不多说了。

好了,安装好ant之后就可以运行这个脚本了,生成java文件:

 

 

生成数据库表:

 

大功告成了,欣赏一下结果:

在java文件夹中生成的java文件代码:

Course.java文件:

package courseChoosing;
// Generated 2007-3-7 15:38:42 by Hibernate Tools 3.2.0.b9


import java.util.HashSet;
import java.util.Set;

/**
 * Course generated by hbm2java
 */
public class Course  implements java.io.Serializable {


     private long id;
     private String name;
     private Integer credit;
     private Integer totalClasses;
     private Set<Student> students = new HashSet<Student>(0);

    public Course() {
    }

    public Course(String name, Integer credit, Integer totalClasses, Set<Student> students) {
       this.name = name;
       this.credit = credit;
       this.totalClasses = totalClasses;
       this.students = students;
    }
  
    public long getId() {
        return this.id;
    }
   
    public void setId(long id) {
        this.id = id;
    }
    public String getName() {
        return this.name;
    }
   
    public void setName(String name) {
        this.name = name;
    }
    public Integer getCredit() {
        return this.credit;
    }
   
    public void setCredit(Integer credit) {
        this.credit = credit;
    }
    public Integer getTotalClasses() {
        return this.totalClasses;
    }
   
    public void setTotalClasses(Integer totalClasses) {
        this.totalClasses = totalClasses;
    }
    public Set<Student> getStudents() {
        return this.students;
    }
   
    public void setStudents(Set<Student> students) {
        this.students = students;
    }

 


}

Student.java文件中的内容:

package courseChoosing;
// Generated 2007-3-7 15:38:42 by Hibernate Tools 3.2.0.b9


import java.util.HashSet;
import java.util.Set;

/**
 * Student generated by hbm2java
 */
public class Student  implements java.io.Serializable {


     private long id;
     private String stuNo;
     private String name;
     private Character gender;
     private Set<Course> courses = new HashSet<Course>(0);

    public Student() {
    }

    public Student(String stuNo, String name, Character gender, Set<Course> courses) {
       this.stuNo = stuNo;
       this.name = name;
       this.gender = gender;
       this.courses = courses;
    }
  
    public long getId() {
        return this.id;
    }
   
    public void setId(long id) {
        this.id = id;
    }
    public String getStuNo() {
        return this.stuNo;
    }
   
    public void setStuNo(String stuNo) {
        this.stuNo = stuNo;
    }
    public String getName() {
        return this.name;
    }
   
    public void setName(String name) {
        this.name = name;
    }
    public Character getGender() {
        return this.gender;
    }
   
    public void setGender(Character gender) {
        this.gender = gender;
    }
    public Set<Course> getCourses() {
        return this.courses;
    }
   
    public void setCourses(Set<Course> courses) {
        this.courses = courses;
    }

 


}

 

schema文件夹中生成的courseChoosing.sql文件内容:

create table course (id bigint not null auto_increment, name varchar(50), credit integer, totalClasses integer, primary key (id));
create table courseChoosing (studentId bigint not null, courseId bigint not null, primary key (studentId, courseId));
create table student (id bigint not null auto_increment, stuNo varchar(10), name varchar(20), gender char(1), primary key (id));
alter table courseChoosing add index FK42CD624F924EFB30 (courseId), add constraint FK42CD624F924EFB30 foreign key (courseId) references course (id);
alter table courseChoosing add index FK42CD624F417DBA12 (studentId), add constraint FK42CD624F417DBA12 foreign key (studentId) references student (id);

生成的数据库表(MySQL Administrator):

分享到:
评论

相关推荐

    hibernate3 配置hbm2ddl和hbm2java所需jar

    - hibernate-tools.jar:这个库包含了hbm2ddl和hbm2java工具以及其他辅助工具,如逆向工程(reverse engineering)等功能。 - jboss-logging.jar:提供日志记录服务,Hibernate使用这个库进行内部的日志输出。 - dom...

    Middlegen插件利用数据库表自动生成Hbm文件

    除了Hbm文件,Middlegen还可以生成POJO(Plain Old Java Object)类,即与数据库表一一对应的Java实体类,以及DDL(Data Definition Language)脚本,用于创建或更新数据库表结构。 在实际开发中,可以结合Ant工具...

    用Hibernate自带的工具(DDL2java).doc

    ### 使用Hibernate自带的工具(DDL2java)生成POJO文件详解 #### 一、概述 在Java开发领域,特别是基于数据库的应用程序开发中,Hibernate框架因其强大的对象关系映射(ORM)能力而受到广泛欢迎。它能够将Java对象与...

    利用hibernate中的SchemaExport生成数据表

    在传统的开发流程中,我们通常先创建数据库表,然后通过反向工程生成`.hbm.xml`映射文件和对应的Java实体类(POJO)。然而,这种方式在面向对象思维主导的现代开发中可能显得不太自然。相反,我们可以直接从对象模型...

    Hibernate实践例子程序

    2. Hibernate Extention,用来自动生成与那些*.hbm.xml对应的POJO,也就是根据那些对象关系映射的配置文件生成相应的class文件。 HibernateEx里面有一个hbm2java工具,就是用来根据些配置文件生成相应的POJO class。...

    hibernate-extensions和Middlegen-Hibernate

    它通过读取数据库的表结构,自动创建对应的实体类(POJO)、持久化接口(PersistentBean)、以及对应的hbm.xml映射文件。这样,开发者就可以专注于业务逻辑,而无需关心底层的数据访问层细节。Middlegen-Hibernate的...

    SSH和DWR简单整合,还包括了根据Pojo反向生成数据库的经典代码

    3. **使用Hibernate Tools**:运行Hibernate的hbm2ddl命令,它会根据Pojo类生成数据库DDL(Data Definition Language),自动创建或更新数据库表。 **学习资源与实践建议:** 对于初学者,可以通过搭建简单的SSH+...

    Hibernate Tool 使用文档

    Hibernate Tools支持多种类型的导出器,如用于生成数据库模式的`hbm2ddl`、用于生成Java源码的`hbm2java`等。 #### 三、Eclipse Plugins - **Introduction**:Eclipse插件为开发者提供了一个图形化的界面来管理...

    Hibernate 课件_配置文件详解

    通过以上介绍,我们不仅了解了Hibernate配置文件的基本结构和关键属性,还深入探讨了JDBC参数、连接池配置以及POJO类与数据库映射的实现机制。这对于深入理解和掌握Hibernate的工作原理至关重要。希望这些知识点能...

    Hibernate自动创建表结构示例--Oracle

    标题"Hibernate自动创建表结构示例--Oracle"表明我们将使用Hibernate在Oracle数据库中自动生成表结构,这是通过Hibernate的`hibernate.hbm2ddl.auto`配置属性实现的。这个属性可以设置为"create"、"update"、...

    用Hibernate3.1实现XML和数据库的同步

    6. **SchemaExport工具**:`org.hibernate.tool.hbm2ddl.SchemaExport`工具可用于根据`.hbm.xml`文件自动生成数据库表结构,简化了数据库初始化和维护工作。 #### 实践步骤详解 - **环境搭建**:首先,需确保已...

    hibernate正向工程和逆向工程

    - 在`hibernate.cfg.xml`配置文件中设置数据库连接信息,并将`hibernate.hbm2ddl.auto`设置为`create`,重启Tomcat即可根据映射文件生成数据库表。 #### 三、逆向工程 逆向工程则是指从已有的数据库表结构出发,...

    hibernate工具参考指南(英文版)

    - **Exporters**:这部分讨论了如何使用不同的导出器来生成不同类型的输出,比如数据库模式、Java POJO类或Hibernate映射文件。 #### 四、Eclipse插件 **知识点详解:** - **下载基本项目**:介绍了如何下载一个...

    hibernate介绍

    4. **DDL 自动更新**:可以通过在 hibernate.cfg.xml 中设置 `hbm2ddl.auto` 属性来自动创建或更新数据库表结构。例如,设置为 `update` 表示将在启动时自动更新数据库表结构。 5. **测试集成**:为了验证 ...

    Hibernate学习笔记

    通过数据库连接,可以自动生成`hbm.xml`映射文件、POJO类以及DAO(Data Access Object)层的代码。在`hibernate.cfg.xml`中设置`hbm2ddl.auto`属性为`update`,可以在启动应用时自动更新数据库结构。 延迟加载是一...

    hibernate映射

    在具体操作中,比如使用Middlegen从数据库定义文件生成映射文件,涉及到的配置参数有: - `database.script.file`:指向创建数据库的SQL脚本文件路径。 - `database.driver.file`:包含数据库JDBC驱动的jar文件路径...

    spring3.2+strut2+hibernate4

    &lt;prop key="hibernate.hbm2ddl.auto"&gt;update ${jdbc.username} &lt;property name="annotatedClasses"&gt; &lt;!-- 此处hibernate 的映射采用的是.xml 配置同则应设置name=”mappingResource”--&gt; ...

    hibernate 详细配置

    根据提供的文件信息,我们可以深入探讨Hibernate的详细配置与使用方法。 ### Hibernate简介 Hibernate是一个开源的对象关系映射(ORM)框架,它为Java应用程序提供了一种将对象模型映射到数据库的方法,允许开发者...

Global site tag (gtag.js) - Google Analytics