因此,我拥有这个现有的数据库架构,其中包含许多要使用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()方法,以便我可以返回动态生成的列名?
您需要创建一个自定义的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文档中的实现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("_", ""); } }