【问题标题】:Is it possible to dynamically define column names in Hibernate / JPA?是否可以在 Hibernate/JPA 中动态定义列名?
【发布时间】:2011-04-06 18:30:12
【问题描述】:

所以我有这个现有的数据库模式,其中包含许多我想用 JPA/Hibernate 建模的表。每个 表具有相同的 30 个附加列组(以允许运行时扩展字段数 记录)。

CREATE TABLE XX
  (
    "ID"          VARCHAR2(100 BYTE) NOT NULL ENABLE,
    "USER_LABEL"      VARCHAR2(256 BYTE),
    "CREATION_DATE"   NUMBER(38,0) NOT NULL ENABLE,
    "ADD_STR_FIELD_0" VARCHAR2(200 BYTE),
    "ADD_LNG_FIELD_0" NUMBER(38,0),
    "ADD_DBL_FIELD_0" NUMBER(38,0),
    "ADD_STR_FIELD_1" VARCHAR2(200 BYTE),
    "ADD_LNG_FIELD_1" NUMBER(38,0),
    "ADD_DBL_FIELD_1" NUMBER(38,0),
    "ADD_STR_FIELD_2" VARCHAR2(200 BYTE),
    "ADD_LNG_FIELD_2" NUMBER(38,0),
    "ADD_DBL_FIELD_2" NUMBER(38,0),
    "ADD_STR_FIELD_3" VARCHAR2(200 BYTE),
    "ADD_LNG_FIELD_3" NUMBER(38,0),
    "ADD_DBL_FIELD_3" NUMBER(38,0),
    "ADD_STR_FIELD_4" VARCHAR2(200 BYTE),
    "ADD_LNG_FIELD_4" NUMBER(38,0),
    "ADD_DBL_FIELD_4" NUMBER(38,0),
    "ADD_STR_FIELD_5" VARCHAR2(200 BYTE),
    "ADD_LNG_FIELD_5" NUMBER(38,0),
    "ADD_DBL_FIELD_5" NUMBER(38,0),
    "ADD_STR_FIELD_6" VARCHAR2(200 BYTE),
    "ADD_LNG_FIELD_6" NUMBER(38,0),
    "ADD_DBL_FIELD_6" NUMBER(38,0),
    "ADD_STR_FIELD_7" VARCHAR2(200 BYTE),
    "ADD_LNG_FIELD_7" NUMBER(38,0),
    "ADD_DBL_FIELD_7" NUMBER(38,0),
    "ADD_STR_FIELD_8" VARCHAR2(200 BYTE),
    "ADD_LNG_FIELD_8" NUMBER(38,0),
    "ADD_DBL_FIELD_8" NUMBER(38,0),
    "ADD_STR_FIELD_9" VARCHAR2(200 BYTE),
    "ADD_LNG_FIELD_9" NUMBER(38,0),
    "ADD_DBL_FIELD_9" NUMBER(38,0),
}

我打算为每个表定义简单的类

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="XX")
public class XX {

    @Id
    Long id = null;
}

然后在一个通用类中定义通用的附加参数

import javax.persistence.Column;

public abstract class AdditionalParameters {

    @Column(name="ADD_STR_FIELD_0")
    private String addStringField0 = null;
    @Column(name="ADD_LNG_FIELD_0")
    private Long addLongField0 = null;
    @Column(name="ADD_DBL_FIELD_0")
    private Double addDoubleField0 = null;
    ....
    ....
    ....
    @Column(name="ADD_STR_FIELD_8")
    private String addStringField8 = null;
    @Column(name="ADD_LNG_FIELD_8")
    private Long addLongField8 = null;
    @Column(name="ADD_DBL_FIELD_8")
    private Double addDoubleField8 = null;
}

虽然这可行,但我不喜欢课程的硬编码性质。

我想将每组字符串、long 和 double 字段建模为一个附加参数组,然后 有 0..9 个组。如果需要,这将允许我稍后轻松添加额外的组。

如果我使用 xml 映射解决方案,我可以在生成 .hbm.xml 时动态确定正确的列名 对于每张桌子。我更喜欢使用带注释的解决方案,但是有没有办法覆盖 @Column getName() 方法 这样我就可以返回一个动态生成的列名?

【问题讨论】:

    标签: java hibernate orm jpa


    【解决方案1】:

    您需要创建一个自定义NamingStrategy

    假设您在 JPA 中使用 spring 和 hibernate,这里是一个带有自定义 NamingStrategy 的配置 sn-p:

    <bean id="entityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="myunit" />
        <property name="dataSource" ref="dataSource" />
        <property name="persistenceXmlLocation"
                  value="classpath:META-INF/persistence.xml" />
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="showSql" value="false" />
                <property name="generateDdl" value="true" />
                <property name="database" value="MYSQL" />
            </bean>
        </property>
        <property name="jpaProperties">
            <props>
                <prop 
                    key="hibernate.ejb.naming_strategy">
                    com.yourcompany.CustomNamingStrategy
                </prop>
            </props>
        </property>
    </bean>
    

    如果您不使用 spring,配置会有所不同,但您仍然可以使用自定义 NamingStrategy(请参阅 Hibernate 文档中的 Implementing a NamingStrategy)。

    无论如何,这里有一个示例 NamingStrategy,它为连接表构建 TYPE1_TYPE2 形式的表名,并为所有表添加一个公共前缀:

    public class CustomNamingStrategy extends ImprovedNamingStrategy {
    
        private static final long serialVersionUID = 1L;
        private static final String PREFIX = "PFX_";
    
        @Override
        public String classToTableName(final String className) {
            return this.addPrefix(super.classToTableName(className));
        }
    
        @Override
        public String collectionTableName(final String ownerEntity,
                final String ownerEntityTable, final String associatedEntity,
                final String associatedEntityTable, final String propertyName) {
            return this.addPrefix(super.collectionTableName(ownerEntity,
                    ownerEntityTable, associatedEntity, associatedEntityTable,
                    propertyName));
        }
    
        @Override
        public String logicalCollectionTableName(final String tableName,
                final String ownerEntityTable, final String associatedEntityTable,
                final String propertyName) {
            return this.addPrefix(super.logicalCollectionTableName(tableName,
                    ownerEntityTable, associatedEntityTable, propertyName));
        }
    
        private String addPrefix(final String composedTableName) {
    
            return PREFIX
                    + composedTableName.toUpperCase().replace("_", "");
    
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 2012-01-15
      • 2019-10-25
      • 2011-09-05
      • 1970-01-01
      • 1970-01-01
      • 2011-12-17
      • 2011-01-11
      • 1970-01-01
      • 2020-07-13
      相关资源
      最近更新 更多