Spring Data JPA, Hibernate #Table - java

I have a problem:
My application has an MSSQL host in which there are 2 databases.
All my entities look at base number:
And one Entity should look at base
I can do this by specifying the base in the #Table parameter (schema = databasename.schema)
Is there any way to make the #Table (schema) parameter come from application.properties?

Yes, it is possible. Look at the following properties:
<property name="hibernate.default_catalog" value="crm"/>
<property name="hibernate.default_schema" value="analytics"/>
You can use the following properties in the spring boot application.properties:
spring.jpa.properties.hibernate.default_catalog=crm
spring.jpa.properties.hibernate.default_schema=analytics
Look also at the #Table annotation documentation. When you set the schema attribute hibernate uses this specified schema, otherwise it is used user default schema that you can provide via hibernate.default_schema.
Also you can try to write your custom schema name resolver. As it stated in the documentation for the hibernate.schema_name_resolver property:
By default, Hibernate uses the org.hibernate.dialect.Dialect#getSchemaNameResolver. You can customize how the schema name is resolved by providing a custom implementation of the SchemaNameResolver interface.

Related

Dynamic dialect with Hibernate and Hikari

I am new at Hibernate.
Into my code, the connection to the DB is managed with the Hikari data source.
My code is right now multitenant, but it manages the same hibernate dialect for all tenants.
Is it possible to create a configuration where each tenant can use a different dialect?
The type of dialect can be provided as a tenant's property.
This is an example of the entityManagerFactory:
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
Map<String, Object> jpaProperties = new HashMap<>();
jpaProperties.put(..., ...);
jpaProperties.put(org.hibernate.cfg.Environment.DIALECT, "myDialect");
LocalContainerEntityManagerFactoryBean emfBean = new LocalContainerEntityManagerFactoryBean();
emfBean.setPackagesToScan(new String[] {MyEntity.class.getPackage().getName()});
emfBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
emfBean.setJpaPropertyMap(jpaProperties);
return emfBean;
}
Edit
I was looking to this solution: it suggests to create a duplicated LocalContainerEntityManagerFactoryBean for each dialect.
What I do not understand is how can I tell when using one EntityManager (MySQL) and when the other one (Postgres or MsSQL): the solution discriminates the entities (each entity has its own DB) but in my case, all entities are on all DBs. Is the tenant that discriminates.
For example: if I create a second instance of LocalContainerEntityManagerFactoryBean (i.e. msSQLEntityManagerFactory()) with setted the dialect for SQL Server, the application fails to start with:
Application failed to start due to an exceptionorg.springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type 'javax.persistence.EntityManagerFactory' available:
expected single matching bean but found 2:
msSQLEntityManagerFactory,entityManagerFactory
That's not really possible as the dialect affects certain quoting rules etc. which you can't just "swap out" at runtime based on a tenant identifier. Just create two persistence units, each pointing to a different data source for every database type. You will have to somehow lookup the appropriate EntityManager/EntityManagerFactory based on your tenant identifier which makes it a bit harder when you want to use Spring Data JPA as that requires a compilation static name reference for the entity manager factory. Maybe you can create a custom EntityManagerFactory that delegates all method calls to the appropriate instance based on the tenant identifier. Overall, this is not so easy and you will probably have to do a lot of trial and error.
IMO it would be better to have a separate application deployment with separate configuration if possible per database type.
I finally managed to find a solution for this problem.
I managed to get around the problem with the dialects by having an entity manager factory for each dialect (in this case MySQL, Postgres and MS SQL Server).
Create a bean for EntityManagerFactory and return a proxy of that interface and in the handler, based on your logic, you can switch which emf to use to suit the used data source.
I have created a video for this because it seems like there is no documentation online.
Session Scoped Connection
It is pretty similar to what you're trying to achieve but in my case the users are providing the credentials, so it's even more complicated.

Spring context:property-placeholder for a boolean value

I am working on an application where I have two classes both implementing a common interface. So in time of bean declaration, I am going to mark one of them primary in my app-context.xml file. I can achieve this by simply declaring the primary bean like this:
<bean id="oracleImpl" class="com.me.dao.OracleImpl" primary="true">
</bean>
Now I don't want to hard code which of the beans is going to be the primary bean, rather want to read the true/false value from a properties file. So I went like this:
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="oracleImpl" class="com.me.dao.OracleImpl" primary="${oracle.primary}">
</bean>
<bean id="pgsqlImpl" class="com.me.dao.PgsqlImpl" primary="${pgsql.primary}">
</bean>
The values of oracle.primary and pgsql.primary are defined in the file jdbc.properties along with other jdbc (non-boolean) properties.
But it doesn't work and says, "'${oracle.primary}' is not a valid value for 'boolean'"
I have a feeling it is something to do with the xsd validators. Browsing through this site and google gave me this much idea, but got no real solution. Can any body help?
This will not work.
As of 3.2.5.RELEASE only the following bean definition elemets support property placeholder:
parent name
bean class name
factory bean name
factory method name
scope
property values
indexed constructor arguments
generic constructor arguments
See the BeanDefinitionVisitor's visitBeanDefinition method for the details. This method is used by the PlaceholderConfigurerSupport.
I would recommend you to create a feature request in the spring issue management system.
PS: if you create an issue please add a comment to the issues url.

how can I use persistence.xml to configurate apache-common-dbutils?

JPA is pretty good for immutable tables but I can't handle dynamic table.
Then I decide to use JPA for handle al the unalterable tables (the core of the application) and dbutils from apache to handle all my the dynamic tables
Both kind of tables are in the same database and I want to define the configuration of the database only in a single file
I define the jpa in a property file:
javax.persistence.jdbc.driver=com.mysql.jdbc.Driver
javax.persistence.jdbc.user=root
javax.persistence.jdbc.password=*****
javax.persistence.jdbc.url=jdbc:mysql://localhost:3306/database
But dbutils use the class "datasource" to configurate.
I didn't find how to get a "Datasource" from de "EntityManagerFactory" of jpa.
Or to get a instance of "EntityManagerFactory" from a "Datasource".
An EMF can be created for a (javax.sql.)DataSource by specifying the persistence-unit "jta-data-source" or "non-jta-data-source" (the JNDI name for the DataSource). So create the DataSource, make it accessible via JNDI, and then you can use it in the EMF and this "dbutils".

How to configure JPA at run time(specialy schema of tables)

I am using JPA and I use Entity XML mapping Files to config my persistence layer on the other hand I have multiple database schemas in an Oracle database
In the persistence configuration, i want to have only one EntityManagerFactory and in fact i want to have connection with database with only one schema(USER).
Statically, I can specify schema name one by one to my Entities in Mapping files like this:
<entity class="package.MyClass" name="MyClass">
<table name="MYTABLE" schema="mySchema"/>
My persistence provider in this project is: org.hibernate.ejb.HibernatePersistence
I want to use a placeholder for specifying schema and replace that when JPA scan mapping files to configure itself.
<entity class="package.MyClass" name="MyClass">
<table name="MYTABLE" schema="#placeholder"/>
at config time replace #placeholder with mySchema
Is anyway to do this?
Which part (class) in JPA scan XML mapping files and can i customize that class to do this replace for me?
I think you can use the bootstrap procedure to access the EntityManagerFactory and the EntityManager at runtime to override the properties.

Spring Annotations - I am getting some documents regarding Annotaions

Spring Annotations - I am getting some documents regarding Annotations but, they are explaining each annotation and how to use it.
but i want, know how can achieve same annotations behavior with bean configuration.
ex:
Annotation Bean config
#Required ?
Can you help.................
I don't really understand your question, but here are some links from the Spring Reference that seem relevant:
3.9. Annotation-based container configuration
3.11. Java-based container configuration
On second thought (and after editing your question's source) I seem to understand. I think you want an XML alternative to the #Required annotation.
Quote from the #Required section:
The container throws an exception if the affected bean property has not been populated; this allows for eager and explicit failure, avoiding NullPointerExceptions or the like later on.
I'm not sure such a thing exists in XML, I think the only way to get that behavior is through explicit wiring.
<bean class"foo.bar.Service.class">
<!-- This will fail if no bean named subService is available -->
<property name="subService" ref="subService" />
</bean>

Categories