Automatic generation of migration SQL for Flyway - java

Is it possible for new Flyway migrations to be generated by JPA/Hibernate's automatic schema generation when a new model / field etc. are added via Java code.
It would be useful to capture the auto-generated SQL and save it directly to a new Flyway migration, for review / editing / committing to a project repository.
Thank you in advance for any assistance or enlightenment you can offer.

If your IDE of choice is IntelliJ IDEA, I'd recommend using the JPA Buddy plugin to do this. It can generate Flyway migrations by comparing your Java model to the target DB.
You can use it to keep your evolving model and your SQL scripts in sync.
Also, it can create the init script if your DB is empty.
Once you have it installed and have Flyway as your Maven/Gradle dependency, you can generate a migration like this:

Flyway doesn't have built-in support for diff, I use liquidbase within a maven spring boot project and changelogs can be created from JPA/hibernate changes by using:
mvn liquibase:diff
All of the options for liquibase diff are located here:
http://www.liquibase.org/documentation/maven/maven_diff.html

If you want to generate the update SQL automatically, you can ask Hibernate to do so; just add the lines below to your Spring Boot configuration:
spring.jpa.properties.javax.persistence.schema-generation.create-source=metadata
spring.jpa.properties.javax.persistence.schema-generation.scripts.action=update
spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=update.sql
When you execute the application, this will generate a file named update.sql on the root of your project. Now, you can just copy and paste them into your Flyway migration.
This was adapted from this other answer: https://stackoverflow.com/a/36966419/679240 ; it is basically the same logic, except that one wants to generate a database creation script, while I needed an update script, instead.
BTW, if you want to replace the names of the foreign keys on the script with more readable ones, you could use this regex: ^(alter table .*?)(\w+)(\s+add constraint )\w+( foreign key \()(.*?)(\).*) with this replacement: $1$2$3fk_$2__$5$4$5$6; this will change the names of the FKs in the script to fk_name_of_the_table__name_of_the_field.

Related

How Insert In multiple database MongoDB with Java Springboot in Maven project

I am wondering if is it possible to insert in multiple databases in MongoDB. I have on my pom.xml project this connection structure:
<configuration.database.host>XXX.XXX.XXX.XXX</configuration.database.host>
<configuration.database.port>27017</configuration.database.port>
<configuration.database.username>useradmin</configuration.database.username>
<configuration.database.password>userpass</configuration.database.password>
<configuration.database>database1</configuration.database>
<configuration.database.collection.documentone>master</configuration.database.collection.documentone>
<configuration.database.collection.documentone.documenttwo>master_advice</configuration.database.collection.documentone.documenttwo>
Now, I need to add in the project another database to insert in antoher document some information, I don't know if I can add another connection and how can I do. for example, in the pom adding:
<configuration.database>database2</configuration.database>
<configuration.database.collection.documentone>cluster</configuration.database.collection.documentone>
of course, considering the configuration in the application.properties file.

Hibernate schema generation consider entities from other maven modules

i'm using the Persitence class from javax for generating SQL scripts from our entities. And it works just fine, for the project where i'am currently in. Here is the code:
final Map<Object, Object> properties = new HashMap<>(dialect.getDefaultProperties());
properties.put(AvailableSettings.DIALECT, dialect.getClass().getName());
properties.put(AvailableSettings.CONNECTION_PROVIDER, DriverManagerConnectionProviderImpl.class.getName());
properties.put(AvailableSettings.DEFAULT_SCHEMA, schemaName);
properties.put(AvailableSettings.HBM2DDL_SCRIPTS_ACTION, "create");
properties.put(AvailableSettings.HBM2DDL_CREATE_SOURCE, "metadata");
properties.put(AvailableSettings.HBM2DDL_SCRIPTS_CREATE_TARGET, target.toURI().toURL().toString());
properties.put(AvailableSettings.USE_QUERY_CACHE, "false");
properties.put(AvailableSettings.USE_SECOND_LEVEL_CACHE, "false");
properties.put(AvailableSettings.IMPLICIT_NAMING_STRATEGY, "org.hibernate.boot.model.naming.ImplicitNamingStrategyComponentPathImpl");
properties.put(AvailableSettings.PHYSICAL_NAMING_STRATEGY, SpringPhysicalNamingStrategy.class.getName());
properties.put(AvailableSettings.JPA_VALIDATION_MODE, "ddl, callback");
properties.put(AvailableSettings.HBM2DDL_DATABASE_ACTION, "none");
properties.put(AvailableSettings.DRIVER, "org.h2.Driver");
properties.put(AvailableSettings.URL, "jdbc:h2:mem:export");
properties.put(AvailableSettings.HBM2DDL_DELIMITER, ";");
System.setProperty("line.separator", ";\n");
Persistence.generateSchema(schemaName, properties);
Generally it's working fine for the entities in the current project, but not fir external entites. I have a external maven module, which contains some entities i also need to be considered for our SQL script. Is there a way to define the external module in the properties, so the will be considered too ?
Create a maven module for your entities
Execute mvn clean install in this module
Add this module in the dependencies of the project that wants to use this modules' entities.
This is all you have to do and I also applied this in many projects.
Since you did not provide what you have done in this manner, cant't help more.
So, please try these steps and if there was a problem update your question with how to did the steps.
P.S: Also if this is the first time creating multi-module project, please google about multi-module maven project. There are plenty of useful posts out there.

I can not add hibernate in intellij

I use IntelliJ to hibernate but it does add error.
I follow video https://www.youtube.com/watch?v=bGl4u44WRiI
this error:
[2016-05-16 07:44:21] javax.persistence.PersistenceException:
[PersistenceUnit: persistenceUnit] class or package not found
[2016-05-16 07:44:21] java.lang.ClassNotFoundException:
models.PmaExportTemplates
From what I noticed about intellij is if you import the hibernate from the project structure to include support. You don't get all the files required. I am not sure what you are trying to do if you are wanting to use JPA and hibernate as a provider, then I would download hibernate separately from hibernate.org and put the lib -> required folder contents and JPA folder content into its own folder along with what jdbc driver you would be using. Ex: SQL, MYSQL ect. If you are wanting to use the function in intellij you also have to provide a persistance.xml file and Java EE persistance support. I would suggest if you are just wanting to save something using hibernate that you download the files as said and then create the hibernate library when you make the project. If you want to avoid using EntityManagerFactory and use native hibernate API then you would be using hibernate.cfg.xml and a (class).hbm.xml mapping file or JPA annotations in the source code. I would suggest using SessionFactory and configure that full support of hibernate. Can you clarify what you want to do?

How do I use templating with Hibernate and Gradle?

I have a server that talks to a database that I need to test. I connect to the database using Hibernate and manage the dependencies using Gradle. I want to use separate tables in MySql for production and testing. So I have currently this line in hibernate.cfg.xml:
<property name="hibernate.connection.url">jdbc:mysql://127.0.0.1:3306/production_database</property>
But what I really want is for it to be something like:
<property name="hibernate.connection.url">jdbc:mysql://127.0.0.1:3306/${DATABASE_NAME}</property>
and then when I run gradle test, DATABASE_NAME can be set to "test_database_name", and when I run gradle jettyRun it'll still be "production_database". This seems like something that should be possible, but when I google for "hibernate teplating" I get references this other thing called HibernateTemplate that has nothing to do with what I want as far as I can tell. What's the syntax that'll make this happen for me?
You should move that property out of hibernate.cfg.xml, and into a database.properties file.
And, Then you can use gradle to modify this file depending upon the argument.
Please refer to Gradle Tasks for this.
ant.propertyfile(
file: "database.properties") {
entry( key: "connectionurl", value: "somevalue")
}

Does Hibernate 4 with ehcache require ehcache-core library?

I am attempting to upgrade an appliaction from Hibernate 3 to Hibernate 4. The application uses ehcache.
When upgrading to Hibernate 4.2.0.Final I added a dependency on hibernate-ehcache-4.2.0.Final as suggested.
When I started up the application I received the following error:
Caused by: java.lang.NoClassDefFoundError: org/hibernate/cache/TimestampsRegion
According to http://www.javacraft.org/2012/03/migrate-to-hibernate-4-ehcache.html I should remove the dependency on ehcache-core and only use the hibernate provided jar to resolve this error.
Now, if I follow these instructions and remove this dependency my application which uses the net.sf.ehcache.CacheManager no-longer compiles.
// For example, this no-longer works
CacheManager manager = CacheManager.getInstance();
So my question is, can I use both libraries and continue working as before (Without updating the app), or do I have to change the app, in which case does hibernate-ehcache even provide the functionality required to access the cache?
When using Hibernate 4 you have to use the org.hibernate packaged classes.
The net.sf.ehcache ones are target at Hibernate 3.
Form 4 they have ported to 4 within the Hibernate repo directly (which is the most sensible thing in our opinion).
So using org.hibernate.cache.ehcache.EhCacheRegionFactory should solve your problem.
Check if there any .properties file in your project like hsqlDatabaseConfig.properties, try to update the property as below
sessionFactory.hibernateProperties = hibernate.cache.use_second_level_cache=true\n\
hibernate.cache.use_query_cache=true\n\
hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.internal.EhcacheRegionFactory\n\

Categories