【问题标题】:Hibernate code generation: Create abstract/concrete model class pairsHibernate 代码生成:创建抽象/具体模型类对
【发布时间】:2013-11-28 08:37:13
【问题描述】:

给出的内容:

  • 我使用休眠代码生成(休眠工具 4)生成模型类
  • 我希望每个数据库表都有一个抽象基类,以及一个具体的扩展
  • 基类应包含所有数据库字段(get/set)
  • 具体类应从基类扩展,并且对于瞬态字段应为空
  • 我使用 Apache Maven 处理我的库
  • 我有一个 java 配置的 Spring MVC 环境

我了解到您可以在休眠工具 JAR 中覆盖 Freemarker 模板。但是当我使用 Maven 时,这是不可能的。?

因为我使用 java 配置的 Spring MVC 环境,如果存在没有 xml 的解决方案,那就太好了。

解决方案应该做到以下几点:

  • 为 MySQL 数据库中的每个表创建一个类对
  • 我不是舒尔,而是加@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();
}

【问题讨论】:

  • 使用 <dependencyManagement>,您应该能够将 Maven 指向您的自定义版本的休眠工具 JAR,而不是来自存储库的那个。 (即,您将获得工具 JAR,修改模板,然后将其安装到您公司的 groupName 下的本地或站点存储库中。)
  • 好的,谢谢,我会检查一下,但我仍然没有好的方法来编写符合我要求的模板。
  • 这种缺乏方法的背后是什么?你看过现有的模板吗?您是否尝试过搜索“休眠自定义模板”?戳Hibernate Tools docs 至少看看下一步该往哪里看?除了在这里列出您的高级要求之外还有什么?
  • 我找到了这个休眠 jira 条目hibernate.atlassian.net/browse/HBX-1110,我现在尝试实现它。我只是问了,因为也许有人遇到了同样的问题并且已经有了可行的解决方案。
  • 这不是 SO 的真正用途,抱歉。一般的期望是您在发帖前自己做自己能做的事情。

标签: java spring hibernate code-generation freemarker


【解决方案1】:

解决方案:

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

来源:

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 和 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>    

【讨论】:

    猜你喜欢
    • 2011-01-08
    • 2012-09-25
    • 2010-09-23
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 2018-08-05
    • 1970-01-01
    相关资源
    最近更新 更多