Using Liquibase and Spring Boot - spring

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/

Related

How to make a Spring Boot project dependency use H2 database

I have a Spring Boot project (MAIN) which in turn depends on a (DAL) dependency.
DAL is where every Entity, Repository, Projection and Spring Data JPA related configurations are.
Now, MAIN project is a scheduler, and I need to make some integration tests over it. As always I want to use H2 database for the job in hands.
I have the H2 configuration under /test/resources/application.properties and this configuration have always worked if the JPA related classes were in the same project.
But in this specific case what is happening is that the H2 configuration are being ignored and the Integration Tests are writing into the real database.
Is possible to make the DAL to use H2 configurations?
For future reference, seting up H2 configuration for nested projects is very much possible.
The reason I was unable te setup this configuration rigth on the first attempt was because on DAL I have configured multiple data sources, as such the default h2 configuration wouldnt be enought.
So I had to make something like the folloing:
first-datasource.driver-class-name=org.h2.Driver
first-datasource.jdbcUrl=jdbc:h2:mem:testdb
first-datasource.username=sa
first-datasource.password=password
second-datasource.driver-class-name=org.h2.Driver
second-datasource.jdbcUrl=jdbc:h2:mem:testdb
second-datasource.username=sa
second-datasource.password=password

How should I control order of execution between Liquibase and springboot data.sql?

We have a (internal to company, external to project) library (jar) that includes some Liquibase scripts to add tables to a schema to support the functionality of that library.
Using SpringBoot and Maven to run integration tests with H2, we have been using sql files, listed in property files, to initialise the DB.
We want to be able to add data to the tables created by the external (to the project) library for the ITs but finding the tables haven't been created by Liquibase when SpringBoot/SpringData attempts to run the insert statements in our sql files.
Given the errors we're seeing (tables not existing when spring attempts to run the insert.sql files) it looks like spring is executing those files before Liquibase has done its thing.
How can I ensure Liquibase config run by the library to create tables has completed before Spring does it's thing with running sql files specified by the spring.datasource.data property?
We don't really want to include the test data in the library (which was working, but introduced other issued we are trying to work around with liquibase inserting test data into production DB).
what about using different context for your tests?
so you will have application.properties in your test folder and there you will define another changelog that will include all changelogs that are needed (even from library) and you will also include the .sql file that you are running probably with jpa? Try to look here if that helps.

I need to generate Liquibase Change-set for my JPA entities. How can I do that?

I have tried the following
liquibase:generateChangeLog - It generated the change log from my db.I need to generate the change-log from my JPA entities.
liquibase:diff - It generates the change log for the difference between my db and JPA entities. I cannot say that my db is always empty and I want to generate the create scripts which can be applied on fresh db.
How can I use Liquibase to generate the scripts based on my JPA entities only ?
Note : I am ok in providing the details about my db such as url,driver etc
If your IDE of choice is IntelliJ IDEA, I'd recommend using the JPA Buddy plugin to do this. It can generate Liquibase changelogs by comparing your Java model to the target DB.
So if your DB is empty, you'll get a changelog that describes your whole model. But it is also useful to keep your evolving model and your changelogs in sync.
Once you have it installed and have Liquibase as your Maven/Gradle dependency, you can generate a changelog like this:
Try to use liquibase-hibernate-plugin
You have to create a schema with persistence properties according to Database Schema Creation and then use the Liquibase generateChangeLog command.

How to disable Javers for integration tests?

I am using Javers 3.11.2 with Spring Boot 1.5.17. When I am trying to run integration tests on an embedded database I still see that Javers tables are getting created each time.
Is there a way I can disable Javers during these tests so that these tables will not be created each time?
There is the easy way, put:
javers:
sqlSchemaManagementEnabled: false
in your application-test.yml. See https://javers.org/documentation/spring-boot-integration/
Disclaimer: I've never used Javers.
In general, disabling something in "integration tests" means that you don't want to load some beans (of Javers in this case).
This means in turn that you have to exclude them from the list of configurations spring boot works with.
If you're using javers autoconfiguration module, it has to provide in its own "spring.factories" file (can be found inside the jar) a file for autoconfiguration.
Find its java code and see whether it has some "#Conditional on something (property beans, etc.)" If it has than create a profile for integration test that will configure the beans in a way that conditional in javers won't pass and the bean won't be created as a consequence
If it doesn't have a conditional on something like this, you'll have to exclude the whole configuration. Its usually can be done by annotation #SpringBootApplication(exclude=<JaversAutoconfiguration goes here>
This will, however, turn it off also for production usage, which is obviously not something that you want. So for "production" profile, you'll have to import it as a regular configuration (not an autoconfiguration), for integration test profile you won't need this.

How to let JPA find generated entities (with spring-data)?

I am writing a Maven plugin that is supposed to generated JPA entities from a DSL. The entities are generated directly as ByteCode, i.e. without an intermediate java source (using ByteBuddy). The generation works fine. But the problem is that my entity isn't found by the hibernate orm. The error occurs in: org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.classForName(ClassLoaderServiceImpl.java:242), and the exception is a ClassNotFoundException. Does the hibernate instrumentation require the java code of the entity? Or how can I let hibernate know about my entity?
Further background: I use spring-data-jpa, and configured the EntityScan with the correct basePackage. My maven plugin is run in the compile phase (immediately after the compilation of the source code).
Works as designed. The only problem is to take care that the package of the class and the folder hierarchy match, and that these packages are added as basePackages for the EntityScan.

Resources