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