首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

让Hibernate生成的DDL脚本自动增多注释

2013-10-09 
让Hibernate生成的DDL脚本自动增加注释我们知道可以通过Hibernate对象自动生成DDL建表语句,通过PowerDesig

让Hibernate生成的DDL脚本自动增加注释


我们知道可以通过Hibernate对象自动生成DDL建表语句,通过PowerDesigner工具可以反向工程生成数据字典,但是在生成的DDL中一直不能写上中文的注释,这就使我们生成的数据字典不具有可用性。

这个假期宅在家里调试代码,发现Hibernate的Dialect,Table,Column的映射中已经做了comment的处理,只是Hibernate团队认为这个功能的重要性太小,一直没有时间提供这个需求,于是就自己动手实现这个功能了,这可是使用我们的数据对象代码与数据字典文档同步的关键一环啊!

通过对Hibernate代码的跟踪发现了处理映射的逻辑是在代码AnnotationBinder中,我们不需要在运行期间处理comment,只是在用SchemaExport时处理就可以,于是简单的实现了此功能:

1. 增加一个注解 @Comment("这是表的说明,也可以是字段的说明"),适用在类名和属性名

2. 复制org.hibernate.cfg.AnnotationBuilder代码为org.hibernate.cfg.MyAnnotationBuilder,处理注解@Comment

3. 复制org.hibernate.cfg.Configuration为org.hibernate.cfg.MyConfiguration,将AnnotationBuilder的调用换成MyAnnotationBuilder

3. 实现SchemaExportTool类,传入MyConfiguration处理Hibernate对象的映射关系,并生成DDL

 

以上思路在基于Hibernate 4.2.3版本在MySql 5.1上测试成功,因为代码只是在开发期运行,不需要良好的结构和优化,所以只是简单实现了,需要此功能的朋友可以自己实现。

 

以下是处理结果示例:

@Entity@Table(name = "AuditRecord_")@Comment("系统审计表")@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)public class AuditRecord implements Serializable {private static final long serialVersionUID = 8844543936912679937L;@Id@GeneratedValue@Comment("ID主键")private Long id;@Comment("审计类型")@Column(length = 30)private String auditType;@Comment("操作人")@ManyToOne@JoinColumn(name = "userId")private Passport operator;// 操作简述@Comment("操作简述")@Column(length = 4000)private String description;@Comment("创建时间")private Date creationTime;}


生成的DDL如下:

create table audit_record_ (        id bigint not null auto_increment comment 'ID主键',        audit_type varchar(30) comment '审计类型',        creation_time datetime comment '创建时间',        description longtext comment '操作简述',        user_id bigint comment '操作人',        primary key (id)    ) comment='系统审计表';


 

主要代码片断如下:

 

import java.io.IOException;import java.util.Properties;import javax.persistence.Embeddable;import javax.persistence.Entity;import javax.persistence.MappedSuperclass;import org.hibernate.MappingException;import org.hibernate.cfg.MyConfiguration;import org.hibernate.tool.hbm2ddl.SchemaExport;import org.springframework.core.io.Resource;import org.springframework.core.io.support.PathMatchingResourcePatternResolver;import org.springframework.core.io.support.ResourcePatternResolver;import org.springframework.core.io.support.ResourcePatternUtils;import org.springframework.core.type.classreading.CachingMetadataReaderFactory;import org.springframework.core.type.classreading.MetadataReader;import org.springframework.core.type.classreading.MetadataReaderFactory;import org.springframework.core.type.filter.AnnotationTypeFilter;import org.springframework.core.type.filter.TypeFilter;import org.springframework.util.ClassUtils;public class SchemaExportTool extends MyConfiguration {private static final long serialVersionUID = 1L;private static final String RESOURCE_PATTERN = "/**/*.class";private static final String PACKAGE_INFO_SUFFIX = ".package-info";private static final TypeFilter[] ENTITY_TYPE_FILTERS = new TypeFilter[] {new AnnotationTypeFilter(Entity.class, false),new AnnotationTypeFilter(Embeddable.class, false),new AnnotationTypeFilter(MappedSuperclass.class, false) };private final ResourcePatternResolver resourcePatternResolver;public SchemaExportTool() {this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(new PathMatchingResourcePatternResolver());}public static void main(String[] args) {try {Properties p = new Properties();p.setProperty("hibernate.dialect","org.hibernate.dialect.MySQLDialect");SchemaExportTool cfg = new SchemaExportTool();cfg.addProperties(p);cfg.setNamingStrategy(new ImprovedMyNamingStrategy());cfg.scanPackage("com.share.passport.domain","com.share.authority.domain", "com.share.utils.domain");SchemaExport se = new SchemaExport(cfg);if (null != args && args.length > 1)if ("-f".equals(args[0]))se.setOutputFile(args[1]);elsese.setOutputFile("create_table.sql");elsese.setOutputFile("create_table.sql");se.setDelimiter(";");// se.drop(false, false);se.create(false, false);} catch (Exception e) {e.printStackTrace();}}private SchemaExportTool scanPackage(String... packagesToScan) {try {for (String pkg : packagesToScan) {String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX+ ClassUtils.convertClassNameToResourcePath(pkg)+ RESOURCE_PATTERN;Resource[] resources = this.resourcePatternResolver.getResources(pattern);MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(this.resourcePatternResolver);for (Resource resource : resources) {if (resource.isReadable()) {MetadataReader reader = readerFactory.getMetadataReader(resource);String className = reader.getClassMetadata().getClassName();if (matchesEntityTypeFilter(reader, readerFactory)) {addAnnotatedClass(this.resourcePatternResolver.getClassLoader().loadClass(className));} else if (className.endsWith(PACKAGE_INFO_SUFFIX)) {addPackage(className.substring(0,className.length()- PACKAGE_INFO_SUFFIX.length()));}}}}return this;} catch (IOException ex) {throw new MappingException("Failed to scan classpath for unlisted classes", ex);} catch (ClassNotFoundException ex) {throw new MappingException("Failed to load annotated classes from classpath", ex);}}/** * Check whether any of the configured entity type filters matches the * current class descriptor contained in the metadata reader. */private boolean matchesEntityTypeFilter(MetadataReader reader,MetadataReaderFactory readerFactory) throws IOException {for (TypeFilter filter : ENTITY_TYPE_FILTERS) {if (filter.match(reader, readerFactory)) {return true;}}return false;}}

/** * $Id:$ */package com.share.utils.hibernate;import org.hibernate.annotations.common.reflection.XClass;import org.hibernate.annotations.common.reflection.XProperty;import org.hibernate.cfg.Ejb3Column;import org.hibernate.mapping.PersistentClass;import com.share.annotations.Comment;public class CommentBinder {    public static void bindTableComment(XClass clazzToProcess, PersistentClass persistentClass) {        if (clazzToProcess.isAnnotationPresent(Comment.class)) {            String tableComment = clazzToProcess.getAnnotation(Comment.class).value();            persistentClass.getTable().setComment(tableComment);        }    }    public static void bindColumnComment(XProperty property, Ejb3Column[] columns) {        if (null != columns)            if (property.isAnnotationPresent(Comment.class)) {                String comment = property.getAnnotation(Comment.class).value();                for (Ejb3Column column : columns) {                    column.getMappingColumn().setComment(comment);                }            }    }    public static void bindColumnComment(XProperty property, Ejb3Column column) {        if (null != column)            if (property.isAnnotationPresent(Comment.class)) {                String comment = property.getAnnotation(Comment.class).value();                column.getMappingColumn().setComment(comment);            }    }}
/** * $Id:$ */package com.share.annotations;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target({ElementType.TYPE,ElementType.FIELD})@Retention(RetentionPolicy.RUNTIME)public @interface Comment {    String value() default "";}


热点排行