成长的记忆

整理学习中的心得体会,记录开发中的酸甜苦辣,这是成长的记忆

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  5 随笔 :: 0 文章 :: 36 评论 :: 0 Trackbacks
最近做项目时,使用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
<#-- // 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>

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>

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);
                }
                
            }

        }

        
    }

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

补充:
无法取得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);
        }

    }

外键默认生成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
。。。
posted on 2009-11-13 00:20 小牧 阅读(9479) 评论(23)  编辑  收藏 所属分类: Hibernate

评论

# re: Hibernate Tools生成注释 2010-01-22 11:21 zuiwoguzhu
把它弄好,发布出来,谢谢了!  回复  更多评论
  

# re: Hibernate Tools生成注释 2010-01-25 17:45 小牧
@zuiwoguzhu

http://www.blogjava.net/pauliz/archive/2010/01/25/310754.html  回复  更多评论
  

# re: Hibernate Tools生成注释 2010-05-28 14:31 James Liu
请问如何得到其源代码进行修改?  回复  更多评论
  

# re: Hibernate Tools生成注释 2010-06-01 08:22 小牧
@James Liu

http://anonsvn.jboss.org/repos/hibernate/trunk/HibernateExt/tools/
  回复  更多评论
  

# re: Hibernate Tools生成注释 2010-06-04 17:55 James Liu
@小牧
多谢,不过修改好后发现外键关系没有生成了。  回复  更多评论
  

# re: Hibernate Tools生成注释 2010-06-04 22:34 小牧
@James Liu

所有的修改都没有涉及外键,不知你是否改到其他地方?
或者最新的trunk代码已做了不同处理
如果没有其他需求的话,直接到http://www.blogjava.net/pauliz/archive/2010/01/25/310754.html 下载修改好的jar包替换吧  回复  更多评论
  

# re: Hibernate Tools生成注释 2010-06-06 07:47 James Liu
再次表示感谢,原来我用的是3.3的版本,修改之前就不能生成外键关系。我测试的是MYSQL数据库,不知其他数据库能否生成?  回复  更多评论
  

# re: Hibernate Tools生成注释 2010-06-07 08:39 James Liu
@小牧
用oracle试过了,能生成外键关系,但是不能生成注释,呵呵。  回复  更多评论
  

# re: Hibernate Tools生成注释 2010-10-22 00:24 yangghost
用oracle生成不了注释..测试过了..
中文问题最关键的地方还是
org.hibernate.tool.hbm2x.TemplateHelper类
在freeMarkerEngine = new Configuration();后面添加
freeMarkerEngine.setDefaultEncoding("UTF-8");
要不然还是会乱码
  回复  更多评论
  

# re: Hibernate Tools生成注释 2010-10-22 00:25 yangghost
生成LIST使用的是
Collection collection = new org.hibernate.mapping.List(rc); // MASTER TODO: allow overriding collection type
你那个是生成collection的
  回复  更多评论
  

# re: Hibernate Tools生成注释 2010-10-22 00:29 yangghost
oracle在主键字段生成为long不是Long的原因
org.hibernate.cfg.reveng.JDBCToHibernateTypeHelper类
public static String getPreferredHibernateType(int sqlType, int size, int precision, int scale, boolean nullable, boolean generatedIdentifier)方法中
把为空的判断去掉.全部返回包装类.
if (precision == 1) {
// NUMERIC(1) is a often used idiom for storing boolean thus providing it out of the box.
return returnNullable?Boolean.class.getName():"boolean";
}
else if (precision < 3) {
return Byte.class.getName();
}
else if (precision < 5) {
return Short.class.getName();
}
else if (precision < 10) {
return Integer.class.getName();
}
else if (precision < 19) {
return Long.class.getName();
}
else {
return "big_decimal";
}  回复  更多评论
  

# re: Hibernate Tools生成注释 2010-10-22 04:49 yangghost
终于把oracle注释和模板都改好了...哈哈
快5点了.天亮了..汗..
果然是个旧东西...还是要自己改改..  回复  更多评论
  

# re: Hibernate Tools生成注释 2010-10-22 23:50 小牧
@yangghost
以上修改只在Hibernate Tools 3.2.4、MySQL 5.1.39上做了测试,其他数据库没有跑过  回复  更多评论
  

# re: Hibernate Tools生成注释 2010-10-22 23:55 小牧
@yangghost
生成LIST使用的是
Collection collection = new org.hibernate.mapping.List(rc); // MASTER TODO: allow overriding collection type
你那个是生成collection的

org.hibernate.mapping.Bag(rc)没有问题,根据Hibernate API,Bag是集合类型,一般映射为List,在hbm.xml中也是<bag />,我一直这么用  回复  更多评论
  

# re: Hibernate Tools生成注释 2010-10-23 23:22 yangghost
小牧你有QQ么?加我88241787,讨论下
我用这个org.hibernate.mapping.Bag(rc)类,
在oracle下生成的是Collection 不是List
现在在oracle下表注释和列注释我都弄好了.
明天再把代码贴上来  回复  更多评论
  

# re: Hibernate Tools生成注释 2010-10-24 23:13 yangghost
列注释
JDBCReaderFactory类中
newMetaDataDialect方法中
在if(dialect!=null) { // temporary hack to enable dialect specific metadata dialects. 里面的代码改为
if(dialect instanceof Oracle9Dialect) {
return new OracleMetaDataDialect();
} else if (dialect instanceof Oracle9iDialect) {
return new OracleMetaDataDialect();
} else if (dialect instanceof OracleDialect) {
return new OracleMetaDataDialect();
} else if (dialect instanceof H2Dialect) {
return new H2MetaDataDialect();
} else if (dialect instanceof MySQLDialect) {
return new MySQLMetaDataDialect();
}

  回复  更多评论
  

# re: Hibernate Tools生成注释 2010-10-24 23:15 yangghost
表注释
TableIdentifier类中
增加属性
private String comment = "";
以及set & get方法
public String getComment() {
return comment;
}

public void setComment(String comment) {
this.comment = comment;
}

  回复  更多评论
  

# re: Hibernate Tools生成注释 2010-10-26 11:24 小牧
@yangghost
应该没有改其他地方,直接就生成List,不过是在MySQL上测试,Oracle没试,照理说应该一样  回复  更多评论
  

# re: Hibernate Tools生成注释 2012-04-17 14:27 dingbowell
求急助。在哪儿可以找到Hibernate Tools 3.4.0的源码吖,请问楼主是怎么找到源码的,我需要改文件中的代码,但需要源码啊……  回复  更多评论
  

# re: Hibernate Tools生成注释 2012-04-17 14:42 小牧
@dingbowell
在这里找一下吧
http://sourceforge.net/projects/hibernate/files/

https://github.com/hibernate/hibernate-tools/  回复  更多评论
  

# re: Hibernate Tools生成注释 2013-07-02 16:15 SHELL
关于无法取得MySQL5 Table的Comments的问题,楼主的修改源码的方案是可行的。当我从GitHub获取了hibernate-tools源码,并修改了“org.hibernate.cfg.reveng.dialect.JDBCMetaDataDialect”类之后,问题解决了。
这时候,我突然想到个问题,既然是通过JDBC获取数据库元信息,没有获取到,应该是数据库厂商JDBC驱动有问题,为什么要去修改hibernate-tools的源码呢?
最后我找到了MySQL驱动的这个bug(http://bugs.mysql.com/bug.php?id=65213),并从该bug页找到了解决方案:
修改MySQL JDBC驱动URL,在其后追加:“?useUnicode=true&amp;characterEncoding=UTF-8&amp;useInformationSchema=true”即可。  回复  更多评论
  

# re: Hibernate Tools生成注释 2015-02-03 18:17 马行空
大神,类的表comment还没有呢  回复  更多评论
  

# re: Hibernate Tools生成注释 2015-02-03 18:19 马行空
大神,请问怎么让hibernate tools默认accesstype是field啊,求教  回复  更多评论
  


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


网站导航:
博客园   IT新闻   Chat2DB   C++博客   博问