Atea - Hero's Grave

面向对象,开源,框架,敏捷,云计算,NoSQL,商业智能,编程思想。

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  40 随笔 :: 0 文章 :: 28 评论 :: 0 Trackbacks
XDoclet是一款开源的代码自动生成引擎,支持很多框架的代码自动生成。
而XDoclet2作为Maven2的插件,支持Hibernate3的pojo->xml的代码自动生成。配合ant与Hibernate Tool API,可以实现pojo<->xml<->db schema的相互转化。具体关系为:
 生成处理  实用工具
 pojo->xml  XDoclet2
 xml->pojo
 Hibernate Tool API
 pojo+xml -> db schema  Hibernate Tool API
 db schema -> pojo+xml
 可用myeclipse,本文不涉及

下面通过ANT脚本例子,来展示如何完成以上的转换。
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <project name="xdoclet_example">
 3 
 4     <!--xdoclet的jar包所在目录-->
 5     <property name="xdoclet.plugin.install.dir" value="./lib/xdoclet" />
 6     <!--待处理项目的src目录-->
 7     <property name="src.dir" value="./src" />
 8     <!--待处理项目的根目录-->
 9     <property name="prj.dir" value="./" />
10 
11     <!--include进来xdoclet所有jar包-->
12     <path id="xdoclet.task.classpath" description="xdoclet的所有jar">
13         <fileset dir="${xdoclet.plugin.install.dir}">
14             <include name="**/*.jar" />
15         </fileset>
16     </path>
17     <!--include进来待处理项目的所有jar包,意在使用hibernate相关的jar包-->
18     <path id="prj.jar" description="项目目录下的所有jar">
19         <fileset dir="${prj.dir}">
20             <include name="**/*.jar" />
21         </fileset>
22     </path>
23     <!--
24         继承上2个目录,同时需要把pojo编译好的class文件包含进来。
25         这里定义需要留意,很容易掉入到ant的bug陷阱里去。
26         详细可参照http://www.blogjava.net/boluobn/articles/136197.html
27     -->
28     <path id="runtime.path" description="SchemaExport用的jar和class文件">
29         <path refid="xdoclet.task.classpath" />
30         <path refid="prj.jar" />
31         <pathelement location="${prj.dir}/build/classes" />
32     </path>
33 
34     <!--
35         xdoclet只在判断未存在hbm.xml的情况下才会生成,已存在的话则不会自动覆盖。
36         所以定义一个清空已存在的hbm.xml文件任务。
37     -->
38     <target name="clean" description="清空已有的hbm.xml">
39         <echo message="清空已有的hbm.xml" />
40         <delete dir="src">
41             <include name="**/po/*.hbm.xml" />
42         </delete>
43     </target>
44 
45     <!--根据pojo生成hbm.xml,注意一下pojo的路径即可-->
46     <target name="xdoclet2hbm" description="根据pojo生成hbm.xml" depends="clean">
47         <echo message="根据pojo生成hbm.xml" />
48         <taskdef name="xdoclet" classname="org.xdoclet.ant.XDocletTask" classpathref="xdoclet.task.classpath" />
49         <xdoclet encoding="utf-8">
50             <fileset dir="${src.dir}">
51                 <include name="**/po/*.java" />
52             </fileset>
53             <component classname="org.xdoclet.plugin.hibernate.HibernateMappingPlugin" destdir="${basedir}/${src.dir}" version="3.0" />
54         </xdoclet>
55     </target>
56 
57     <!--根据hibernate.cfg.xml文件生成pojo-->
58     <target name="hbm2java" description="根据hbm.xml文件生成pojo">
59         <echo message="根据hbm.xml文件生成pojo" />
60         <taskdef name="hbm2java" classname="org.hibernate.tool.ant.HibernateToolTask" classpathref="runtime.path" />
61         <hbm2java destdir="${src.dir}">
62             <configuration configurationfile="${src.dir}/hibernate.cfg.xml" />
63             <hbm2java />
64         </hbm2java>
65     </target>
66 
67     <!--
68         生成数据库环境的任务。
69         这个可能并不常用,使用org.hibernate.tool.hbm2ddl.SchemaExport编写一个JUnit test可以更方便的连搭环境带造数据。
70     -->
71     <target name="SchemaExport" description="根据hibernate.cfg.xml生成数据库环境">
72         <echo message="根据hibernate.cfg.xml生成数据库环境" />
73         <taskdef name="schemaexport" classname="org.hibernate.tool.hbm2ddl.SchemaExportTask" classpathref="runtime.path" />
74         <schemaexport config="${src.dir}/hibernate.cfg.xml" quiet="false" text="false" drop="false" delimiter=";" output="schema-export.sql" />
75     </target>
76 
77 </project>
脚本很详细,看注释即可。

在使用xdoclet2hbm前,需要在pojo上设定javadoc注释,以告诉xdoclet如何进行解析。
one2one & one2many的例子:
Child.java
 1 package po;
 2 
 3 /**
 4  * @hibernate.class table="child"
 5  */
 6 @SuppressWarnings("serial")
 7 public class Child implements java.io.Serializable {
 8 
 9     //xdoclet注释有写在getter上与写在field上2种方法。
10     //写在field上会自动生成access="field",所以写在getter上更常用一些。
11 
12     private String id;
13     private String name;
14     private Father father;
15 
16     /**
17      * @hibernate.id generator-class="uuid.hex" column="id" length="32"
18      */
19     public String getId() {
20         return this.id;
21     }
22 
23     public void setId(String id) {
24         this.id = id;
25     }
26 
27     //基本支持所有的hibernate 属性,所以想要啥设置就大胆的写吧
28     /**
29      * @hibernate.property column="name" length="32" not-null="true" type="java.lang.String" lazy="true"
30      */
31     public String getName() {
32         return this.name;
33     }
34 
35     public void setName(String name) {
36         this.name = name;
37     }
38 
39     /**
40      * @hibernate.many-to-one column="father_id" not-null="true"
41      */
42     public Father getFather() {
43         return this.father;
44     }
45 
46     public void setFather(Father father) {
47         this.father = father;
48     }
49 
50 }

Father.java
 1 package po;
 2 
 3 import java.util.HashSet;
 4 import java.util.Set;
 5 
 6 /**
 7  * @hibernate.class table="father"
 8  */
 9 @SuppressWarnings("serial")
10 public class Father implements java.io.Serializable {
11 
12     private String id;
13 
14     private String name;
15 
16     private Integer age;
17 
18     private Set<Child> children = new HashSet<Child>(0);
19 
20     /**
21      * @hibernate.id generator-class="uuid.hex" column="id" length="32"
22      */
23     public String getId() {
24         return this.id;
25     }
26 
27     public void setId(String id) {
28         this.id = id;
29     }
30 
31     /**
32      * @hibernate.property column="name" length="32" not-null="true" type="java.lang.String"
33      */
34     public String getName() {
35         return this.name;
36     }
37 
38     public void setName(String name) {
39         this.name = name;
40     }
41 
42     /**
43      * @hibernate.property column="age" length="32" type="java.lang.Integer"
44      */
45     public Integer getAge() {
46         return age;
47     }
48 
49     public void setAge(Integer age) {
50         this.age = age;
51     }
52 
53     /**
54      * @hibernate.set table="child"
55      * @hibernate.key column="father_id"
56      * @hibernate.one-to-many class="po.Child"
57      */
58     public Set<Child> getChildren() {
59         return children;
60     }
61 
62     public void setChildren(Set<Child> children) {
63         this.children = children;
64     }
65 }

many2many的例子:
Student.java
 1 package po;
 2 
 3 import java.util.HashSet;
 4 import java.util.Set;
 5 
 6 /**
 7  * @hibernate.class table="student"
 8  */
 9 @SuppressWarnings("serial")
10 public class Student implements java.io.Serializable {
11 
12     private String id;
13     private String name;
14     private Set<Teacher> teachers = new HashSet<Teacher>(0);
15 
16     /**
17      * @hibernate.id generator-class="uuid.hex" column="id" length="32"
18      */
19     public String getId() {
20         return this.id;
21     }
22 
23     public void setId(String id) {
24         this.id = id;
25     }
26 
27     /**
28      * @hibernate.property column="name" length="32" not-null="true" type="java.lang.String"
29      */
30     public String getName() {
31         return this.name;
32     }
33 
34     public void setName(String name) {
35         this.name = name;
36     }
37 
38     /**
39      * @hibernate.set table="student_teacher_relation"
40      * @hibernate.key column="student_id"
41      * @hibernate.many-to-many class="po.Teacher" column="teacher_id"
42      */
43     public Set<Teacher> getTeachers() {
44         return teachers;
45     }
46 
47     public void setTeachers(Set<Teacher> teachers) {
48         this.teachers = teachers;
49     }
50 }

Teacher.java
 1 package po;
 2 
 3 import java.util.HashSet;
 4 import java.util.Set;
 5 
 6 /**
 7  * @hibernate.class table="teacher"
 8  */
 9 @SuppressWarnings("serial")
10 public class Teacher implements java.io.Serializable {
11 
12     private String id;
13     private String name;
14     private Set<Student> students = new HashSet<Student>(0);
15 
16     /**
17      * @hibernate.id generator-class="uuid.hex" column="id" length="32"
18      */
19     public String getId() {
20         return this.id;
21     }
22 
23     public void setId(String id) {
24         this.id = id;
25     }
26 
27     /**
28      * @hibernate.property column="name" length="32" not-null="true" type="java.lang.String"
29      */
30     public String getName() {
31         return this.name;
32     }
33 
34     public void setName(String name) {
35         this.name = name;
36     }
37 
38     /**
39      * @hibernate.set table="student_teacher_relation"
40      * @hibernate.key column="teacher_id"
41      * @hibernate.many-to-many class="po.Student" column="student_id"
42      */
43     public Set<Student> getStudents() {
44         return students;
45     }
46 
47     public void setStudents(Set<Student> students) {
48         this.students = students;
49     }
50 
51 }

总结:
1.本文没有涉及hibernate annnotation模式,需要者请自行查阅相关资料。
2.XDoclet2没有XDoclet1代好找,推荐一个网址 Jar Search Engine
3.本文未能涉及在开发中,程序运转时遇到DB schema结构变化而进行的动态自动转换技术。如有高人知晓,请不吝赐教。
posted on 2009-08-01 22:35 Atea 阅读(1100) 评论(2)  编辑  收藏 所属分类: HibernateAnt

评论

# re: 使用XDoclet2+Ant实现Hibernate3的pojo-xml-db代码相互转换[未登录] 2010-08-11 23:38 lixl
请问 pojo转换.hbm.xml 的脚本如何执行呢?请指教 详解  回复  更多评论
  

# re: 使用XDoclet2+Ant实现Hibernate3的pojo-xml-db代码相互转换[未登录] 2010-08-17 20:27 Atea
@lixl
1、注意一下pojo的路径
把这句话改成你自己的:
<include name="**/po/*.java" />
2、在po里写javadoc
3、执行ant xdoclet2hbm

PS:
一年之后,反观xml配置方式已不如annotation来得方便
只在一些有特殊要求的项目中用

  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航: