JPA, externalizing имена столбцов, таблиц или схем?

я адаптирую приложение 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 ответов


использовать orm.xml. Это то, что JPA обеспечивает его. Размещение информации о развертывании в аннотациях-плохая идея, если вам когда-либо нужно изменить развертывание, поэтому просто иметь другое означает, что вы можете легко достичь этого. Обратите внимание, что вы можете установить схему по умолчанию в persistence-unit-defaults часть orm.xml слишком


Externalize Schema

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

на ОРМ.в XML

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

ОРМ.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>

постоянством.в 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> 

для столбцов и таблиц необходимо изменить развертывание. Невозможно заменить заполнители во время выполнения в скомпилированных классах.


Hibernate имеет org.hibernate.cfg.Configuration который является точкой, где пакеты сканируются и файлы конфигурации считываются.

он использует org.hibernate.cfg.AnnotationBinder.bindClass(...) которые читают аннотации к классам.

эти классы (8 kLOC) и методы так долго, что я не могу их легко прочитать, поэтому у меня нет надежды на конфигурацию подкласса...

никогда, если учесть, что все классы и код инициализации привязанных к конкретным классам без возможности вводить собственные, кажется, моя задача не может быть решена легко с текущих Спящий режим 4.архитектура х.

Я начинаю искать варианты и просить о externaliztion конфигурации в EBean список рассылки и получен ответ:

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 и широко использовать views и synonyms для управления, какая таблица будет доступна (Оракул):

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;

и синонимы вообще не допускают ограничения FK для Oracle!

кажется, что спящий режим диктует макет данных, и я думаю переключиться на более гибкую структуру-Ebean, но я также оцениваю sql2o и jOOQ.