Generate schema in dropwizard-hibernate - maven

I followed the tutorial for dropwizard and hibernate without problems. Now I have non trivial annotations in my entities, and I would like hibernate to generate the tables for me, and stuff like that.So, how can I change hibernate's configuration? Can I give it a hibernate.cfg.xml? If I can, do I have to set up the connection again?
I found this PR,
but it doesn't seem to be in the public release yet (no hibernateBundle.configure in my jars)
But maybe I'm looking for the wrong thing. So far, I'm just trying to set hibernate.hbm2dll.auto. After all, there might be an other way to enable hibernate table generation in Dropwizard... So, any help?
Thank you.
Edit: I approached the problem from another angle, to explicitly create the schema instead of using hbm2ddl.auto. See proposed answer.

Edit: Problem solved! Doing this in the YAML config currently works: (Dropwizard 0.7.1)
database:
properties:
hibernate.dialect: org.hibernate.dialect.MySQLDialect
hibernate.hbm2ddl.auto: create
(from this answer)
Old answer:
This is what I am currently using: A class that calls hibernate's SchemaExport to export the schema to a SQL file or to modify the database. I just run it after changing my entities, and before running the application.
public class HibernateSchemaGenerator {
public static void main(String[] args) {
Configuration config = new Configuration();
Properties properties = new Properties();
properties.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
properties.put("hibernate.connection.url", "jdbc:mysql://localhost:3306/db");
properties.put("hibernate.connection.username", "user");
properties.put("hibernate.connection.password", "password");
properties.put("hibernate.connection.driver_class", "com.mysql.jdbc.Driver");
properties.put("hibernate.show_sql", "true");
config.setProperties(properties);
config.addAnnotatedClass(MyClass.class);
SchemaExport schemaExport = new SchemaExport(config);
schemaExport.setOutputFile("schema.sql");
schemaExport.create(true, true);
}
}
I didn't know about hibernate tools before. So this code example can be used in the service initialization to act like hbm2ddl.auto = create.
I'm currently using it just by running the class (from eclipse or maven) to generate and review the output SQL.

Related

I want to use jooq on a server where the DB environment is dynamic

I want to use jooq on a server where the DB environment is dynamic.
I want to use jooq in spring boot 2 gradle environment.
But there is a problem.
The build.gradle file requires hard-coded DB information but is available.
Can I create only JClass like QClass in QueryDSL?
I am in the server's external environment
Creates a dynamic DataSource such as ClassName, UserName, Password, and URL.
Hard-coded jooq can not be used.
In jooq
jooq{
version = '3.11.2'
sample(sourceSets.main) {
jdbc {
driver = 'org.postgresql.Driver'
url = 'jdbc:mysql//localhost:3306/sample'
user = 'some_user'
password = 'secret'
....
===========
The jdbc connection information should be hard-coded as shown.
But I want a dynamic jooq setting based on the external server settings.
Generally, a dynamic DataSource generation method is already in use.
Help!
I'm sorry I did not speak English.
You can build datasource in your configuration class instead of having hardcoded values in application.yml. Something like this:
#Bean
private DataSource buildDataSource() {
final BasicDataSource dataSource = new BasicDataSource();
dataSource.setUrl(env.getProperty("dataSource.url")+ "_somevalue");
dataSource.setUsername(env.getProperty("dataSource.username"));
dataSource.setPassword(env.getProperty("dataSource.password"));
return dataSource;
}
so you can define datasource url,username,password using some logic.

Neo4J ogm testing create temporary database

i'm using spring and at the moment running my tests create new objects in my "real" embedded database. I want to create a new one or a temporary db just for testing. I'm new with spring and neo4j so could anyone please help?
thanks a lot
If you are using the embedded driver with SDN/OGM you just need to configure it without providing a path. Then it will create embedded database in /tmp/.. which gets deleted on jvm exit.
E.g. if you are using java configuration
#Bean
public Configuration getConfiguration() {
Configuration config = new Configuration();
config
.driverConfiguration()
.setDriverClassName("org.neo4j.ogm.drivers.embedded.driver.EmbeddedDriver");
return config;
}
See docs for full documentation
http://docs.spring.io/spring-data/data-neo4j/docs/current/reference/html/#_configuring_the_embedded_driver

Completely auto DB upgradable Spring boot application

I am trying to use flyway for DB migrations and Spring boot's flyway support for auto-upgrading DB upon application start-up and subsequently this database will be used by my JPA layer
However this requires that schema be present in the DB so that primary datasource initialization is successful. What are the options available to run a SQL script that will create the required schema before flyway migrations happen.
Note that If I use flyway gradle plugin (and give the URL as jdbc:mysql://localhost/mysql. It does create the schema for me. Am wondering if I could make this happen from Java code on application startup.
Flyway does not support full installation when schema is empty, just migration-by-migration execution.
You could though add schema/user creation scripts in the first migration, though then your migration scripts need to be executed with sysdba/root/admin user and you need to set current schema at the beginning of each migration.
If using Flyway, the least problematic way is to install schema for the first time manually and do a baseline Flyway task (also manually). Then you are ready for next migrations to be done automatically.
Although Flyway is a great tool for database migrations it does not cover this particular use case well (installing schema for the first time).
"Am wondering if I could make this happen from Java code on application startup."
The simple answer is yes as Flyway supports programmatic configuration from with java applications. The starting point in the flyway documentation can be found here
https://flywaydb.org/documentation/api/
flyway works with a standard JDBC DataSource and so you can code the database creation process in Java and then have flyway handle the schema management. In many environment you are likely to require 2 steps anyway as the database/schema creation will need admin rights to the database, while the ongoing schema management will need an account with reduced access rights.
what you need is to implement the interface FlywayCallback
in order to kick start the migration manually from you code you can use the migrate() method on the flyway class
tracking the migration process can be done through the MigrationInfoService() method of the flyway class
Unfortunately if your app has a single datasource that expects the schema to exist, Flyway will not be able to use that datasource to create the scheme. You must create another datasource that is not bound to the schema and use the unbounded datasource by way of a FlywayMigrationStrategy.
In your properties file:
spring:
datasource:
url: jdbc:mysql://localhost:3306/myschema
bootstrapDatasource:
url: jdbc:mysql://localhost:3306
In your config file:
#Bean
#Primary
#ConfigurationProperties("spring.datasource")
public DataSourceProperties primaryDataSourceProperties() {
return new DataSourceProperties();
}
#Bean
#Primary
#ConfigurationProperties("spring.datasource")
public DataSource primaryDataSource() {
return primaryDataSourceProperties().initializeDataSourceBuilder().build();
}
#Bean
#ConfigurationProperties("spring.bootstrapDatasource")
public DataSource bootstrapDataSource() {
return DataSourceBuilder.create().build();
}
And in your FlywayMigrationStrategy file:
#Inject
#Qualifier("bootstrapDataSource")
public void setBootstrapDataSource(DataSource bootstrapDataSource) {
this.bootstrapDataSource = bootstrapDataSource;
}
#Override
public void migrate(Flyway flyway) {
flyway.setDataSource(bootstrapDataSource);
...
flyway.migrate()
}

Setting Flyway 'baselineOnMigrate' and 'baselineVersion' using spring boot property file

Spring Boot's FlywayProperties.java supports many of the Flyway settings but not 'baselineVersion' or 'baselineOnMigrate'. I am converting an existing application to Flyway and these setting appear to be designed for this purpose. Our production environment is highly controlled and running a commandline version of flyway there to achieve this is not practical.
Is creating a custom Flyway #Bean the only option here?
You can set any of flyways properties be prefixing them with flyway in your application.yml/.properties.
It is made possible by org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration.FlywayConfiguration#flyway which is annotated with #ConfigurationProperties(prefix = "flyway").
If you are using an application.yml add the following:
spring:
flyway:
baselineOnMigrate: true
If using an application.properties add the following:
spring.flyway.baselineOnMigrate = true
Update: added prefix spring (see #pdem comment).
It is impossible. I spent some time today analyzing code of Spring Boot to try to find a solution to this. There is nothing about setting any of these properties in FlywayAutoConfiguration. Also I found that Spring is never calling configure method on Flyway object what would be the only other option for flyway.properties to work. Spring is abusing flyway.properties a little bit and instead of providing this file further to Flyway they use it themselves as a source of properties. That is why the set of possible options when using FlywayAutoConfiguration is so limited. So using FlywayAutoConfiguration is not a good option if you need any more advanced features of Flyway. But using #Bean is not a tragedy here. Below you may see an example of using #Bean this way that implementing this behavior would be impossible with any property files:
#Profile(value = "!dbClean")
#Bean(name = "flyway", initMethod = "migrate")
public Flyway flywayNotADestroyer() {
Flyway flyway = new Flyway();
flyway.setDataSource(dataSource());
flyway.setBaselineOnMigrate(true);
return flyway;
}
#Profile(value = "dbClean")
#Bean(name = "flyway", initMethod = "migrate")
public Flyway flywayTheDestroyer() {
Flyway flyway = new Flyway();
flyway.setDataSource(dataSource());
flyway.setBaselineOnMigrate(true);
flyway.clean();
return flyway;
}
As you can see I have two Spring profiles here. One default that will not clean your database, and one with full clean of the database. Very handy.
I had success using a FlywayMigrationStrategy.
#Component
public class BaselineOnMigrateMigrationStrategy implements FlywayMigrationStrategy {
#Override
public void migrate(Flyway flyway) {
flyway.setBaselineOnMigrate(true);
flyway.migrate();
}
}
You can to use on application.properties file, but you need to add spring. prefix to it for springboot 2 like #pdem marked in this answer comments https://stackoverflow.com/a/39244097/273119.
spring.flyway.baseline-on-migrate=true
I am using flyway 5.1.4, for me adding these in application.properties worked
flyway.enabled = true
flyway.baseline-on-migrate = true
After digging into the source and running some experiments, it would appear that because the setBaselineVersion() is overloaded in the Flyway class, Spring is unable to inject the property value.
Changing to flyway.baselineVersionAsString=2 works as desired.
Answer of Seth is worked for me.
But I changed
flyway.setBaselineOnMigrate(true);
for
flyway.baseline();

Hibernate naming strategy

I am building a REST webservice with Spring (Boot) and am trying to use hibernate as orm mapper without any xml configuration.
I basically got it to work, but I am stuck with a configuration issue.
I instantiate LocalContainerEntityManagerFactoryBean as #Bean in a #Configuration file.
I set hibernate.ejb.naming_strategy as in the following example -> this seems to work for creating the tables if they do not exist (column names are camelCase like in my #Entity classes) but when a query is executed, hibernate "forgets" about this naming configuration and tries to use another kind of naming strategy with under_score_attributes --> obviously those queries fail. Is there any other property I need to set?
Or another way of configuring the properties preferably without adding a cfg.xml or persistence.xml?
LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean();
Properties props = new Properties();
props.put("hibernate.hbm2ddl.auto", "create");
props.put("hibernate.ejb.naming_strategy","org.hibernate.cfg.DefaultNamingStrategy");
lef.setJpaProperties(props);
lef.afterPropertiesSet();
HibernateJpaAutoConfiguration allows the naming strategy (and all other JPA properties) to be set via local external configuration. For example, in application.properties:
spring.jpa.hibernate.ddl_auto: create
spring.jpa.hibernate.naming_strategy: org.hibernate.cfg.EJB3NamingStrategy
Have you tried setting this particular property using programmatic properties? Or a hibernate.properties file in the package root? Or a JVM system property? All are described here.
From my experience, there are sometimes difficult to diagnose Hibernate problems if you insist on not using any XML (which would be my preference as well). If nothing else works, you may be forced to define a configuration file at least.
I got the solution now.
#EnableAutoConfiguration(exclude={HibernateJpaAuto Configuration.class})
The JpaAutoConfiguration must be excluded. Still I think this might be a bug, as normally it should automatically "stand back" when I use my own #Configuration.

Resources