JPA, external columns, table or schema names?

I am adapting the Spring + Hibernate + Tomcat + Oracle application to a distributed form and should make the schema names customizable in JPA annotations, something like Spring EL:

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

I am looking for placeholder support in annotations like ${app.dataSchema} in the above example. Or any other opportunity ...

The idea is to have an application that can be deployed to another site without recompilation, where the database relationship / hierarchy is saved, but some names are changed and can be configured using the system properties, JNDI, or deploy a context descriptor.

One solution that I see - before create view in the selected schema - is to provide a bridge between the actual names of the schemas / tables / columns and hardcoded applications.

But I hope JPA / Hibernate / Spring have some tools for this configuration ...

+6
source share
3 answers

Hibernate has org.hibernate.cfg.Configuration , which is the point at which packets are scanned and configuration files are read.

It uses org.hibernate.cfg.AnnotationBinder.bindClass(...) , which reads class annotations.

These classes (8 kLOC) and methods are so long that I cannot read them easily, so I have no hope for a subclass of Configuration ...

Given that all classes and initialization code that are tied to specific classes without the ability to enter their own, it seems that my task cannot be easily solved using the current Hibernate 4.x architecture.

I start looking for alternatives and ask about externalization of the configuration in the EBean mail list and I got the 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; } 

So simple that I say goodbye to Hibernate!

UPDATE @Xstian. Before switching to Ebean, I set the default schema via hibernate.default_schema and made extensive use of view and synonym to control which table would be available (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; 

During the transition to views / synonyms, I only have a problem with DB constraints.

If you use the Oracle-FK constraint on the view, do not work unless you add a constraint with the disable novalidate and the same as that specified in 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; 

And synonyms do not allow limiting FK for Oracle at all!

Hibernate seems to dictate the data structure, and I think switching to a more flexible structure is Ebean, but I also evaluate sql2o and jOOQ .

+1
source

Use orm.xml . This is what the JPA provides. Putting deployment information in annotations is a bad idea if you ever need to change the deployment, so just having another orm.xml file means you can easily achieve this. Please note that you can set the default scheme in part while preserving the default unit of measurement orm.xml too

+3
source

Appearance scheme

By 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> 

In 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> 

By 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> 

For columns and tables, deployment must be changed. You cannot replace run-time placeholders in compiled classes.

+3
source

Source: https://habr.com/ru/post/975661/


All Articles