JPA,外化列,表或模式名称?

时间:2014-09-22 15:53:24

标签: spring hibernate tomcat jpa

我将Spring + Hibernate + Tomcat + Oracle应用程序改编为分布式表单,需要在JPA注释中定制模式名称,类似于Spring EL:

@Entity
@Table(name = "LOSS", schema="${app.dataSchema}")
public class Loss { ... }

我在上面的示例中寻找像${app.dataSchema}这样的注释中占位符的支持。或任何其他可能性......

想法 - 拥有可以在不重新编译的情况下部署在另一个站点上的应用程序,其中保留了数据库关系/层次结构,但某些名称已更改,可以通过系统属性,JNDI或部署上下文描述符进行配置。

我看到的一个解决方案 - 在所选架构中create view - 提供实际架构/表/列与应用程序硬编码名称之间的桥梁。

但是我希望JPA / Hibernate / Spring有一些这样的配置工具......

3 个答案:

答案 0 :(得分:3)

使用orm.xml。这就是JPA提供的。如果您需要更改部署,那么将部署信息放在注释中是一个坏主意,因此只需拥有一个不同的orm.xml文件就可以轻松实现这一目标。请注意,您也可以在orm.xml persistence-unit-defaults 部分设置默认架构

答案 1 :(得分:3)

外化架构

按EntityManagerFactory

<bean id="domainEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="pun"/>
    <property name="dataSource" ref="domainDataSource"/>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="generateDdl" value="false"/>
            <property name="showSql" value="false"/>
            <property name="databasePlatform" value="${hibernate.dialect}"/>
        </bean>
    </property>
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.hbm2ddl.auto">create-update</prop>
            <prop key="hibernate.default_schema">${yourSchema}</prop>
        </props>
    </property>
</bean>

通过orm.xml

...
  <persistence-unit name="MySchemaPU"  transaction-type="JTA">
    <provider>
     <mapping-file>META-INF/orm.xml</mapping-file>
...

下面的orm.xml:

<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_1_0.xsd"
                 version="1.0">
 <persistence-unit-metadata>

  <persistence-unit-defaults>
   <schema>myschema</schema>
  </persistence-unit-defaults>
 </persistence-unit-metadata>
</entity-mappings>

通过persistence.xml

<persistence-unit name="myPersistenceUnit" transaction-type="RESOURCE_LOCAL">
      <provider>org.hibernate.ejb.HibernatePersistence</provider>

      <jta-data-source>myDatasource</jta-data-source>

      <properties>
        .....
        <property name="hibernate.default_schema" value="MYSCHEMA"/>
      </properties>
</persistence-unit> 

对于列和表,必须更改部署。您无法在编译的类中替换运行时的占位符。

答案 2 :(得分:1)

Hibernate有org.hibernate.cfg.Configuration,这是扫描包并读取配置文件的一个点。

它使用org.hibernate.cfg.AnnotationBinder.bindClass(...)读取类的注释。

这些类(8 kLOC)和方法太长了以至于我无法轻松阅读它们,所以我没有希望将子类配置为......

如果注意到所有类和初始化代码绑定到具体类而没有注入自己的可能性,似乎我的任务无法通过当前的Hibernate 4.x架构轻松解决。

我开始寻找替代方案并询问EBean邮件列表和got answer中配置的外部化:

public class MySchemaNamingConvention
    extends com.avaje.ebean.config.UnderscoreNamingConvention {

@Override
protected TableName getTableNameFromAnnotation(Class<?> beanClass) {
   final Table t = findTableAnnotation(beanClass);
   if (t != null && !isEmpty(t.name())) {
       String catalog = t.catalog();
       String schema = t.schema();
       //////   CUSTOM schema processing code HERE.
       //////   CUSTOM schema processing code HERE.
       //////   CUSTOM schema processing code HERE.
       return new TableName(quoteIdentifiers(catalog),
                            quoteIdentifiers(schema),
                            quoteIdentifiers(t.name()));
     }
     return null;
}

我很容易告诉Hibernate!

更新 @Xstian。在迁移到Ebean之前,我通过hibernate.default_schema设置默认架构,并广泛使用viewsynonym来控制哪些表可访问(Oracle):

grant select on ANOTHER_SCHEMA.TBL to MY_SCHEMA;

create or replace view MY_SCHEMA.TBL as select * from ANOTHER_SCHEMA.TBL;

create or replace synonym MY_SCHEMA.TBL for ANOTHER_SCHEMA.TBL;

在迁移到视图/同义词期间,我只遇到数据库约束问题。

如果您使用Oracle-FK约束视图不起作用,除非您使用disable novalidate关键字添加约束并且与引用的PK相同:

alter view MY_SCHEMA.XXX add constraint PK_XXX primary key(ID) disable novalidate;

alter table/view MY_SCHEMA.TBL add constraint FK_XXX foreign key (XXX_ID)
  references MY_SCHEMA.XXX (ID) disable novalidate;

同义词根本不允许对Oracle进行FK约束!

似乎Hibernate要求数据布局,我想切换到更灵活的框架--Ebean,但我也评估sql2ojOOQ

相关问题