Hibernate Tools生成注释
最近做项目时,使用Hibernate Tools 3.2.4生成entity和hbm.xml,但默认情况下,DB中的comments没法生成到javadoc和xml中,改了templates倒是有注释了,但却是乱码,心里一直耿耿于怀...(这不符合咱一直强调的编码规范不是?最主要的是人懒,有时用entity不想再找文档)。在网上找了半天,大多说是freemarker编码设置问题,但不管怎么设置,都没一点效果,决定自己动手。下了源码,查到原因,人家压根就没处理中文问题。记录一下处理过程。
ftl是freemarker模板,可以在jar包外使用,java和properties重新打包替换hibernate-tools.jar,如果是eclipse-plugins,jar包在plugins\org.hibernate.eclipse_3.2.4.GA-R200905070146-H18\lib\tools\hibernate-tools.jar
pojo\PojoFields.ftl
pojo\PojoPropertyAccessors.ftl
org\hibernate\tool\hbm2x\TemplateProducer.java
org\hibernate\tool\hbm2x\jtidy.properties
补充:
无法取得MySQL5 Table的Comments,修改org.hibernate.cfg.reveng.dialec.MySQLMetaDataDialect
重载getTables方法
外键默认生成List,修改org.hibernate.cfg.JDBCBinder
ftl是freemarker模板,可以在jar包外使用,java和properties重新打包替换hibernate-tools.jar,如果是eclipse-plugins,jar包在plugins\org.hibernate.eclipse_3.2.4.GA-R200905070146-H18\lib\tools\hibernate-tools.jar
pojo\PojoFields.ftl
<
#
--
//
Fields -->
< #foreach field in pojo.getAllPropertiesIterator() >< # if pojo.getMetaAttribAsBool(field, " gen-property " , true ) > /** */ /** */ /** */ /**
<#if pojo.hasMetaAttribute(field, "field-description")>
${pojo.getFieldJavaDoc(field, 0)}
</#if>
<#foreach column in field.columnIterator><#if column.comment?exists && column.comment?trim?length!=0> * ${column.comment}.
</#if>
</#foreach>
*/
$ {pojo.getFieldModifiers(field)} $ {pojo.getJavaTypeName(field, jdk5)} $ {field.name} < # if pojo.hasFieldInitializor(field, jdk5) > = $ {pojo.getFieldInitialization(field, jdk5)} </ # if > ;
</ # if >
</ #foreach >
< #foreach field in pojo.getAllPropertiesIterator() >< # if pojo.getMetaAttribAsBool(field, " gen-property " , true ) > /** */ /** */ /** */ /**
<#if pojo.hasMetaAttribute(field, "field-description")>
${pojo.getFieldJavaDoc(field, 0)}
</#if>
<#foreach column in field.columnIterator><#if column.comment?exists && column.comment?trim?length!=0> * ${column.comment}.
</#if>
</#foreach>
*/
$ {pojo.getFieldModifiers(field)} $ {pojo.getJavaTypeName(field, jdk5)} $ {field.name} < # if pojo.hasFieldInitializor(field, jdk5) > = $ {pojo.getFieldInitialization(field, jdk5)} </ # if > ;
</ # if >
</ #foreach >
pojo\PojoPropertyAccessors.ftl
<
#
--
//
Property accessors -->
< #foreach property in pojo.getAllPropertiesIterator() >
< # if pojo.getMetaAttribAsBool(property, " gen-property " , true ) >
/** */ /**
<#if pojo.hasFieldJavaDoc(property)>
* ${pojo.getFieldJavaDoc(property, 4)}
</#if>
<#foreach column in property.columnIterator><#if column.comment?exists && column.comment?trim?length!=0> * 取得 ${column.comment}.
</#if>
</#foreach>
*/
< #include " GetPropertyAnnotation.ftl " />
$ {pojo.getPropertyGetModifiers(property)} $ {pojo.getJavaTypeName(property, jdk5)} $ {pojo.getGetterSignature(property)} () {
return this.${property.name};
}
/** */ /**
<#if pojo.hasFieldJavaDoc(property)>
* ${pojo.getFieldJavaDoc(property, 4)}
</#if>
<#foreach column in property.columnIterator><#if column.comment?exists && column.comment?trim?length!=0> * 设置 ${column.comment}.
</#if>
</#foreach>
*/
$ {pojo.getPropertySetModifiers(property)} void set$ {pojo.getPropertyName(property)} ($ {pojo.getJavaTypeName(property, jdk5)} $ {property.name} ) {
this.${property.name} = ${property.name};
}
</ # if >
</ #foreach >
< #foreach property in pojo.getAllPropertiesIterator() >
< # if pojo.getMetaAttribAsBool(property, " gen-property " , true ) >
/** */ /**
<#if pojo.hasFieldJavaDoc(property)>
* ${pojo.getFieldJavaDoc(property, 4)}
</#if>
<#foreach column in property.columnIterator><#if column.comment?exists && column.comment?trim?length!=0> * 取得 ${column.comment}.
</#if>
</#foreach>
*/
< #include " GetPropertyAnnotation.ftl " />
$ {pojo.getPropertyGetModifiers(property)} $ {pojo.getJavaTypeName(property, jdk5)} $ {pojo.getGetterSignature(property)} () {
return this.${property.name};
}
/** */ /**
<#if pojo.hasFieldJavaDoc(property)>
* ${pojo.getFieldJavaDoc(property, 4)}
</#if>
<#foreach column in property.columnIterator><#if column.comment?exists && column.comment?trim?length!=0> * 设置 ${column.comment}.
</#if>
</#foreach>
*/
$ {pojo.getPropertySetModifiers(property)} void set$ {pojo.getPropertyName(property)} ($ {pojo.getJavaTypeName(property, jdk5)} $ {property.name} ) {
this.${property.name} = ${property.name};
}
</ # if >
</ #foreach >
org\hibernate\tool\hbm2x\TemplateProducer.java
public
void
produce(Map additionalContext, String templateName, File destination, String identifier, String fileType, String rootContext)
{
String tempResult = produceToString( additionalContext, templateName, rootContext );
if(tempResult.trim().length()==0) {
log.warn("Generated output is empty. Skipped creation for file " + destination);
return;
}
FileWriter fileWriter
=
null
;
Writer fileWriter = null;
try {
th.ensureExistence( destination );
ac.addFile(destination, fileType);
log.debug("Writing " + identifier + " to " + destination.getAbsolutePath() );
fileWriter
=
new
FileWriter(destination);
fileWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(destination), "UTF-8"));
fileWriter.write(tempResult);
}
catch (Exception e) {
throw new ExporterException("Error while writing result to file", e);
} finally {
if(fileWriter!=null) {
try {
fileWriter.flush();
fileWriter.close();
}
catch (IOException e) {
log.warn("Exception while flushing/closing " + destination,e);
}
}
}
}
String tempResult = produceToString( additionalContext, templateName, rootContext );
if(tempResult.trim().length()==0) {
log.warn("Generated output is empty. Skipped creation for file " + destination);
return;
}
Writer fileWriter = null;
try {
th.ensureExistence( destination );
ac.addFile(destination, fileType);
log.debug("Writing " + identifier + " to " + destination.getAbsolutePath() );
fileWriter.write(tempResult);
}
catch (Exception e) {
throw new ExporterException("Error while writing result to file", e);
} finally {
if(fileWriter!=null) {
try {
fileWriter.flush();
fileWriter.close();
}
catch (IOException e) {
log.warn("Exception while flushing/closing " + destination,e);
}
}
}
}
org\hibernate\tool\hbm2x\jtidy.properties
indent
=
auto
indent - spaces = 4
#indent - attributes = yes
wrap = 180
markup = yes
clean = yes
output - xml = yes
input - xml = yes
show - warnings = yes
trim - empty - elements = yes
input-encoding=utf-8
output-encoding=utf-8
indent - spaces = 4
#indent - attributes = yes
wrap = 180
markup = yes
clean = yes
output - xml = yes
input - xml = yes
show - warnings = yes
trim - empty - elements = yes
input-encoding=utf-8
output-encoding=utf-8
补充:
无法取得MySQL5 Table的Comments,修改org.hibernate.cfg.reveng.dialec.MySQLMetaDataDialect
重载getTables方法
/** */
/**
* MetaData中无法取得table Comment,重载
*/
@Override
public Iterator getTables(String xcatalog, String xschema, String xtable) {
try {
final String catalog = caseForSearch(xcatalog);
final String schema = caseForSearch(xschema);
final String table = caseForSearch(xtable);
log.debug("getTables(" + catalog + "." + schema + "." + table + ")");
ResultSet tableRs = getMetaData().getTables(catalog, schema, table, new String[] { "TABLE", "VIEW" });
return new ResultSetIterator(tableRs, getSQLExceptionConverter()) {
Map element = new HashMap();
protected Object convertRow(ResultSet tableResultSet) throws SQLException {
element.clear();
putTablePart(element, tableResultSet);
element.put("TABLE_TYPE", tableResultSet.getString("TABLE_TYPE"));
String remarks = tableResultSet.getString("REMARKS");
if (StringHelper.isEmpty(remarks)) {
String sql = "show table status " + (schema == null ? "" : " from " + schema + " ") + " like '"
+ element.get("TABLE_NAME") + "' ";
PreparedStatement statement = getConnection().prepareStatement(sql);
ResultSet tableRs = statement.executeQuery();
if (tableRs.next()) {
remarks = tableRs.getString("COMMENT");
}
}
element.put("REMARKS", remarks);
return element;
}
protected Throwable handleSQLException(SQLException e) {
// schemaRs and catalogRs are only used for error reporting if
// we get an exception
String databaseStructure = getDatabaseStructure(catalog, schema);
throw getSQLExceptionConverter().convert(
e,
"Could not get list of tables from database. Probably a JDBC driver problem. "
+ databaseStructure, null);
}
};
} catch (SQLException e) {
// schemaRs and catalogRs are only used for error reporting if we get an exception
String databaseStructure = getDatabaseStructure(xcatalog, xschema);
throw getSQLExceptionConverter().convert(e,
"Could not get list of tables from database. Probably a JDBC driver problem. " + databaseStructure,
null);
}
}
* MetaData中无法取得table Comment,重载
*/
@Override
public Iterator getTables(String xcatalog, String xschema, String xtable) {
try {
final String catalog = caseForSearch(xcatalog);
final String schema = caseForSearch(xschema);
final String table = caseForSearch(xtable);
log.debug("getTables(" + catalog + "." + schema + "." + table + ")");
ResultSet tableRs = getMetaData().getTables(catalog, schema, table, new String[] { "TABLE", "VIEW" });
return new ResultSetIterator(tableRs, getSQLExceptionConverter()) {
Map element = new HashMap();
protected Object convertRow(ResultSet tableResultSet) throws SQLException {
element.clear();
putTablePart(element, tableResultSet);
element.put("TABLE_TYPE", tableResultSet.getString("TABLE_TYPE"));
String remarks = tableResultSet.getString("REMARKS");
if (StringHelper.isEmpty(remarks)) {
String sql = "show table status " + (schema == null ? "" : " from " + schema + " ") + " like '"
+ element.get("TABLE_NAME") + "' ";
PreparedStatement statement = getConnection().prepareStatement(sql);
ResultSet tableRs = statement.executeQuery();
if (tableRs.next()) {
remarks = tableRs.getString("COMMENT");
}
}
element.put("REMARKS", remarks);
return element;
}
protected Throwable handleSQLException(SQLException e) {
// schemaRs and catalogRs are only used for error reporting if
// we get an exception
String databaseStructure = getDatabaseStructure(catalog, schema);
throw getSQLExceptionConverter().convert(
e,
"Could not get list of tables from database. Probably a JDBC driver problem. "
+ databaseStructure, null);
}
};
} catch (SQLException e) {
// schemaRs and catalogRs are only used for error reporting if we get an exception
String databaseStructure = getDatabaseStructure(xcatalog, xschema);
throw getSQLExceptionConverter().convert(e,
"Could not get list of tables from database. Probably a JDBC driver problem. " + databaseStructure,
null);
}
}
外键默认生成List,修改org.hibernate.cfg.JDBCBinder
/** */
/**
* @param rc
* @param processed
* @param table
* @param object
*/
private Property bindOneToMany(PersistentClass rc, ForeignKey foreignKey, Set processed, Mapping mapping) {
Table collectionTable = foreignKey.getTable();
Collection collection
=
new
org.hibernate.mapping.Set(rc);
//
MASTER TODO: allow overriding collection type
Collection collection = new org.hibernate.mapping.Bag(rc); // MASTER TODO: allow overriding collection type
。。。
* @param rc
* @param processed
* @param table
* @param object
*/
private Property bindOneToMany(PersistentClass rc, ForeignKey foreignKey, Set processed, Mapping mapping) {
Table collectionTable = foreignKey.getTable();
。。。