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]
                










