所以我有这个现有的数据库模式,其中包含许多我想用JPA / Hibernate建模的表。每 table具有相同的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()方法 这样我就可以返回一个动态生成的列名?
答案 0 :(得分:13)
您需要创建自定义NamingStrategy。
假设您在JPA中使用spring和hibernate,这是一个带有自定义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(请参阅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("_", "");
}
}