Using both GORM & direct JPA/Hibernate datasource in Grails application - spring

We are trying to upgrade our existing Grails application to 5.2.4
We have defined datasource properties in application.yml which gets used during GORM initialization. Rest of the application we use pure JPA/Hibernate (i.e. don't use GORM)
by using datasource defined in a spring style bean.
At high level, issue that we are facing is either GORM or JPA datasource is getting initialized correctly. But both data sources are not getting initialized at the same time.
If I add dependency following dependencies in gradle script,
org.grails.plugins:hibernate5
org.hibernate:hibernate-core:xxx.Final
Then GORM gets initialized correctly. But then we get following issue when doing JPA style queries
Caused by IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: is not mapped [select xxx]
If I remove those dependency, GORM queries fails with following error.
Either class is not a domain class or GORM has not been initialized correctly or has already been shutdown. Ensure GORM is loaded and configured correctly before calling any methods on a GORM entity.
It seems may be some configuration is missing, but nor sure where is the exact issue.
Appreciate any help/suggestions.

Related

Configuring Spring Boot to use both H2 AND Oracle at the same time

I am writing a Spring Batch job and don't care about restarts and don't want the hassle of creating, securing and managing an Oracle schema for Spring Batch database objects. H2 on the file system is more than enough for us.
The issue is that I am writing an batch job that needs to connect to an Oracle database and failing miserably just trying to get 2 data sources, transaction managers and entity managers. Right now I am trying two H2 database and haven't even tried configuring Oracle database yet.
I have used two Oracle data sources in other Spring Boot applications successfully in the past but this is my first attempt with Spring Batch that has configuration code to create the data source.
I have tried creating two DataSource, EntityManagerFactoryBean and TransactionManager with one using default spring.datasources configuration, default bean names and #Primary.
I have tried creating just a second DataSource, EntityManagerFactoryBean and TransactionManager with different bean names. This seems to have an issue that the TransactionManager orEntityManager is already assigned to the thread.
I have tried creating a dataSource for batch but run into circular bean creation errors.
I have tried creating a BatchConfigurer and that runs into circular bean creation errors.
I have tried creating a JobRepositoryFactoryBean but a default one is still created.
I have tried using a #PersistenceContext on my #Entity classes.
It shouldn't be this hard so I must be missing something. Any help would be appreciated.
Thanks, Wes.
I think I have some success. I am able to eventually run the batch job using Spring Boot 2.2.0 and Spring Batch 4.2.0 but I have to wait for a 5 minute timeout while creating the Entity Manager for H2 for the Spring Batch repository. The Oracle Entity Manager is registered really quickly and before the H2 Entity Manager despite the H2 Entity Manager being #Primary.
I have a separate configuration class for each of my two DataSources. Each one is annotated with #Configuration, #EnableTransactionManagement and #EnableJPARepository.
The one for Spring Batch is using the standard bean names, dataSource, entityManagerFactory and transactionManager. Each #Bean is annotated with #Primary.
One setting that I needed was to add a .packages("org") to the entityManagerFactory bean. This would pick up all of org.springframework including Spring Batch.
The only other real change I have made from common implementations is to set the dialect in the JPA Properties of the Entity Manager.
I needed the spring.main.allow-bean-definition-overriding: true setting.
There may be more to my solution that I should share but I have been at this for a couple of days and have gone in circles. I even remember getting what appeared as a hung process time and and killed the job thinking it was hung. I may have had some "success" early on but just was too quick to kill the execution.
I would still like to know why it is taking so long to create the H2 Entity Manager.
Thanks, Wes.

Using Liquibase and Spring Boot

I have a Spring Boot application and want to use Liquibase to generate the changelogs for my JPA entities. However, I encounter different issues, depending on my approach.
My first approach is to use the diff goal of the maven plugin. The url is my H2 development database with the H2 driver and the reference URL is something like "hibernate:spring:myBasePackage.myEntityPackage?dialect=org.hibernate.dialect.H2Dialect" with the driver "liquibase.ext.hibernate.database.connection.HibernateDriver". In that case Liquibase seems to recognize my entities, but prints the differences to the console. Also the differences do not have the form of a changelog file.
My second approach would be to use the generateChangeLog goal of the maven plugin. In this case my url is "hibernate:spring:myBasePackage.myEntityPackage?dialect=org.hibernate.dialect.H2Dialect" with the driver "liquibase.ext.hibernate.database.connection.HibernateDriver. In this case I am getting an error "Unable to resolve persistence unit root URL: class path resource [] cannot be resolved to URL because it does not exist". This error can be found in both the Spring an the Liquibase issue trackers, but it seems like it is always said that this error is already fixed.
My third approach is basically like the second, but in this case I am using a "hibernate:classic" url with an implementation of "CustomClassicConfigurationFactory", which registers my annotated classes explicitly. This does work. However, in this case I have to do this in my application-jar. I have to add my application-jar as a dependency for the maven-plugin. Thus I have to build my application-jar (and install it to the local Maven repository), before I can generate the changelogs. This seems to be cumbersome.
My questions are:
Is there an easier way to generate the changelogs for JPA entities in a Spring boot based application?
Why are the first two approaches not working?
Is there a way to simplify the third approach?
I am using:
Spring Boot 1.5.4.RELEASE
Liquibase-Hibernate4 3.6
Liquibase 3.5.3
Many thanks in advance.
In the first approach using liquibase:diff , the change set for the entities (create table change set) will not be generated since liquibase do not assume new jpa entity as change.
In the second approach generateChangeLog, it generates the change log from the given data base.It won't look into your jpa entities.
In order to generate the ddl scripts for your jpa entities , just submit the following to your jpa properties
<property key="javax.persistence.schema-generation.scripts.action">drop-and-create</property>
<property key="javax.persistence.schema-generation.scripts.create-target">./ddl/create.sql</property>
<property key="javax.persistence.schema-generation.scripts.drop-target">./ddl/drop.sql</property>
The above will generate the scripts the ddl folder under the root folder.
You can check the other properties here https://thoughts-on-java.org/standardized-schema-generation-data-loading-jpa-2-1/

Spring Boot - Let Hibernate initialize all datasources of AbstractRoutingDataSource

I've implemented the AbstractRoutingDataSource in order to horizontally partition my data [1]. I rely on Hibernates functionality to create and update the database schema. This works fine for the first datasource, which is resolved by the determineCurrentLookupKey() declared in AbstractRoutingDataSource.
Is there a way to apply the schema generation/update to the other datasources as well?
I've found the classes SchemaExport and SchemaUpdate respectively, that are capable of the required functionality. However, both require an instance of org.hibernate.boot.MetaData, which I don't how to obtain.
(I'm using Spring Boot in version 1.4.2.RELEASE.)
[1] https://spring.io/blog/2007/01/23/dynamic-datasource-routing/
Thanks!
I got the same issue and found a solution using the SchemaExport class of hibernate.
For each DataSourceEnum you can manually initialize the datasource.
here is my detailed answer to my own issue discription

Using multiple embedded datastores with Spring Boot

I'm trying to set up a Spring Boot application using Spring Data JPA, Neo4J and MongoDB. The goal is to be able to save different entities in each datastore, as well as using cross-store entities.
The project seems to work well with each store individually, but saving a JPA entity raises this exception :
org.springframework.dao.InvalidDataAccessApiUsageException: No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call; nested exception is javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call
This exception is not raised if I remove all neo4J and mongoDB related code.
Here is a link to the project on github :
GitHub
I managed to get it working by using the configuration of this project.
It looks like I had to add an "transactionManagerRef" attribute to the #EnableJpaRepositories annotation, a bit more configuration for Transition Managers, and modify some dependencies.

Spring Boot app testing with database vendor specific JPA annotation

I got an app with an existing database that has Oracle only field type (e.g. "binary-float") mapped on the entity class with #ColumnDefinition annotation.
Things runs fine when running the app normally by launching the Application class.
However I can't seem to find a way to write junit tests easily. In another Spring Boot app, I have been using different profile to define a normal datasource that points to Oracle and a junit test datasource that points to the h2 in-memory db. I stayed mostly within JPAQL and common sql standard when using direct sql. Problem is, this scheme doesn't work if the JPA mapping annotation is database specific.
Any suggestions?

Resources