转自:http://qiaomuren.blog.hexun.com/11855630_d.html
良好的模型对于高效的开发高性能的应用系统是至关重要的。每个团队在进行设计时都必须得进行选择:是用纯OOD/OOA的思想进行对象建模或者用面向关系数据的思想进行E-R建模,这是个艰难的抉择!选择其中的每一种都会导致不同的开发流程,其中各有利弊。
下面是使用对象建模的一些工具和方法步骤:
流程:类图—>Java源代-à(加Xdoclet)-à映射文件(.hbm.xml)-à数据库表-à物理数据模型(如果需要的话)
1、 先用对象建模工具(例如rose)把类图设计好。在该步骤中要注意把各个类之间的关系(如一对一、一对多、多对多)搞清楚,这使得下一步添加Xdoclet时工作量比较小。
2、 用对象建模工具从设计好的类图中导出Java源代码。
3、 导出源代码后就可在源代码中添加Xdoclet标签了,这些标签用于生成Hibernate的映射文件。在添加Xdoclet标签时要注意的是:要把Xdoclet标签加在每个属性的getter()方法之前,如果只在属性前加标签生成映射文件时就会报错。
举个例子,有一个人的实体类,我们在加Xdoclet时要特别注意,不要只加在属性之前,而是要加在每个属性的getter()方法之前,事实上可以不在属性之前加Xdoclet标签,如下所示例子中有一个Set类型的address属性,元素是Address对象(例子没有给出),假设一个人有多个地址,这是一个一对多的关系,在配置一对多和多对多关系时有几点要注意:
import java.io.Serializable;
import java.util.Set;
import java.util.HashSet;
/**
* @hibernate.class
* table="Tperson"
*
*/
public class Person implements Serializable {
private Long personId;
private String name;
private int age;
private Set address = new HashSet(); //在这一定要实例化address对象
//我们应该在这加Xdoclet
/**
* 年龄
* @hibernate.property
* type="int"
* column="age"
*/
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
/**
* 用户ID
* @hibernate.id
* generator="native"
* type="java.lang.Long"
* column="personId"
*/
public Long getPersonId() {
return personId;
}
public void setPersonId(Long personId) {
this.personId = personId;
}
/**
* 用户姓名
* @hibernate.property
* type="java.lang.String"
* column="name"
* length="32"
* not-null="true"
*/
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/**
* 用户地址
* @hibernate.set
* table-"Taddress"
* class="Address"
*
* @hibernate.collection-key
* column="personId"
*
* 注意下面是collection-one-to-many而不是one-to-many
* 对于多对多关系也是这样collection-many-to-many
* @hibernate.collection-one-to-many
* class="Person"
*/
public Set getAddress() {
return address;
}
public void setAddress(Set address) {
this.address = address;
}
}
加完了这些Xdoclet我们就可以用工具生成映射文件了。一般用得较多的Xdoclet的Hibernate标签有:
@hibernate.class
@hibernate.id
@hibernate.property
@hibernate.set
@hibernate.many-to-one
以上只给出了一些经常用的标记,大家在开发时可参考Xdoclet手册。
4、 在Myeclipse project的properties窗口,选择左侧的“MyEclipse-XDoclet”,“Add Standard...”,“Choose an entry”这儿选择“Standard Hibernate”。如下图:右键电击你的工程,然后选择属性,你就会看到这个图。然后选择Myeclipse选项就会看到其中有一个子选项Xdoclet,点击Xdoclet出现如下界面,然后点击Add Standard按钮,选择其中的Standard Hibernate,我们可以看到,Xdoclet支持很多技术的代码生成。
5、 右键点击工程根目录,选择Myeclipse选项的Run Xdoclet,这样就可以生成映射文件了生成的映射文件默认情况下是和你的POJO在同一目录下。(在这我只举了用Myeclipse工具生成映射文件,你也可以用其他方式生成,可选工具:Xdoclet—1.2.3(支持Hibernate3)的Ant构建,具体配置请查阅相关资料)
6、这一步要从映射文件生成数据库表。下面写一个测试类来生成数据库表,同时也一定程度上验证了我们的映射文件的配置文件是否正确,如果不正确,那么在生成数据库表时就会发生错误。
import java.io.File;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.HibernateException;
import org.hibernate.cfg.Configuration;
import junit.framework.TestCase;
public class TestHibernate extends TestCase {
protected Session session;
public TestHibernate(String s) {
super(s);
}
protected void setUp() throws Exception {
super.setUp();
try {
Configuration config = new Configuration().configure(new File("C:\\hibernate.cfg.xml"));
SessionFactory factory = config.buildSessionFactory();
session = factory.openSession();
} catch(HibernateException e) {
e.printStackTrace();
}
}
protected void tearDown() throws Exception {
super.tearDown();
try {
session.close();
} catch(HibernateException e) {
e.printStackTrace();
}
}
public void testInsert() {
Transaction tx = null;
try {
tx = session.beginTransaction();
Course course = new Course();
course.setCourseName("computer");
course.setDescription("计算”);
session.save(course);
session.flush();
tx.commit();
} catch(HibernateException e) {
e.printStackTrace();
fail(e.getMessage());
if(tx != null) {
try {
tx.rollback();
} catch(HibernateException err) {
err.printStackTrace();
}
}
}
}
Hibernate配置文件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.url">jdbc:mysql://localhost:3306/webstudy</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="connection.password">root</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.show_sql">True</property>
<property name="hibernate.jdbc.batch_size">25</property>
<property name="hibernate.jdbc.fatch_size">25</property>
<property name="myeclipse.connection.profile">MySQL</property>
注意在这加上下面这一行:可选值:update,create,create-drop;Hibernate在加载该配置文件时会自动检测数据库表是否存在。如果设为update,如果数据库表不存在,则Hibernate会使用SchemaExport工具导出该表的定义然后创建该表。
<property name="hibernate.hbm2ddl.auto">update</property>
<mapping resource="Person.hbm.xml"/>
</session-factory>
</hibernate-configuration>
(可选工具:Hibernate Synchronizer Eclipse插件(这个工具支持正向工程和反向工程))
7、 数据库表自动创建完毕,单元测试顺利通过。
8、日后如果对Java代码进行重构时,如果修改量不大我们可以手动去修改映射文件和数据库表的定义以达到三者之间的同步;而如果重构范围很大,我们完全可以重复以上的过程来达到三者同步的目的。
下面来总结一下我对面向对象建模的一些看法:
<1> 优点:完全采用OOA/OOD的思想,完全以Java代码为中心进行开发
<2>缺点:手工添加Xdoclet工作量大,而且容易出错,并且要配置好一些关键性的东西,否则Hibernate的性能会很差。
下面是使用E-R建模的一些工具和方法步骤:
流程:物理数据模型-à数据库表-à映射文件(.hbm.xml)-àJava源代码
1、 用E-R建模工具(如Power Designer或者Erwin)把物理数据模型建好
2、 用这些工具导出数据库表的定义,然后生成数据库表
3、 表生成后我们可以用Middlegen来生成映射文件,Middlegen有一个专门的Hibernate的工具Middlegen—Hibernate-r5,它依赖于Ant(也有个eclipse插件),我们就用它来生成映射文件。下载了该工具后首先要修改config/database下面的mysql.xml文件,如果你用的是其他的数据库,则修改对应的xml文件,它支持多种数据库,修改后要把mysql的JDBC驱动程序加入CLASSPATH。
<property name="database.script.file" value="${src.dir}/sql/${name}-mysql.sql"/>
<property name="database.driver.file" value="${lib.dir}/mysql-connector-java-5.0.3-bin.jar"/>
<property name="database.driver.classpath" value="${database.driver.file}"/>
<property name="database.driver" value="com.mysql.jdbc.Driver"/>
<property name="database.url" value="jdbc:mysql://localhost/webstudy"/>
<property name="database.userid" value="root"/>
<property name="database.password" value="root"/>
<property name="database.schema" value=""/>
<property name="database.catalog" value=""/>
<property name="jboss.datasource.mapping" value="mySQL"/>
上面的一些参数你可以根据实际情况进行修改。
然后修改根目录下的build.xml文件的开始部分,指定使用mysql.xml配置文件。
<!DOCTYPE project [
<!ENTITY database SYSTEM "file:./config/database/mysql.xml">
]>
为了在映射文件中生成Xdoclet,我们找到Middlegen任务的子任务Hibernate部分:
<hibernate
destination="${build.gen-src.dir}"
package="${name}.hibernate"
genXDocletTags="false"
genIntergratedCompositeKeys="false"
javaTypeMapper="middlegen.plugins.hibernate.HibernateJavaTypeMapper"
/>
其中destination是生成的映射文件的目录,你可以自己修改到合适的路径
Package属性你指定你的类的包名,genXDocletTags是是否在映射文件中产生Xdoclet,如果为true,则在映射文件中会加人Xdoclet,生成Java源代码时这些Xdoclet也会被抽取到Java源代码中。
指定好以上参数后我们就可以运行build.xml文件了,你要先搭建好Ant构建环境。到达build.xml文件所在的目录后从命令行输入ant,middlegen就会自动运行了,如下图:
我们可以改变两个实体的关系和方向,默认它会生成双向关系。点击每个实体可以修改它的一些配置。修改好后点击Generate就可以产生Hibernate映射文件了,全部生产在你之前指定的目录下。查看它生成的文件我们会发现它生成的映射文件并不完美,它把那些多对多关系的交叉表也生成了,而且在生成的映射文件中的多对多的关系配置还有点问题,但是用工具生成比手工编写出错的几率要小得多,而且效率也要高得多,在项目的初期我们可以使用这个工具大规模的生成映射文件,在中、后期如果我们对Java文件或者映射文件进行重构后我们就不应该使用Middlegen了,而是通过正向工程来同步三者。
4、 对上一步生成的映射文件做好修改后我们就可以生成Java源文件了。我们可以用Hibernate Synchronizer Eclipse插件来生成,也可以直接用Myeclipse生成(如果你已经装了的话)。如果使用Myeclipse生成Java源代码,我们只需要右键点击映射文件,然后选择Myeclipse选项的子选项Gen POJO,生成的Java源代码默认和映射文件在同一目录下。如果装了Hibernate Synchronizer Eclipse插件,右键点击映射文件你会看到Synchronizer选项,生成的方式与Myeclipse基本上一样。
5、 生成的Java源代码和上面用面向对象方法时我们在Java源代码中加入Xdoclet后基本上一样的。需要注意的是如果我们需要对数据库表字段进行修改,我们不再使用Middlegen了,否则它重新生成的映射文件会把我们已经修改的映射文件给覆盖掉,而我们应该用面向对象的方式从Java源代码到映射文件在到数据库表,或者我们完全可以以映射文件中的Xdoclet为中心,向上生成Java源代码,向下生成数据库表,这些根据你的喜好,两者没有太大的区别。
下面我来总结一下我对E-R建模的一些看法:
优点:工具生成代码效率高,而且不易出错,可用于项目初期大规模生成映射文件,在日常的项目中是用得最多的。
缺点:工具并不是万能的,生成的代码并不尽善尽美。而且在用Middlegen生成的那一步中,如果表很多时在它的那个图形用户界面显示出来的实体将惨不忍睹,密密麻麻,可能你没有耐心去调整那些实体的关系了。
综上所诉,目前我们在开发面向对象应用时还不能完全抛弃E-R建模,因为目前还没有哪个工具足够强大从对象模型到Java源代码在到映射文件和数据库表的自动完美的构建,所以我们在开发项目时应该根据实际情况进行选择,比如说如果公司有一批精通数据库建模的精英队伍,那我们就要充分利用这些宝贵的资源,而不是一味的采取面向对象的思想去开发。