Hibernate代码生成:创建抽象/具体的模型类对

时间:2013-11-28 08:37:13

标签: java spring hibernate code-generation freemarker

给出的内容:

  • 我使用hibernate代码生成生成我的模型类(hibernate tools 4)
  • 我想为每个数据库表提供一个抽象基类,以及一个具体的扩展
  • 基类应包含所有数据库字段(get / set)
  • 具体类应该从base扩展,对于transistent fields应该为空
  • 我用Apache Maven处理我的图书馆
  • 我有一个java可配置的Spring MVC环境

我已经读过你可以在hibernate工具JAR中覆盖Freemarker模板。但是当我使用Maven时,这是不可能的。

因为我使用java可配置的Spring MVC环境,如果不存在没有xml的解决方案,那将会很棒。

解决方案应该执行以下操作:

  • 为MySQL数据库中的每个表创建一个类对
  • 我不是shure,而是添加@MappedSuperclass注释?

示例: 抽象基类

@Entity
@MappedSuperclass
@Table(name = "employee", catalog = "test", uniqueConstraints = @UniqueConstraint(columnNames = "E_MAIL"))
public abstract class EmployeeBase implements java.io.Serializable {

    private Integer id;

    public Employee() {
    }

    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "ID", unique = true, nullable = false)
    public Integer getId() {
        return this.id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

示例:具体类

public class Employee extends EmployeeBase {
   // my transistent fields, for example getFirstAndLastName();
}

1 个答案:

答案 0 :(得分:0)

<强>解决方案:

  1. 创建两个ReverseEngineeringStrategies(基础和混凝土)
  2. 从HibernateTools.jar更新Freemarker模板
  3. 在Eclipse中创建代码生成配置(Hibernate插件)并设置策略和自定义模板。
  4. 切换逆向工程策略并运行两次。
  5. <强>来源:

    <强> BaseClassStrategy:

    public class BaseClassStrategy extends DelegatingReverseEngineeringStrategy {
    
        public BaseClassStrategy(ReverseEngineeringStrategy delegate) {
            super(delegate);
        }
    
        @Override
        public Map<String, MetaAttribute> tableToMetaAttributes(TableIdentifier tableIdentifier) {
    
            @SuppressWarnings("unchecked")
            Map<String, MetaAttribute> metaAttributes = super.tableToMetaAttributes(tableIdentifier);
            if (metaAttributes == null) {
                metaAttributes = new HashMap<String, MetaAttribute>();
            }
    
            // Update modifier
            if (!metaAttributes.containsKey("scope-class")) {
                MetaAttribute metaAttribute = new MetaAttribute("scope-class");
                metaAttribute.addValue("public abstract");
                metaAttributes.put(metaAttribute.getName(), metaAttribute);
            }
    
            // Update class name
            if (!metaAttributes.containsKey("generated-class")) {
                MetaAttribute metaAttribute = new MetaAttribute("generated-class");
                metaAttribute.addValue(tableToAbstractClassName(tableIdentifier));
                metaAttributes.put(metaAttribute.getName(), metaAttribute);
            }
    
            return metaAttributes;
        }   
    
        private String tableToAbstractClassName(TableIdentifier tableIdentifier) {
            String className = super.tableToClassName(tableIdentifier);
            int dotIndex = className.lastIndexOf('.');
            return className.substring(0, dotIndex + 1) + className.substring(dotIndex + 1) + "Base";
        }
    }
    

    <强> ConcreteClassStrategy:

    public class ConcreteClassStrategy extends DelegatingReverseEngineeringStrategy {
    
        public ConcreteClassStrategy(ReverseEngineeringStrategy delegate) {
            super(delegate);
        }
    
        @Override
        public Map<String, MetaAttribute> tableToMetaAttributes(TableIdentifier tableIdentifier) {
    
            @SuppressWarnings("unchecked")
            Map<String, MetaAttribute>  metaAttributes = super.tableToMetaAttributes(tableIdentifier);
            if (metaAttributes == null) {
                metaAttributes = new HashMap<String, MetaAttribute>();
            }
    
    
            String className = super.tableToClassName(tableIdentifier);
            int dotIndex = className.lastIndexOf('.');
            String abstractClassName = className.substring(dotIndex + 1) + "Base";
    
            // Update extends modifier
            if (!metaAttributes.containsKey("scope-class")) {
                MetaAttribute metaAttribute = new MetaAttribute("extends");
                metaAttribute.addValue(abstractClassName);
                metaAttributes.put(metaAttribute.getName(), metaAttribute);
            }
    
            return metaAttributes;
        }
    }
    

    休眠模板:

    将以下文件夹结构添加到您的项目中:

    src/main/resources
    |-> hibernate-templates
        |-> dao
        |-> pojo
    

    从hibernate-tools.jar复制pojo AND dao文件夹并更新以下文件。只有添加两个文件夹才能使用它!

    <强> Ejb3TypeDeclaration.ftl

    <#if ejb3?if_exists>
    <#if pojo.isComponent()>
    @${pojo.importType("javax.persistence.Embeddable")}
    <#else>
    @${pojo.importType("javax.persistence.Entity")}
    @${pojo.importType("javax.persistence.Table")}(name="${clazz.table.name}"
    <#if clazz.table.schema?exists>
        ,schema="${clazz.table.schema}"
    </#if><#if clazz.table.catalog?exists>
        ,catalog="${clazz.table.catalog}"
    </#if>
    <#assign uniqueConstraint=pojo.generateAnnTableUniqueConstraint()>
    <#if uniqueConstraint?has_content>
        , uniqueConstraints = ${uniqueConstraint} 
    </#if>)
    </#if>
    </#if>
    

    <强> Ejb3TypeDeclaration.ftl

    <#if ejb3?if_exists>
    <#if pojo.isComponent()>
    @${pojo.importType("javax.persistence.Embeddable")}
    <#else>
    @${pojo.importType("javax.persistence.MappedSuperclass")}
    </#if>
    </#if>
    

    <强> Pojo.ftl

    ${pojo.getPackageDeclaration()}
    // Generated ${date} by Hibernate Tools ${version}
    <#assign classbody>
    <#include "PojoTypeDeclaration.ftl"/> {
    
    <#if !pojo.isInterface()>
    
    <#if pojo.getDeclarationName()?ends_with("Base")>
    <#include "PojoFields.ftl"/>
    </#if>
    
    <#include "PojoConstructors.ftl"/>
    
    <#if pojo.getDeclarationName()?ends_with("Base")>
    
    <#include "PojoPropertyAccessors.ftl"/>
    
    <#include "PojoToString.ftl"/>
    
    <#include "PojoEqualsHashcode.ftl"/>
    </#if>
    
    <#else>
    <#include "PojoInterfacePropertyAccessors.ftl"/>
    
    </#if>
    <#include "PojoExtraClassCode.ftl"/>
    
    }
    </#assign>
    
    ${pojo.generateImports()}
    ${classbody}
    

    <强> PojoConstructor.ftl

    <#--  /** default constructor */ -->
    public ${pojo.getDeclarationName()}() {}
    
    <#if pojo.needsMinimalConstructor()>    
    <#-- /** minimal constructor */ -->
    public ${pojo.getDeclarationName()}(${c2j.asParameterList(pojo.getPropertyClosureForMinimalConstructor(), jdk5, pojo)}) {
        <#if pojo.getDeclarationName()?ends_with("Base")>
            <#foreach field in pojo.getPropertiesForMinimalConstructor()>
            this.${field.name} = ${field.name};
            </#foreach>
        <#else>
            super(${c2j.asArgumentList(pojo.getPropertyClosureForMinimalConstructor())});        
        </#if>
    }
    </#if>    
    
    <#if pojo.needsFullConstructor()>
    <#-- /** full constructor */ -->
    public ${pojo.getDeclarationName()}(${c2j.asParameterList(pojo.getPropertyClosureForFullConstructor(), jdk5, pojo)}) {
        <#if pojo.getDeclarationName()?ends_with("Base")>
            <#foreach field in pojo.getPropertiesForFullConstructor()> 
            this.${field.name} = ${field.name};
            </#foreach>
        <#else>
            super(${c2j.asArgumentList(pojo.getPropertyClosureForFullConstructor())});        
        </#if>
    }
    </#if>