Можно ли динамически определять имена столбцов в Hibernate / JPA? - PullRequest
5 голосов
/ 01 сентября 2010

Итак, у меня есть существующая схема БД с несколькими таблицами, которые я хочу смоделировать с помощью 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;
}

, в то время как это будетработа, мне не нравится жестко закодированная природа класса.

Я хотел бы смоделировать каждый набор строковых, длинных и двойных полей в качестве дополнительной группы параметров, а затем иметь 0,9 группы.Это позволило бы мне легко добавить дополнительные группы позже, если потребуется.

Если я использую решение для сопоставления xml, я могу динамически определить правильное имя столбца при создании файла .hbm.xml для каждой таблицы.Я бы предпочел использовать аннотированное решение, но есть ли способ переопределить метод @Column getName (), чтобы я мог вернуть динамически генерируемое имя столбца?

1 Ответ

13 голосов
/ 01 сентября 2010

Вам необходимо создать пользовательскую NamingStrategy .

Предполагается, что вы используете Spring и Hibernate с JPA, вот фрагмент конфигурации с пользовательской 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>

Если вы не используете Spring, конфигурация будет другой, но вы все равно можете использовать пользовательскую NamingStrategy (см. Реализация NamingStrategy из документации Hibernate).

В любом случае, вот пример 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("_", "");

    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...