是否可以在Hibernate / JPA中动态定义列名? [英] Is it possible to dynamically define column names in Hibernate / JPA?

查看:110
本文介绍了是否可以在Hibernate / JPA中动态定义列名?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  CREATE TABLE XX 

IDVARCHAR2(100 BYTE)NOT NULL ENABLE,
USER_LABELVARCHAR2(256 BYTE),
CREATION_DATENUMBER(38,0)NOT NULL ENABLE,
ADD_STR_FIELD_0VARCHAR2(200 BYTE),
ADD_LNG_FIELD_0NUMBER 38,0),
ADD_DBL_FIELD_0NUMBER(38,0),
ADD_STR_FIELD_1VARCHAR2(200 BYTE),
ADD_LNG_FIELD_1NU​​MBER(38,0),
ADD_DBL_FIELD_1NU​​MBER(38,0),
ADD_STR_FIELD_2VARCHAR2(200 BYTE),
ADD_LNG_FIELD_2NUMBER(38,0),
ADD_DBL_FIELD_2NUMBER(38,0) ,
ADD_STR_FIELD_3VARCHAR2(200 BYTE),
ADD_LNG_FIELD_3NUMBER(38,0),
ADD_DBL_FIELD_3NUMBER(38,0),
ADD_STR_FIELD_4VARCHAR2 (200 BYTE),
ADD_LNG_FIELD_4NUMBER(38,0),
ADD_DBL_FIELD_4NUMBER(38,0),
ADD_STR_FIELD_5VARCHAR2(200 BYTE),
ADD_LNG_FIELD_5NUMBER(38,0),
ADD_DBL_FIELD_5NUMBER(38,0),
ADD_STR_FIELD_6VARCHAR2(200 BYTE),
ADD_LNG_FIELD_6NUMBER(38,0),
ADD_DBL_FIELD_6NUMBER(38,0),
ADD_STR_FIELD_7VARCHAR2(200 BYTE),
ADD_LNG_FIELD_7NUMBER(38,0),
ADD_DBL_FIELD_7NUMBER(38,0),
ADD_STR_FIELD_8VARCHAR2(200 BYTE),
ADD_LNG_FIELD_8NUMBER(38 ,0),
ADD_DBL_FIELD_8NUMBER(38,0),
ADD_STR_FIELD_9VARCHAR2(200 BYTE),
ADD_LNG_FIELD_9NUMBER(38,0),
ADD_DBL_FIELD_9NUMBER(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;
}

虽然这会起作用,但我不喜欢类的硬编码本质。

我想将每组字符串,长字段和双字段建模为一个附加参数组,然后
拥有0..9个组。这将允许我稍后在需要时轻松添加额外的组。



如果我使用xml映射解决方案,我可以在生成.hbm.xml时动态地确定正确的列名称$每桌
。我宁愿使用注解的解决方案,但有没有办法来覆盖@Column getName()方法
,这样我就可以返回一个动态生成的列名称?

解决方案

您需要创建一个自定义

 < bean id =entityManagerFactory
class =org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean>
< property name =persistenceUnitNamevalue =myunit/>
< property name =dataSourceref =dataSource/>
< property name =persistenceXmlLocation
value =classpath:META-INF / persistence.xml/>
< property name =jpaVendorAdapter>
< bean class =org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter>
< property name =showSqlvalue =false/>
< property name =generateDdlvalue =true/>
< property name =databasevalue =MYSQL/>
< / bean>
< / property>
< property name =jpaProperties>
<道具>
< prop
key =hibernate.ejb.naming_strategy>
com.yourcompany.CustomNamingStrategy
< / prop>
< /道具>
< / property>
< / bean>

如果您不使用spring,配置将会不同,但您仍然可以使用自定义的NamingStrategy (请参阅实施命名策略来自Hibernate Documentation)。



无论如何,下面是一个示例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));

$ b @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));

$ b @Override
public String logicalCollectionTableName(final String tableName,
final String ownerEntityTable,final String associatedEntityTable,
final String propertyName){
返回this.addPrefix(super.logicalCollectionTableName(tableName,
ownerEntityTable,associatedEntityTable,propertyName));


private String addPrefix(final String composedTableName){

return PREFIX
+ composedTableName.toUpperCase()。replace(_, );

}

}


So i have this existing DB schema with a number of tables that i want to model with JPA/Hibernate. Each table has the same group of 30 additional columns ( to allow for runtime expansion of the number of fields recorded).

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

I plan to define simple classes for each table

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

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

    @Id
    Long id = null;
}

and then define the common additional parameters in a common class

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

while this will work, i don't like the hardcoded nature of the class.

I would like to model each set of string,long and double fields as an additional parameter group, and then have 0..9 groups. This would allow me easily add extra groups later if required.

If i use the xml mapping solution i can dynamically determine the correct column name when generating the .hbm.xml for each table. I would prefer to use an annotated solution, but is there a way to override the @Column getName() method so that i can return a dynamically generated column name?

解决方案

You need to create a custom NamingStrategy.

Assuming you use spring and hibernate with JPA, here is a configuration snippet with a custom NamingStrategy:

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

If you don't use spring, configuration will be different, but you can still use a custom NamingStrategy (see Implementing a NamingStrategy from the Hibernate Documentation).

Anyway, here is a sample NamingStrategy that builds table names of the form TYPE1_TYPE2 for join tables and adds a common prefix to all tables:

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("_", "");

    }

}

这篇关于是否可以在Hibernate / JPA中动态定义列名?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆