Hibernate Tools源码的使用

Eclipse 中Hibernate tools 的安装和使用 [url]http://zhoualine.iteye.com/blog/1190141[/url]

源码里面有一个很好的格式化类:org.hibernate.tool.hbm2x.[color=darkblue][b]XMLPrettyPrinter[/b][/color]
调用
	public void formatFiles() {

formatXml( "xml" );
formatXml( "hbm.xml" );
formatXml( "cfg.xml" );

}

private void formatXml(String type) throws ExporterException {
List list = (List) files.get(type);
if(list!=null && !list.isEmpty()) {
for (Iterator iter = list.iterator(); iter.hasNext();) {
File xmlFile = (File) iter.next();
try {
XMLPrettyPrinter.prettyPrintFile(XMLPrettyPrinter.getDefaultTidy(), xmlFile, xmlFile, true);
}
catch (IOException e) {
throw new ExporterException("Could not format XML file: " + xmlFile,e);
}
}
}
}


[color=red][b]获得源码的方法:[/b][/color]
[url]https://github.com/hibernate/hibernate-tools[/url], 然后建立maven工程
[color=red][size=large]得到源码后需要处理的问题:[/size][/color]
1.修改pom.xml的name等信息,来适合自己建立的工程。
2.注释掉pom.xml一些没必要的数据库信息。
3.注释几个地方
		<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.5.8</version>
<!--<scope>test</scope>-->
</dependency>

4.加入sql server driver,先执行mavn
[color=darkblue]mvn install:install-file -Dfile=/mnt/D/work_documents/jar2mvn/sqljdbc-4.0.jar -DgroupId=sqljdbc -DartifactId=sqljdbc -Dversion=4.0 -Dpackaging=jar[/color]
再加入依赖:
        <dependency>
<groupId>sqljdbc</groupId>
<artifactId>sqljdbc</artifactId>
<version>4.0</version>
</dependency>

5. 加入
/mnt/D/work_documents/workspace_ide/HibernateTools/src/java/config/hibernate.cfg.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- 连接数据库信息 -->
<property name="hibernate.bytecode.use_reflection_optimizer">false</property>
<property name="hibernate.connection.driver_class">com.microsoft.sqlserver.jdbc.SQLServerDriver</property>
<property name="hibernate.connection.password">sa</property>
<property name="hibernate.connection.url">jdbc:sqlserver://192.168.0.196:1433;databaseName=dev_cpm</property>
<property name="hibernate.connection.username">sa</property>
<property name="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</property>
<property name="hibernate.search.autoregister_listeners">false</property>
<!-- 代码生成信息 info -->
<!--<property name="hibernatetool.metadatadialect">org.hibernate.cfg.reveng.dialect.SQLServer2008MetaDataDialect</property>-->
<property name="hibernatetool.metadatadialect">org.hibernate.cfg.reveng.dialect.SQLServerMetaDataDialect</property>

<!-- 自定义信息 -->
<property name="custom.package">com</property>
<property name="custom.one2many">false</property>
<property name="custom.many2one">true</property>
<property name="custom.many2many">true</property>
<property name="custom.detectOptimisticLock">true</property>
<!-- 要遍历的数据库,这个是必需写正确,否在找不到表 -->
<property name="custom.catlog">dev_cpm</property>
<property name="custom.schema">dbo</property>
<property name="custom.isAnnotation">true</property>
<property name="custom.genPojo">true</property>
<property name="custom.genDao">true</property>
<property name="custom.outputDir">/mnt/D/work_documents/workspace_ide/HibernateTools/codes</property>
</session-factory>
</hibernate-configuration>


/mnt/D/work_documents/workspace_ide/HibernateTools/src/java/com/pandy/RunHibernateTools.java
package com.pandy;

import java.io.File;
import java.util.Properties;

import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.JDBCMetaDataConfiguration;
import org.hibernate.cfg.reveng.DefaultReverseEngineeringStrategy;
import org.hibernate.cfg.reveng.ReverseEngineeringSettings;
import org.hibernate.tool.hbm2x.DAOExporter;
import org.hibernate.tool.hbm2x.DAONewExporter;
import org.hibernate.tool.hbm2x.POJOExporter;

public class RunHibernateTools {

public void run() {

String path = getClass().getResource("/").toString();
if (path.startsWith("file:"))
path = path.substring("file:".length() + 1);

//String fileName = path + "config/hibernate.cfg.xml";
String fileName = "/mnt/D/work_documents/workspace_ide/HibernateTools/src/java/config/hibernate.cfg.xml";
File file = new File(fileName);
if (!file.exists()) {
throw new RuntimeException("找不到配置文件");
}
// 直接给绝对路径会出问题
Configuration xmlcfg = new Configuration().configure(file);

JDBCMetaDataConfiguration cfg = new JDBCMetaDataConfiguration();
Properties properties = xmlcfg.getProperties();
cfg.setProperties(properties);

DefaultReverseEngineeringStrategy configurableNamingStrategy = new DefaultReverseEngineeringStrategy();
configurableNamingStrategy.setSettings(new ReverseEngineeringSettings(configurableNamingStrategy)
.setDefaultPackageName(getString(properties, "custom.package", "com"))// 要生成的包名
.setCreateCollectionForForeignKey(getBoolean(properties, "custom.one2many", false))// 是否生成many-to-one的在one端的集合类,
// 就是一对多的关系
.setCreateManyToOneForForeignKey(getBoolean(properties, "custom.many2one", true))// 是否生成many-to-one
.setDetectManyToMany(getBoolean(properties, "custom.many2many", true))// 是否生成many-to-many
.setDetectOptimisticLock(getBoolean(properties, "custom.detectOptimisticLock", true)) // 乐观锁对象?
);
cfg.setReverseEngineeringStrategy(configurableNamingStrategy);
//cfg.readFromJDBC();// 不区分schema和catlog的话,容易碰到错误.
cfg.readFromJDBC(getString(properties, "custom.catlog", "Test"), getString(properties, "custom.schema", "dbo"));// 只从数据的这些信息生成
cfg.buildMappings();

if (getBoolean(properties, "custom.genPojo", true)) {
POJOExporter exporter = new POJOExporter(cfg, getOutputDir(properties));
if (getBoolean(properties, "custom.isAnnotation", true)) {
exporter.getProperties().setProperty("ejb3", "true");// ejb3注解
exporter.getProperties().setProperty("jdk5", "true");// jdk5语法(主要是集合类的泛型处理)
}
exporter.start();
}

if (getBoolean(properties, "custom.genDao", false)) {
DAOExporter daoExporter = new DAOExporter(cfg, getOutputDir(properties));
daoExporter.start();
}
}

private File getOutputDir(Properties properties) {
File file = new File(getString(properties, "custom.outputDir", "/"));// 生成项目的物理位置(跟目录,tools会自动根据pacakge建立相应路径)
return file;
}

private static boolean getBoolean(Properties properties, String key, boolean defaultValue) {
String val = properties.getProperty(key);
if (isBlank(val)) {
return defaultValue;
}
return Boolean.valueOf(val);
}

private static String getString(Properties properties, String key, String defaultValue) {
String val = properties.getProperty(key);
if (isBlank(val)) {
return defaultValue;
}
return val;
}

private static Integer getInteger(Properties properties, String key, Integer defaultValue) {
String val = properties.getProperty(key);
if (isBlank(val)) {
return defaultValue;
}
return Integer.parseInt(val);
}

private static boolean isBlank(String val) {
if (val == null || val.trim().length() == 0)
return true;
return false;
}

public static void main(String[] args) {
System.out.println("----------------代码生成开始-----------------------");
RunHibernateTools tools = new RunHibernateTools();
tools.run();
System.out.println("----------------代码生成完成-----------------------");

}

}

可能要适当修改
6.增加一个存放代码的文件夹
/mnt/D/work_documents/workspace_ide/HibernateTools/codes
7. /mnt/D/work_documents/workspace_ide/HibernateTools/src/java/org/hibernate/cfg/JDBCMetaDataConfiguration.java 增加一个方法:
public void readFromJDBC(String catalog, String schema) {

JDBCBinder binder = new JDBCBinder(this, buildSettings(), createMappings(), revEngStrategy);

binder.readFromDatabase(catalog, schema, buildMapping(this));

}

mian方法修改:
//cfg.readFromJDBC();// 不区分schema和catlog的话,容易碰到错误.
cfg.readFromJDBC(getString(properties, "custom.catlog", "Test"), getString(properties, "custom.schema", "dbo"));// 只从数据的这些信息生成

8.生成的DAO后缀是Home,要是改成XxxxDAO,以DAO为后缀。
/mnt/D/work_documents/workspace_ide/HibernateTools/src/java/org/hibernate/tool/hbm2x/DAOExporter.java, 修改以下方法为:
protected void init() {
super.init();
setTemplateName(DAO_DAOHOME_FTL);
setFilePattern("{package-name}/{class-name}DAO.java");
}

9.模板文件,如果生成的代码需要修改,可以修改模板,路径为
/mnt/D/work_documents/workspace_ide/HibernateTools/src/templates
10. [color=red]配置需要生成代码的表[/color]
A: 跟踪代码
/mnt/D/work_documents/workspace_ide/HibernateTools/src/java/org/hibernate/tool/hbm2x/GenericExporter.java
[color=red]前面有一段static代码[/color],里面有 ge.getConfiguration().getClassMappings(),ge.getConfiguration()里面有一个tables属性,映射了table=>java file.
B:到/mnt/D/work_documents/workspace_ide/HibernateTools/src/java/org/hibernate/tool/hbm2x/AbstractExporter.java 去查看这个configuration到底怎么初始化?
可以看到它的初始化是GenericExporter构造函数里面传入。那么就要找到什么时候创建GenericExporter?
C:
它是在POJOExporter构造函数里面,那么就在main函数的POJOExporter exporter = new POJOExporter(cfg, getOutputDir(properties));创建。
D:到main函数更在cfg的创建,并监视里面的tables什么时候有值?cfg.readFromJDBC()这里被赋值,继续跟踪。
D: 跟踪到/mnt/D/work_documents/workspace_ide/HibernateTools/src/java/org/hibernate/cfg/JDBCBinder.java,readFromDatabase()方法DatabaseCollector collector = readDatabaseSchema(catalog, schema),被赋值。
E: 让它继续找,我们只是在生成的时候过滤掉就可以了。[color=red]那么回到A,在这里做手脚[/color]。
-----------
I: /mnt/D/work_documents/workspace_ide/HibernateTools/src/java/config/hibernate.cfg.xml增加一个
<!--  需要都好隔开表名  -->
<property name="custom.filter.include">app_user,rh_log_exception_info,rh_log_exception_param</property>

II:/mnt/D/work_documents/workspace_ide/HibernateTools/src/java/org/hibernate/cfg/JDBCMetaDataConfiguration.java最后面增加
public String[] filterIncludeTables = null;
public void setFilterIncludeTables(String[] filters) {
this.filterIncludeTables = filters;
for (int i = 0; i < filters.length; i++) {
this.filterIncludeTables[i] = filters[i].replace("_", "");
}
}

public boolean isInclude(String shortName) {
if(filterIncludeTables==null) return true;

for (int i = 0; i < filterIncludeTables.length; i++) {
if(shortName.equalsIgnoreCase(filterIncludeTables[i])) return true;
}
return false;
}

III: /mnt/D/work_documents/workspace_ide/HibernateTools/src/java/org/hibernate/tool/hbm2x/GenericExporter.java修改static段的代码:
	static {
modelIterators.put( "configuration", new ModelIterator() {

void process(GenericExporter ge) {
TemplateProducer producer = new TemplateProducer(ge.getTemplateHelper(),ge.getArtifactCollector());
producer.produce(new HashMap(), ge.getTemplateName(), new File(ge.getOutputDirectory(),ge.filePattern), ge.templateName, "Configuration");

}

});
modelIterators.put("entity", new ModelIterator() {

void process(GenericExporter ge) {
Iterator iterator = ge.getCfg2JavaTool().getPOJOIterator(ge.getConfiguration().getClassMappings());
Map additionalContext = new HashMap();
while ( iterator.hasNext() ) {
POJOClass element = (POJOClass) iterator.next();
JDBCMetaDataConfiguration cfg = (JDBCMetaDataConfiguration)ge.getConfiguration();
if(cfg.isInclude(element.getShortName())){
ge.exportPersistentClass( additionalContext, element );
}
}
}
});
modelIterators.put("component", new ModelIterator() {

void process(GenericExporter ge) {
Map components = new HashMap();

Iterator iterator = ge.getCfg2JavaTool().getPOJOIterator(ge.getConfiguration().getClassMappings());
Map additionalContext = new HashMap();
while ( iterator.hasNext() ) {
POJOClass element = (POJOClass) iterator.next();
ConfigurationNavigator.collectComponents(components, element);
}

iterator = components.values().iterator();
while ( iterator.hasNext() ) {
Component component = (Component) iterator.next();
ComponentPOJOClass element = new ComponentPOJOClass(component,ge.getCfg2JavaTool());
JDBCMetaDataConfiguration cfg = (JDBCMetaDataConfiguration)ge.getConfiguration();
if(cfg.isInclude(element.getShortName())){
ge.exportComponent( additionalContext, element );
}
}
}
});
}

这样就搞定了。可以模仿做排除功能。
11.打包成jar, 参考:[url]http://panyongzheng.iteye.com/blog/1759912[/url],[url]http://sundful.iteye.com/blog/1850070[/url],修改pom.xml使用maven-compiler-plugin插件的java版本为1.7。 并修改插件的版本号[url]http://qiang106.iteye.com/blog/1388645[/url],
			<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<includes>
<include>**/*.java</include>
</includes>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
......
......
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptors>
<descriptor>./src/assembly/dist.xml</descriptor>
</descriptors>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>

命令为:
测试并打包:[color=darkblue]mvn -e clean package[/color]
不需要测试打包:[color=darkblue]mvn -e clean package -DskipTests[/color]
复制源码,不测试打包:[color=darkblue]mvn clean assembly:assembly -DskipTests[/color]
12.执行jar:
复制得到依赖jar: [color=darkblue]mvn dependency:copy-dependencies -DoutputDirectory=target/lib[/color]
执行不含源码jar:[color=darkblue]java -jar /mnt/D/work_documents/workspace_ide/HibernateTools/target/hibernate-tools-Pandy.4.0.0-CR1.jar[/color]
执行含源码的jar:[color=darkblue]java -jar /mnt/D/work_documents/workspace_ide/HibernateTools/target/hibernate-tools-Pandy.4.0.0-CR1-jar-with-dependencies.jar[/color]
最后的[color=red]打包并执行[/color]的两个命令:
[color=red]mvn -e clean package dependency:copy-dependencies -DskipTests -DoutputDirectory=target/lib[/color]
[color=red]java -jar /mnt/D/work_documents/workspace_ide/HibernateTools/target/hibernate-tools-Pandy.4.0.0-CR1.jar[/color]

13.执行是输入hibernate.cfg.xml文件路径
A:修改run方法,增加一个hibernate.cfg.xml的绝对路径参数,并注释掉原本硬编码路径:

B:修改mian方法:
public static boolean validate(String[] args){
if(args==null||args.length==0) {
System.out.println("ERROR: 一定要输入一个参数,这个参数是hibernate.cfg.xml的绝对路径.");
return false;
}
String filePath = args[0];

File file = new File(filePath);
if(!file.exists()){
System.out.println("ERROR: hibernate.cfg.xml文件不存在.");
return false;
}
return true;
}

public static void main(String[] args) {
System.out.println("验证参数:");
if(!validate(args)){
System.exit(0);
}

System.out.println("----------------代码生成开始-----------------------");
RunHibernateTools tools = new RunHibernateTools();
tools.run(args[0]);
System.out.println("----------------代码生成完成-----------------------");

}

最终执行命令: [color=red]java -jar /mnt/D/work_documents/workspace_ide/HibernateTools/target/hibernate-tools-Pandy.4.0.0-CR1.jar /mnt/D/work_documents/workspace_ide/HibernateTools/hibernate.cfg.xml[/color]
14.POJO的源码主键生成
org.hibernate.tool.hbm2x.pojo.EntityPOJOClass, generateAnnIdGenerator()方法。因为不知道怎么传入主键的配置,所以尝试在这里修改。我改成了:要么是uuid,要么是auto类型,这个是自己的需求。
			if ( !"native".equals( strategy ) ) {
if ( "guid".equals( strategy )||"uuid".equals( strategy ) ) {
//增加uuid的注解
builder.resetAnnotation( importType("javax.persistence.GeneratedValue") );
builder.addQuotedAttribute( "generator", "system-uuid" );
idResult.append(builder.getResult());
//增加一个注解
AnnotationBuilder builder1=AnnotationBuilder.createAnnotation( importType("org.hibernate.annotations.GenericGenerator") )
.addQuotedAttribute( "name", "system-uuid" )
.addQuotedAttribute( "strategy", "org.hibernate.id.UUIDGenerator");
idResult.append(builder1.getResult());
}
else {
/*builder.resetAnnotation( importType("javax.persistence.GeneratedValue") );
builder.addAttribute( "strategy", staticImport("javax.persistence.GenerationType", "IDENTITY" ) );
idResult.append(builder.getResult());*/
builder.resetAnnotation( importType("javax.persistence.GeneratedValue") );
//使用自动主键生成器
builder.addAttribute( "strategy", staticImport("javax.persistence.GenerationType", "GenerationType.AUTO" ) );
idResult.append(builder.getResult());
}
}else {
builder.resetAnnotation( importType("javax.persistence.GeneratedValue") );
idResult.append(builder.getResult());
}



[b]修改源码默认产生equal,toString,hashCode方法:[/b]
/mnt/D/work_documents/workspace_ide_linux/HibernateTools/src/java/org/hibernate/tool/hbm2x/pojo/BasicPOJOClass.java
[b]toString:[/b]
private boolean needsToString(Iterator iter) {
/*while ( iter.hasNext() ) {
Property element = (Property) iter.next();
if ( c2j.getMetaAsBool( element, "use-in-tostring" ) ) {
return true;
}
}
return false;*/
return true;
}

private Iterator getToStringPropertiesIterator(Iterator iter) {
List properties = new ArrayList();

while ( iter.hasNext() ) {
Property element = (Property) iter.next();
//if ( c2j.getMetaAsBool( element, "use-in-tostring" ) ) {
properties.add( element );
//}
}

return properties.iterator();
}

[b]equal & hashCode:[/b]
private boolean needsEqualsHashCode(Iterator iter) {
while ( iter.hasNext() ) {
Property element = (Property) iter.next();
//if ( usePropertyInEquals( element ) ) {
return true;
//}
}
return false;
}

public String generateHashCode(Property property, String result, String thisName, boolean jdk5) {
StringBuffer buf = new StringBuffer();
//if ( c2j.getMetaAsBool( property, "use-in-equals" ) ) {
...... 里面的不用注释
//}
return buf.toString();
}



[b]修改版本号信息:[/b]
/mnt/D/work_documents/workspace_ide_linux/HibernateTools/src/java/org/hibernate/tool/Version.java


自己的修改hibernate-tools的模板和修复Comment乱码问题:[url]http://kennylee26.iteye.com/blog/1229993[/url]
Hibernate Tools生成注释:[url]http://www.blogjava.net/pauliz/archive/2009/11/13/302162.html[/url]
修改源码的地方:
[color=red][b]输出中文乱码[/b][/color]:
1.
TemplateProducer.produce(), 应该使用UTF-8输出到文件.
Writer fileWriter = null;
....
fileWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(destination), "UTF-8"));
2.src/org/hibernate/tool/hbm2x/jtidy.properties
input-encoding=utf-8
output-encoding=utf-8
3.反转表名等类,都存放在:org.hibernate.cfg.reveng.dialect, 并针对相应类重载getTables方法.
[b][color=red]DAO:[/color][/b]
src/org/hibernate/tool/hbm2x/DAOExporter.java, 这里修改输出类的文件名,extends,implements等.
dao/daohome.ftl, 这里可以修改默认的方法,和类名字等.
[b][color=red]POJO:[/color][/b]
src/org/hibernate/tool/hbm2x/POJOExporter.java, 这里修改输出类的extends,implements等.
pojo/Pojo.ftl

去掉注解的schema,catlog, Ejb3TypeDeclaration.ftl,Line8,7

POJO的头部注释信息:生成表的注释:
A:修改或者重载JDBCMetaDataDialect的继续类的getTables()方法,确保这里的rs.getString("remarks")能得到数据库的注释,否则自己查找数据库得到注释.
B:src/pojo/PojoTypeDeclaration.ftl,增加表注释
${pojo.getClassJavaDoc(pojo.getDeclarationName() + " By Pandy.", 0)}
改为
<#if clazz.table.comment?exists>
/**
* Entity: ${clazz.table.comment}
*/
</#if>

extends:
BasicPOJOClass.getExtendsDeclaration(), Line190
EntityPOJOClass.getExtends(), 写入extends, 或者直接Line84固定返回extends

implements:
BasicPOJOClass.getImplementsDeclaration(), Line200
EntityPOJOClass.getImplements(), Line87
给POJO增加一些默认的函数:
src/pojo/Pojo.ftl, Line11,
增加serialVersionUID:
src/pojo/Pojo.ftl, Line7
private static final long serialVersionUID = 1L;


[color=red][b]修改数据库语言:Dialect[/b][/color], 这里影响到pojo.id的注解
MetaDataDialectFactory.createMetaDataDialect();
这里没有正确从文件hibernate.properties获得dialect, 所以直接修改property=默认的dialect,
比如:String property ="org.hibernate.cfg.reveng.dialect.SQLServerMetaDataDialect";
SQLServerMetaDataDialect这个是在Hibernate-Tools.jar里面的.


[url]http://tonydark01.iteye.com/blog/1721834[/url]
直接用junit或mian函数运行,而非依赖于jboss的插件,省的更新eclipse或者迁移的时候各种麻烦 ,副项目包备份.
1.增加slf4j-simple-1.5.2.jar,
2.增加驱动程序包,
3.给JDBCMetaDataConfiguration.java增加一个方法
public void readFromJDBC(String catalog, String schema) {
JDBCBinder binder = new JDBCBinder(this, buildSettings(), createMappings(), revEngStrategy);
binder.readFromDatabase(catalog, schema, buildMapping(this));
}

4.给hibernate.cfg.xml增加一个属性
<property name="hibernatetool.metadatadialect">org.hibernate.cfg.reveng.dialect.SQLServer2008MetaDataDialect</property>
,
[color=red]注意,貌似许多属性都是在这里增加的.[/color]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值