Hibernate映射文件生成器by LDDXFS

本文由 http://www.cnblogs.com/LDDXFS/ 原创,转载请注明本文出处。(新版本的代码生成器写好了,新版本设计上更合理,会在近期对其进行相关介绍,打算在工作稳定后开源,本文为旧版本)

关于代码生成器,JBOSS的Hibernate Tool插件也有hbm.xml生成功能,自己写这个生成器的目的是为了代码简洁一些

1作用

它根据.properties文件上定义的参数扫描某文件夹下XXX.java文件, 依据xml模板文件生成Hibernate的映射文件 XXX.hbm.xml

可以提取XXX.java文件中字段上的doc注释到XXX.hbm.xml文件对应的配置上

支持的关联关系有 一对一,一对多Set List,多对一。

最终 生成的hbm.xml文件如下

 1 <?xml version="1.0"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
 4 <hibernate-mapping package="cn.lddxfs.tieba.domain">
 5     <class name="AdminUser" table="tiebaTB_AdminUser">
 6 <!--id-->
 7 <id name="id" column="id">
 8     <generator class="native"></generator>
 9 </id>
10 <!--用户名-->
11 <property name="name" unique="true"></property>
12 <!--邮箱,登陆时使用-->
13 <property name="email" unique="true"></property>
14 <!--密码-->
15 <property name="password"></property>
16 <!--UUID用于激活-->
17 <property name="uuid"></property>
18 <!--状态,已经启用,为激活-->
19 <!-- status属性,表达的是本类AdminUser与DataDictoryValue的多对一 
20     class属性:关联的实体类型
21     column属性:外键列(引用关联对象的表的主键)
22 -->
23 <many-to-one name="status" class="DataDictoryValue" column="statusId"></many-to-one>
24 <!--居民身份证-->
25 <property name="idcard"></property>
26 <!--审核了那些吧-->
27 <!-- baApply属性,List集合,表达的是本类与BaApply的一对多 
28     class属性:关联的实体类型
29     key子元素:对方表中的外键列(多方的那个表)
30             
31     inverse属性:
32         默认为false,表示本方维护关联关系。
33         如果为true,表示本方不维护关联关系。
34         只是影响是否能设置外键列的值(设成有效值或是null值),对获取信息没有影响。
35                 
36     cascade属性:
37         默认为none,代表不级联。
38         级联是指操作主对象时,对关联的对象也做相同的操作。
39         可设为:delete, save-update, all, none ...
40                 
41     lazy属性:懒加载,默认为true。
42         true:懒加载,在第一次使用时加载。
43         false:立即加载,在获取本对象时就加载这个集合的所有元素。
44         extra:增强的懒加载策略。
45 -->
46 <set name="baApply">
47     <key column="adminUserId"></key>
48     <one-to-many class="BaApply"/>
49 </set>
50 </class>
51 </hibernate-mapping>

2依赖的jar文件

3模板文件  src/generator/template/template.xml

  1 <?xml version="1.0" encoding="UTF-8"?>
  2 <beanCache>
  3     <XMLBeans>
  4         <XMLBean>
  5             <type><![CDATA[hbmhead]]></type>
  6             <note></note>
  7             <value>
  8 <![CDATA[
  9 <?xml version="1.0"?>
 10 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 11 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
 12 <hibernate-mapping package="<%package%>">
 13     <class name="<%Class%>" table="<%tableprefix%><%Class%>">
 14 ]]>
 15             </value>
 16         </XMLBean>
 17         <XMLBean>
 18             <type><![CDATA[id]]></type>
 19             <note></note>
 20             <value>
 21 <![CDATA[
 22 <id name="<%key%>" column="<%keyColumn%>">
 23     <generator class="native"></generator>
 24 </id>
 25 ]]>
 26             </value>
 27         </XMLBean>
 28         <XMLBean>
 29             <type><![CDATA[hbmfoot]]></type>
 30             <note></note>
 31             <value>
 32 <![CDATA[
 33     </class>
 34 </hibernate-mapping>
 35 ]]>
 36             </value>
 37         </XMLBean>
 38         <XMLBean>
 39             <type><![CDATA[property]]></type>
 40             <note></note>
 41             <value>
 42 <![CDATA[
 43     <property name="<%field%>"></property>
 44 ]]>
 45             </value>
 46         </XMLBean>
 47         <XMLBean>
 48             <type><![CDATA[picture]]></type>
 49             <note></note>
 50             <value>
 51 <![CDATA[
 52     <property name="<%field%>" length="819200"></property>
 53 ]]>
 54             </value>
 55         </XMLBean>
 56         <XMLBean>
 57             <type><![CDATA[111]]></type>
 58             <note>
 59 <![CDATA[
 60 <!--<%field%>属性,<%Field%>类型。
 61     表达的是本类<%Class%>与<%Field%>的一对一。
 62     采用基于外键的一对一映射方式,本方<%Field%>是有外键方。
 63 -->
 64 ]]>
 65             </note>
 66             <value>
 67 <![CDATA[
 68 <many-to-one name="<%field%>" class="<%Field%>" column="<%field%>Id" unique="true"></many-to-one>
 69 ]]>
 70             </value>
 71         </XMLBean>
 72         <XMLBean>
 73             <type><![CDATA[110]]></type>
 74             <note>
 75 <![CDATA[
 76 <!-- <%field%>属性,<%Field%>类型。
 77     表达的是本类<%Class%>与<%Field%>的一对一。
 78     采用基于外键的一对一映射方式,本方<%Class%>是无外键方。
 79     property-ref属性:
 80         写的是对方<%Field%>映射中外键列对应的属性名<%class%>。    
 81 -->
 82 ]]>
 83             </note>
 84             <value>
 85 <![CDATA[
 86 <one-to-one name="<%field%>" class="<%Field%>" property-ref="<%class%>"/>
 87 ]]>
 88             </value>
 89         </XMLBean>
 90         <XMLBean>
 91             <type><![CDATA[1nSet]]></type>
 92             <note>
 93 <![CDATA[
 94 <!-- <%field%>属性,Set集合,表达的是本类与<%Field%>的一对多 
 95     class属性:关联的实体类型
 96     key子元素:对方表中的外键列(多方的那个表)
 97             
 98     inverse属性:
 99         默认为false,表示本方维护关联关系。
100         如果为true,表示本方不维护关联关系。
101         只是影响是否能设置外键列的值(设成有效值或是null值),对获取信息没有影响。
102                 
103     cascade属性:
104         默认为none,代表不级联。
105         级联是指操作主对象时,对关联的对象也做相同的操作。
106         可设为:delete, save-update, all, none ...
107                 
108     lazy属性:懒加载,默认为true。
109         true:懒加载,在第一次使用时加载。
110         false:立即加载,在获取本对象时就加载这个集合的所有元素。
111         extra:增强的懒加载策略。
112 -->
113 ]]>
114             </note>
115             <value>
116 <![CDATA[
117 <set name="<%field%>" cascade="all" lazy="true">
118     <key column="<%class%>Id"></key>
119     <one-to-many class="<%Field%>"/>
120 </set>
121 ]]>
122             </value>
123         </XMLBean>
124         <XMLBean>
125             <type><![CDATA[1nList]]></type>
126             <note>
127 <![CDATA[
128 <!-- <%field%>属性,List集合,表达的是本类与<%Field%>的一对多 
129     class属性:关联的实体类型
130     key子元素:对方表中的外键列(多方的那个表)
131             
132     inverse属性:
133         默认为false,表示本方维护关联关系。
134         如果为true,表示本方不维护关联关系。
135         只是影响是否能设置外键列的值(设成有效值或是null值),对获取信息没有影响。
136                 
137     cascade属性:
138         默认为none,代表不级联。
139         级联是指操作主对象时,对关联的对象也做相同的操作。
140         可设为:delete, save-update, all, none ...
141                 
142     lazy属性:懒加载,默认为true。
143         true:懒加载,在第一次使用时加载。
144         false:立即加载,在获取本对象时就加载这个集合的所有元素。
145         extra:增强的懒加载策略。
146 -->
147 ]]>
148             </note>
149             <value>
150 <![CDATA[
151 <list name="<%field%>">
152     <key column="<%class%>Id"></key>
153     <list-index column="<%Class%>_<%field%>_idx"></list-index>
154     <one-to-many class="<%Field%>"/>
155 </list>
156 ]]>
157             </value>
158         </XMLBean>
159         <XMLBean>
160             <type><![CDATA[n1]]></type>
161             <note>
162 <![CDATA[
163 <!-- <%field%>属性,表达的是本类<%Class%>与<%Field%>的多对一 
164     class属性:关联的实体类型
165     column属性:外键列(引用关联对象的表的主键)
166 -->
167 ]]>
168             </note>
169             <value>
170 <![CDATA[
171 <many-to-one name="<%field%>" class="<%Field%>" column="<%field%>Id"></many-to-one>
172 ]]>
173             </value>
174         </XMLBean>
175         <XMLBean>
176             <type><![CDATA[nnSet]]></type>
177             <note>
178 <![CDATA[
179 <!-- <%field%>属性,Set集合。
180     表达的是本类<%Class%>与<%Field%>的多对多。    
181     table属性:中间表(集合表)
182     key子元素:集合外键(引用当前表主键的那个外键)
183 -->
184 ]]>
185             </note>
186             <value>
187 <![CDATA[
188 <set name="<%field%>" table="<%tableprefix%><%centerTable%>" inverse="false">
189     <key column="<%class%>Id"></key>
190     <many-to-many class="<%Field%>" column="<%field%>Id"></many-to-many>
191 </set>
192 ]]>
193             </value>
194         </XMLBean>
195         <XMLBean>
196             <type><![CDATA[nnList]]></type>
197             <note>
198 <![CDATA[
199 <!-- <%field%>属性,List集合。
200     表达的是本类<%Class%>与<%Field%>的多对多。    
201     table属性:中间表(集合表)
202     key子元素:集合外键(引用当前表主键的那个外键)
203 -->
204 ]]>
205             </note>
206             <value>
207 <![CDATA[
208 <list name="<%field%>" table="<%tableprefix%><%centerTable%>" inverse="false">
209     <key column="<%class%>Id"></key>
210     <list-index column="<%Class%>_<%field%>_idx"></list-index>
211     <many-to-many class="<%Field%>" column="<%field%>Id"></many-to-many>
212 </list>
213 ]]>
214             </value>
215         </XMLBean>
216     </XMLBeans>
217 </beanCache>
View Code

4properties文件  src/generator/generator.properties

 1 #项目名称
 2 project=cn.lddxfs.tieba
 3 #实体所在包名
 4 package=cn.lddxfs.tieba.domain
 5 #实体所在包相对路径
 6 #pathname=src/cn/lddxfs/tieba/domain/
 7 #数据库中表前缀
 8 tableprefix=tiebaTB_
 9 #实体唯一标示符
10 key=id
11 #数据库表主键名
12 keyColumn=id
13 #中间表
14 #centerTable=<%Class%>_<%Field%>
View Code

5 java文件

src/generator/XMLBean.java

 1 package generator;
 2 
 3 public class XMLBean {
 4 
 5     /**
 6      * <pre>
 7      * 基本类型 
 8      * 
 9      * 本方                                          对方
10      * 一对一主键                            一对一外键
11      * ClassA key        ClassB
12      * 
13      * 一对多List                    多对一 
14      * List《ClassA》              ClassB
15      * 
16      * 一对多Set           多对一 
17      * Set《ClassA》               ClassB
18      * 
19      * 多对多List          多对多List
20      * List《ClassA》             List《ClassB》
21      * 
22      * 多对多Set           多对多Set
23      * Set《ClassA》               Set《ClassB》
24      *  dynamic-update="true"
25         dynamic-insert="true"
26      * </pre>
27      */
28     /**
29      * 关联关系类型
30      */
31     private String type;
32     /**
33      * 注释
34      */
35     private String note;
36     /**
37      * 内容,通过type来指定
38      */
39     private String value;
40 
41     public String getType() {
42         return type;
43     }
44 
45     public void setType(String type) {
46         this.type = type;
47     }
48 
49     public String getNote() {
50         return note;
51     }
52 
53     public void setNote(String note) {
54         this.note = note;
55     }
56 
57     public String getValue() {
58         return value;
59     }
60 
61     public void setValue(String value) {
62         this.value = value;
63     }
64 
65 }
View Code

src/generator/XMLBeanCache.java

 1 package generator;
 2 
 3 import java.util.HashMap;
 4 import java.util.Map;
 5 
 6 public class XMLBeanCache {
 7 
 8     private Map<String, XMLBean> XMLBeanMap = new HashMap<String, XMLBean>();
 9     private Boolean hasNote;
10 
11     public Boolean getHasNote() {
12         return hasNote;
13     }
14 
15     public void setHasNote(Boolean hasNote) {
16         this.hasNote = hasNote;
17     }
18 
19     public Map<String, XMLBean> getXMLBeanMap() {
20         return XMLBeanMap;
21     }
22 
23     public void setXMLBeanMap(Map<String, XMLBean> xMLBeanMap) {
24         XMLBeanMap = xMLBeanMap;
25     }
26 
27     /**
28      * 
29      * @param key
30      *            map的key
31      * @return 字符串,hashMap的value 中的XMLBean的内容
32      */
33     public String getXMLBeanStr(String key) {
34         XMLBean xmlBean = this.XMLBeanMap.get(key);
35         if (hasNote) {
36             if (xmlBean.getNote()==null||"".equals(xmlBean.getNote().trim())) {
37                 return xmlBean.getNote() + xmlBean.getValue() + '
';
38             } else {
39                 return xmlBean.getNote() + '
' + xmlBean.getValue() + '
';
40             }
41         }
42         return xmlBean.getValue() + '
';
43     }
44 
45     // 供Digester调用的方法
46     public void addXMLBean(XMLBean xMLBean) {
47         this.XMLBeanMap.put(xMLBean.getType(), xMLBean);
48 
49     }
50 }
View Code

src/generator/XMLBeanDigester.java

 1 package generator;
 2 
 3 import java.io.BufferedReader;
 4 import java.io.FileInputStream;
 5 import java.io.IOException;
 6 import java.io.InputStream;
 7 import java.io.InputStreamReader;
 8 
 9 import org.apache.commons.digester3.Digester;
10 import org.xml.sax.SAXException;
11 
12 public class XMLBeanDigester {
13      public XMLBeanCache digester() throws Exception {  
14             Digester digester = new Digester();  
15             digester.setValidating(false);  
16             digester.addObjectCreate("beanCache/XMLBeans", XMLBeanCache.class);  
17             // 指明匹配模式和要创建的类   
18             digester.addObjectCreate("beanCache/XMLBeans/XMLBean", XMLBean.class);  
19             // 设置对象属性,与xml文件对应,不设置则是默认  
20             digester.addBeanPropertySetter("beanCache/XMLBeans/XMLBean/type", "type");   
21             digester.addBeanPropertySetter("beanCache/XMLBeans/XMLBean/note", "note");   
22             digester.addBeanPropertySetter("beanCache/XMLBeans/XMLBean/value", "value");   
23   
24   
25             // 当移动到下一个标签中时的动作  
26             digester.addSetNext("beanCache/XMLBeans/XMLBean", "addXMLBean");  
27               
28             XMLBeanCache bc = null;  
29             try {  
30                 
31                 InputStream inputStream = new FileInputStream("src/generator/template/template.xml");
32 
33                 BufferedReader bufferedReader = new BufferedReader(
34                         new InputStreamReader(inputStream, "UTF-8"));
35                 
36                 bc = (XMLBeanCache) digester.parse(bufferedReader);
37 //                bc = (BeanCache) digester.parse("beanCache.xml");  
38             } catch (IOException e) {  
39                 throw new Exception(e);  
40             } catch (SAXException e) {  
41                 throw new Exception(e);  
42             }  
43             return bc;
44         }  
45 }
View Code

src/generator/GlobalVar.java

  1 package generator;
  2 
  3 import java.io.File;
  4 import java.io.FileInputStream;
  5 import java.io.InputStream;
  6 import java.util.LinkedList;
  7 import java.util.List;
  8 import java.util.Properties;
  9 
 10 public class GlobalVar {
 11     /**
 12      * 基本数据类型
 13      */
 14     protected String[] BASE_TYPE = new String[] { "Integer", "Long", "String",
 15             "Date", "Boolean","Blob","Clob" };
 16     /**
 17      * 数组类型
 18      */
 19     protected String[] ARRAY_TYPE = new String[] { "byte[]", "Byte[]" };
 20     /**
 21      * 集合数据类型
 22      */
 23     protected String[] COLLECTION_TYPE = new String[] { "List", "Set" };
 24     /**
 25      * 配置文件的路径
 26      */
 27     protected String PROPERTIES_LOCATION = "src/generator/generator.properties";
 28     /**
 29      * 源码文件夹
 30      */
 31     protected String SRC_PATH = "src/";
 32     /**
 33      * class文件的文件编码
 34      */
 35     protected String CHARSET_NAME = "UTF-8";
 36     protected String[] DOMAIN_TYPE = new String[] {};
 37     protected Properties PROPS;
 38     protected String PACKAGE_Str;
 39     protected String PATHNAME;
 40 
 41     public GlobalVar() {
 42         /* 加载资源文件 */
 43         PROPS = new Properties();
 44         InputStream is;
 45         try {
 46             is = new FileInputStream(PROPERTIES_LOCATION);
 47             PROPS.load(is);
 48         } catch (Exception e) {
 49             // TODO Auto-generated catch block
 50             e.printStackTrace();
 51         }
 52 
 53         // 得到包名
 54         PACKAGE_Str = PROPS.getProperty("package");
 55         // 得到路径名 pathname=src/cn/lddxfs/tieba/domain/
 56         PATHNAME = SRC_PATH + PACKAGE_Str.replace('.', '/') + "/";
 57 
 58         // logger.debug("pathname=" + pathname);
 59         /* 得到路径名,得到domain类名迭代器 */
 60         File dir = new File(PATHNAME);
 61         List<String> classNameList = new LinkedList<String>();
 62         listClassName(dir, classNameList);
 63         // Iterator<String> classNameit1 = classNameList.iterator();
 64 
 65         DOMAIN_TYPE = classNameList.toArray(new String[0]);
 66         for(String name:DOMAIN_TYPE){
 67             System.out.println(name);
 68         }
 69 
 70     }
 71 
 72     /**
 73      * 列出指定目录下的java文件的类名 ,例如 如果有文件“Person.java” ,则列出“Person”
 74      * 
 75      * @param file
 76      *            指定一个目录
 77      * @param classNameList
 78      *            返回的类名列表 ,无“.java”后缀
 79      */
 80     private void listClassName(File file, List<String> classNameList) {
 81         if (file == null) {
 82             return;
 83         }
 84         if (file.isDirectory()) {
 85             File f[] = file.listFiles();
 86             if (f != null)
 87                 for (int i = 0; i < f.length; i++) {
 88                     listClassName(f[i], classNameList);
 89                 }
 90         } else {
 91 
 92             if (file.getName().endsWith(".java")) {
 93                 String str = (file.getName().substring(0, file.getName()
 94                         .length() - 5));
 95 
 96                 classNameList.add(str);
 97             }
 98         }
 99     }
100 
101 }

一个重点

src/generator/DomainGenerator.java

  1 package generator;
  2 
  3 import java.io.BufferedReader;
  4 import java.io.File;
  5 import java.io.FileInputStream;
  6 import java.io.FileNotFoundException;
  7 import java.io.FileOutputStream;
  8 import java.io.InputStream;
  9 import java.io.InputStreamReader;
 10 import java.io.OutputStreamWriter;
 11 import java.lang.reflect.Field;
 12 import java.lang.reflect.ParameterizedType;
 13 import java.lang.reflect.Type;
 14 import java.util.Iterator;
 15 import java.util.List;
 16 import java.util.Set;
 17 import java.util.regex.Matcher;
 18 import java.util.regex.Pattern;
 19 
 20 import org.apache.log4j.Logger;
 21 import org.junit.Test;
 22 
 23 import cn.lddxfs.tieba.domain.DataDictory;
 24 import cn.lddxfs.tieba.domain.DataDictoryValue;
 25 
 26 public class DomainGenerator extends GlobalVar {
 27 
 28     private Logger logger = Logger.getLogger(DomainGenerator.class);
 29 
 30     /**
 31      * 设置是否显示注释
 32      */
 33     private Boolean HAS_NOTE = true;
 34 
 35     /**
 36      * 
 37      * @throws Exception
 38      */
 39     @Test
 40     public void generatorHBMXML() throws Exception {
 41         /**
 42          * 遍历
 43          */
 44         XMLBeanDigester xmlBeanDigester = new XMLBeanDigester();
 45         XMLBeanCache xmlBeanCache = xmlBeanDigester.digester();
 46         xmlBeanCache.setHasNote(HAS_NOTE);
 47         /**
 48          * Map<String, XMLBean> xmlBeanMap = xmlBeanCache.getXMLBeanMap();
 49          * Set<String> beantypeSet = xmlBeanMap.keySet(); Iterator<String>
 50          * beantypeSetit = beantypeSet.iterator(); while
 51          * (beantypeSetit.hasNext()) { String beantype = beantypeSetit.next();
 52          * XMLBean xmlBean = xmlBeanMap.get(beantype);
 53          * System.out.println(xmlBean.getType());
 54          * System.out.println(xmlBean.getValue());
 55          * 
 56          * }
 57          */
 58         /**
 59          * <pre>
 60          * 生成hbm.xml文件的思路: 
 61          *  1 遍历完一个类就直接写出到文件
 62          *  2 遍历完所有类才写,这种方式实现复杂并且需要消耗较多系统资源,不宜采用
 63          * 对于1 ,文件的命名为 “实体名.temp”, 存放到properties文件 给出的package下
 64          * 
 65          * <pre>
 66          */
 67         // 部分 new String[]{"Level","User"} 或全部 DOMAIN_TYPE
 68         for (String domain_type : DOMAIN_TYPE) {
 69             // 得到类全限定名
 70             String className = PACKAGE_Str + "." + domain_type;
 71             // 得到Class对象
 72             Class clazz = Class.forName(className);
 73             // 新建实体对应的Hibernate映射文件.hbm.xml的临时文件.hbm.temp
 74             File classNamehbmFile = new File(PATHNAME + clazz.getSimpleName()
 75                     + ".hbm.xml");
 76             // 存储 .hbm.temp 文件的字符串
 77             StringBuffer hbmFileSB = new StringBuffer();
 78             String hbmFileStr = "";
 79 
 80             hbmFileSB.append(xmlBeanCache.getXMLBeanStr("hbmhead"));
 81 
 82             /**
 83              * 返回 Field 对象的一个数组,这些对象反映此 Class
 84              * 对象所表示的类或接口所声明的所有字段。包括公共、保护、默认(包)访问和私有字段
 85              * ,但不包括继承的字段。返回数组中的元素没有排序,也没有任何特定的顺序。如果该类或接口不声明任何字段,或者此 Class
 86              * 对象表示一个基本类型、一个数组类或 void,则此方法返回一个长度为 0 的数组。
 87              */
 88             Field[] fields = clazz.getDeclaredFields();
 89             logger.debug("className=" + className);
 90             logger.debug("类" + clazz + "的字段如下========");
 91 
 92             System.out.println("DomainGenerator.name()" + clazz.getName()
 93                     + "  {");
 94             for (Field field : fields) {
 95                 // 获得所有Field的类型 不包括泛型Field的 泛型参数
 96                 // 返回一个 Class 对象,它标识了此 Field 对象所表示字段的声明类型
 97                 Class fieldClazz = field.getType();
 98                 /**
 99                  * 
100                  */
101                 Class dClazz = null;
102 
103                 String fieldClazzSimpleName = fieldClazz.getSimpleName();
104 
105                 if (HAS_NOTE) {
106                     String fieldNote = "<!--" + getNote(field) + "-->
";
107                     hbmFileSB.append(fieldNote);
108                 }
109                 // 获得所有泛型的Field
110                 // 返回一个 Type 对象,它表示此 Field 对象所表示字段的声明类型。
111                 // 如果 Type 是一个参数化类型,则返回的 Type 对象必须准确地反映源代码中使用的实际类型参数。
112                 // 如果底层字段的类型是一个类型变量或者是一个参数化类型,则创建它。否则将解析它。
113                 Type fieldGenericType = field.getGenericType();
114 
115                 /*
116                  * System.out.println(fieldGenericType.toString().replaceAll(
117                  * "java\.lang\.", ""));
118                  */
119 
120                 /* 如果是类类型 String Byte[] User */
121                 if (fieldGenericType instanceof Class) {
122 
123                     for (String s : BASE_TYPE) {
124                         if (fieldClazzSimpleName.equals(s)) {
125                             // TODO 直接创建xml
126                             if (field.getName()
127                                     .equals(PROPS.getProperty("key"))) {
128                                 hbmFileSB.append(xmlBeanCache
129                                         .getXMLBeanStr("id"));
130                             } else {
131                                 hbmFileSB.append(xmlBeanCache
132                                         .getXMLBeanStr("property"));
133                                 break;
134                             }
135                         }
136                     }
137                     for (String s : ARRAY_TYPE) {
138                         if (fieldClazzSimpleName.equals(s)) {
139                             // 设置长度
140                             hbmFileSB.append(xmlBeanCache
141                                     .getXMLBeanStr("picture"));
142                             break;
143                         }
144                     }
145 
146                     for (String s : DOMAIN_TYPE) {
147                         if (fieldClazzSimpleName.equals(s)) {
148                             // 实体类型
149                             dClazz = fieldClazz;
150                             // 获得对端是0 1 还是 n
151                             String otherString = Other(clazz, fieldClazz);
152                             if (otherString.equals("0")) {
153                                 logger.debug("0对1");// 本方含外键
154                                 // 多对一
155                                 hbmFileSB.append(xmlBeanCache
156                                         .getXMLBeanStr("n1"));
157                                 System.out.println("0对1默认为多对1"
158                                         + clazz.getName() + " 中Field "
159                                         + fieldClazzSimpleName);
160 
161                                 // 110
162                                 break;
163                             } else if (otherString.equals("1")) {
164                                 logger.debug("1对1");
165                                 hbmFileSB.append(xmlBeanCache
166                                         .getXMLBeanStr("111"));
167                                 hbmFileSB.append(xmlBeanCache
168                                         .getXMLBeanStr("110"));
169                                 System.out.println("1对1请手动指定含外键方  "
170                                         + clazz.getName() + " 中Field "
171                                         + fieldClazzSimpleName);
172                                 // 111 或110
173                                 break;
174                             } else if (otherString.equals("n")) {
175                                 logger.debug("n对1");
176                                 // n1
177                                 hbmFileSB.append(xmlBeanCache
178                                         .getXMLBeanStr("n1"));
179                                 break;
180                             }
181 
182                         }
183                     }
184 
185                 } else if (fieldGenericType instanceof ParameterizedType) {
186 
187                     /* 如果是参数化类型 List<User> List<Tie> List<String> */
188                     // 得到泛型类java.util.List<cn.lddxfs.tieba.domain.Ba>
189                     ParameterizedType pt = (ParameterizedType) fieldGenericType;
190                     Type t1Type = pt.getActualTypeArguments()[0];
191 
192                     Class t1Clazz = null;
193                     if (t1Type instanceof Class) {
194                         t1Clazz = (Class) t1Type;
195                     }
196 
197                     dClazz = t1Clazz;
198 
199                     String t1SimpleName = t1Clazz.getSimpleName();
200 
201                     String otherString = Other(clazz, t1Clazz);
202 
203                     // System.out.print(fieldClazzSimpleName);
204 
205                     if (otherString.equals("0")) {
206                         System.out.println("0对n默认为1对n" + clazz.getName()
207                                 + " 中Field " + t1Clazz.getSimpleName());
208 
209                         logger.debug("0对n");
210                         // 1nList或 1nSet
211                         hbmFileSB.append(xmlBeanCache.getXMLBeanStr("1n"
212                                 + fieldClazzSimpleName));
213                     } else if (otherString.equals("1")) {
214                         logger.debug("1对n");
215                         // 1nList 或1nSet
216                         hbmFileSB.append(xmlBeanCache.getXMLBeanStr("1n"
217                                 + fieldClazzSimpleName));
218                     } else if (otherString.equals("n")) {
219                         logger.debug("n对n");
220                         // nnList 或nnSet
221                         hbmFileSB.append(xmlBeanCache.getXMLBeanStr("nn"
222                                 + fieldClazzSimpleName));
223 
224                         String centerTableString = "";
225                         if (dClazz.getSimpleName().compareTo(
226                                 clazz.getSimpleName()) > 0) {
227                             centerTableString = dClazz.getSimpleName() + "_"
228                                     + clazz.getSimpleName();
229                         } else {
230                             centerTableString = clazz.getSimpleName() + "_"
231                                     + dClazz.getSimpleName();
232                         }
233                         hbmFileStr = hbmFileSB.toString();
234                         hbmFileStr = hbmFileStr.replaceAll("<%centerTable%>",
235                                 centerTableString);
236 
237                         hbmFileSB = new StringBuffer(hbmFileStr);
238                     }
239                 }
240 
241                 logger.debug("fieldClazzSimpleName=" + fieldClazzSimpleName);
242                 // 字段上的注释
243 
244                 // 替换Field 替换field
245                 hbmFileStr = hbmFileSB.toString();
246 
247                 hbmFileStr = hbmFileStr
248                         .replaceAll("<%field%>", field.getName());
249                 if (dClazz != null) {
250                     hbmFileStr = hbmFileStr.replaceAll("<%Field%>",
251                             dClazz.getSimpleName());
252                 }
253                 hbmFileSB = new StringBuffer(hbmFileStr);
254             }
255             System.out.println(" }");
256 
257             logger.debug("类" + clazz + "的字段如上=====");
258             hbmFileStr = hbmFileSB.toString();
259             hbmFileStr += xmlBeanCache.getXMLBeanStr("hbmfoot");
260             // 替换Class class
261             hbmFileStr = hbmFileStr.replaceAll("<%Class%>",
262                     clazz.getSimpleName());
263             String clazzSimpleString = clazz.getSimpleName().substring(0, 1)
264                     .toLowerCase()
265                     + clazz.getSimpleName().substring(1);
266             hbmFileStr = hbmFileStr.replaceAll("<%class%>", clazzSimpleString);
267 
268             // 循环properties文件
269             Set<String> keySet = PROPS.stringPropertyNames();
270             Iterator<String> keyIterator = keySet.iterator();
271             while (keyIterator.hasNext()) {
272                 String key = (String) keyIterator.next();
273                 String value = PROPS.getProperty(key);
274                 // 用properties文件中的键 值替换文件中相应的内容
275                 hbmFileStr = hbmFileStr.replaceAll("<%" + key + "%>", value);
276             }
277 
278             if (classNamehbmFile.exists()) {
279                 classNamehbmFile.delete();
280             }
281 
282             // 将hbmFileStr写出到文件
283             OutputStreamWriter writer = new OutputStreamWriter(
284                     new FileOutputStream(classNamehbmFile), CHARSET_NAME);
285             writer.write(hbmFileStr);
286             writer.flush();
287             writer.close();
288 
289         }
290         /*
291          * // BeanInfo表示该Student对象所有的属性情况 BeanInfo bi =
292          * Introspector.getBeanInfo(clazz); // 取得Student对象所有属性集合
293          * PropertyDescriptor[] pds = bi.getPropertyDescriptors(); for
294          * (PropertyDescriptor pd : pds) { System.out.println(pd.getName()); }
295          */
296         /*
297          * 列出文件名 List<File> fileList = new LinkedList<File>(); listFileName(dir,
298          * fileList); Iterator<File> fileListiterator = fileList.iterator();
299          * while (fileListiterator.hasNext()) { fileListiterator.next(); }
300          */
301     }
302 
303     /**
304      * 获取给定Field类型字段上的java注释
305      * 
306      * @param field
307      * @return
308      * @throws FileNotFoundException
309      */
310     public String getNote(Field field) throws Exception {
311 
312         Class fieldClazz = field.getType();
313         Class clazz = field.getDeclaringClass();
314 
315         // System.out.println("fieldClazz=" + fieldClazz.getSimpleName());
316 
317         String pathString = SRC_PATH + clazz.getName().replace('.', '/')
318                 + ".java";
319 
320         logger.debug("pathString=" + pathString);// 打印java文件的路径
321         InputStream inputStream = new FileInputStream(pathString);
322 
323         BufferedReader bufferedReader = new BufferedReader(
324                 new InputStreamReader(inputStream, CHARSET_NAME));
325         String line;
326         StringBuffer stringBuffer = new StringBuffer();
327         while ((line = bufferedReader.readLine()) != null) {
328             // System.out.println(line);
329             stringBuffer.append(line);
330         }
331         // 得到文件的内容
332         String fileContent = stringBuffer.toString();
333 
334         String REGEX = "\s+/\*\*[,,\s\*0-9A-Za-zu4e00-u9fa5]+(\*/)?\s*private{1}\s*"
335                 + fieldClazz.getSimpleName().replaceAll("\[\s*\]", "")
336                 + "((<[A-Za-z]*>)|(\[[A-Za-z]*\]))*"
337                 + "\s*"
338                 + field.getName()
339                 + "\s*"
340                 + "(=\s*new\s*[A-Za-z]*\s*<[A-Za-z]*>\s*\(\s*\))?"
341                 + "\s*;{1}";
342         // =new LinkedList<Ba>()
343         /* 匹配语法 */
344         // private Field field;
345         Pattern p = Pattern.compile(REGEX);
346         Matcher m = p.matcher(fileContent); // 获取 matcher 对象
347         int count = 0;
348         String remarkString = "";
349         while (m.find()) {
350             count++;
351             remarkString = fileContent.substring(m.start(), m.end());
352             logger.debug("finded a remark=" + remarkString);
353         }
354         if (count != 1) {
355             System.out.println("匹配不正确,无法找到方法上注释" + clazz.getName() + "   "
356                     + fieldClazz.getName() + " " + field.getName());
357 
358         }
359         bufferedReader.close();
360 
361         return remarkString.substring(0, remarkString.lastIndexOf("*/"))
362                 .replaceAll("\*", "").replaceAll("/", "").trim();
363     }
364 
365     // //////////////////////
366     @Test
367     public void initDataDictory() throws Exception {
368 
369         for (String domain_type : DOMAIN_TYPE) {
370             // 得到类全限定名
371             String className = PACKAGE_Str + "." + domain_type;
372             // 得到Class对象
373             Class clazz = Class.forName(className);
374             Field[] fields = clazz.getDeclaredFields();
375             for (Field field : fields) {
376                 if (field.getType().equals(DataDictoryValue.class)) {
377 
378                     
379                     DataDictory dataDictory = new DataDictory();
380                     dataDictory.setKeyWord(clazz.getSimpleName()+field.getName());
381                     dataDictory.setRemark(clazz.getSimpleName()+getNote(field));
382                     
383                              
384                             
385                     System.out.println("INSERT into tiebatb_datadictory(keyWord,remark) VALUES('"+clazz.getSimpleName()+"','"+clazz.getSimpleName()+getNote(field)+"');");
386                 }
387                 ;
388             }
389         }
390     }
391 
392     /**
393      * 列出指定目录下的java文件名
394      * 
395      * @param file
396      *            指定一个目录
397      * @param fileList
398      *            返回的类名列表 ,无“.java”后缀
399      */
400     @Deprecated
401     public void listFileName(File file, List<File> fileList) {
402         if (file == null) {
403             return;
404         }
405         if (file.isDirectory()) {
406             File f[] = file.listFiles();
407             if (f != null)
408                 for (int i = 0; i < f.length; i++) {
409                     listFileName(f[i], fileList);
410                 }
411         } else {
412 
413             if (file.getName().endsWith(".java")) {
414                 System.out.println(file.getName());
415 
416                 // fileList.add(str);
417             }
418         }
419     }
420 
421     /**
422      * 判断名称为fieldClazz的实体中含有多少个clazz类型的Field
423      * 
424      * @param clazz
425      *            A类
426      * @param fieldClazz
427      *            A类中的Field
428      * @return
429      */
430     public String Other(Class clazz, Class fieldClazz) {
431 
432         Field[] oFields = fieldClazz.getDeclaredFields();
433         // 获得关联实体上所有的Field并遍历
434         for (Field ofield : oFields) {
435             Class ofieldClazz = ofield.getType();
436             String ofieldClazzSN = ofieldClazz.getSimpleName();
437 
438             Type ofieldGenericType = ofield.getGenericType();
439 
440             /* 如果是类类型 String Byte[] User */
441             if (ofieldGenericType instanceof Class) {
442                 if (clazz.getSimpleName().equals(ofieldClazzSN)) {
443                     // 基本类型
444                     // System.out.println("1" + ofieldClazzSN);
445                     // 一对一主键
446                     return "1";
447                     // 一对一外键
448                 }
449 
450             }
451 
452             else if (ofieldGenericType instanceof ParameterizedType) {
453                 /* 如果是参数化类型 List<User> List<Tie> */
454                 // 得到泛型类java.util.List<cn.lddxfs.tieba.domain.Ba>
455                 ParameterizedType pt = (ParameterizedType) ofieldGenericType;
456                 Type t1Type = pt.getActualTypeArguments()[0];
457 
458                 Class t1Clazz = null;
459                 if (t1Type instanceof Class) {
460                     t1Clazz = (Class) t1Type;
461                 }
462 
463                 String t1SimpleName = t1Clazz.getSimpleName();
464                 if (clazz.getSimpleName().equals(t1SimpleName)) {
465                     // 基本类型
466                     /*
467                      * System.out .println("多" + ofieldClazzSN + " " +
468                      * t1SimpleName);
469                      */
470                     // 一对多1nSet 1nList
471 
472                     return "n";
473                 }
474 
475             }
476 
477         }
478         return "0";
479     }
480 
481 }
View Code

你需要将类似以下格式的java文件

  1 package cn.lddxfs.tieba.domain;
  2 
  3 import java.util.HashSet;
  4 import java.util.LinkedList;
  5 import java.util.List;
  6 import java.util.Set;
  7 
  8 /**
  9  * 系统管理员
 10  */
 11 public class AdminUser {
 12 
 13     /**
 14      * id
 15      */
 16     private Long id;
 17 
 18     /**
 19      * 用户名
 20      */
 21     private String name;
 22 
 23     /**
 24      * 邮箱,登陆时使用
 25      */
 26     private String email;
 27 
 28     /**
 29      * 密码
 30      */
 31     private String password;
 32 
 33     /**
 34      * UUID用于激活
 35      */
 36     private String uuid;
 37 
 38     /**
 39      * 状态,已经启用,为激活
 40      */
 41     private DataDictoryValue status;
 42 
 43     /**
 44      * 居民身份证
 45      */
 46     private String idcard;
 47 
 48     /**
 49      * 审核了那些吧
 50      */
 51     private Set<BaApply> baApply=new HashSet<BaApply>();
 52 
 53     public Long getId() {
 54         return id;
 55     }
 56 
 57     public void setId(Long id) {
 58         this.id = id;
 59     }
 60 
 61     public String getName() {
 62         return name;
 63     }
 64 
 65     public void setName(String name) {
 66         this.name = name;
 67     }
 68 
 69     public String getEmail() {
 70         return email;
 71     }
 72 
 73     public void setEmail(String email) {
 74         this.email = email;
 75     }
 76 
 77     public String getPassword() {
 78         return password;
 79     }
 80 
 81     public void setPassword(String password) {
 82         this.password = password;
 83     }
 84 
 85     public String getUuid() {
 86         return uuid;
 87     }
 88 
 89     public void setUuid(String uuid) {
 90         this.uuid = uuid;
 91     }
 92 
 93     public DataDictoryValue getStatus() {
 94         return status;
 95     }
 96 
 97     public void setStatus(DataDictoryValue status) {
 98         this.status = status;
 99     }
100 
101     public String getIdcard() {
102         return idcard;
103     }
104 
105     public void setIdcard(String idcard) {
106         this.idcard = idcard;
107     }
108 
109     public Set<BaApply> getBaApply() {
110         return baApply;
111     }
112 
113     public void setBaApply(Set<BaApply> baApply) {
114         this.baApply = baApply;
115     }
116 }
View Code

现在只需要通过junit运行src/generator/DomainGenerator.java中的generatorHBMXML()方法就可以生成 hbm.xml文件了,

本文由 http://www.cnblogs.com/LDDXFS/ 原创,转载请注明本文出处。

原文地址:https://www.cnblogs.com/LDDXFS/p/4171251.html