spring-boot Persistent h2database in filesystem - spring-boot

How can I configure spring-boot with h2database so as it reuses database each time I restart.
This is the only line I have in my application.properties file
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect

You have to specify for spring.datasource.url a value that specifies a filesystem DB. You can do it by using the jdbc:h2:file: prefix.
For example, you could use this configuration to store the DB in a mydb.mv.db file in the db folder of your home directory:
spring.datasource.url = jdbc:h2:file:~/db/mydb
Note that spring.jpa.database-platform=org.hibernate.dialect.H2Dialect is not required. The url and the H2 JDBC driver located in the classpath at runtime are enough.
Note also that by default, the database will be automatically created at startup if you use an embedded database (H2, HSQL or Derby).
It is the case even if you specify a file as database in the JDBC URL.
So to avoid recreating the db at each Spring Boot startup, you should also add :
spring.jpa.hibernate.ddl-auto = update
or
spring.jpa.hibernate.ddl-auto = validate

Related

How to generate .data file with Spring Boot and HSQLDB

I Use a Spring Boot 2 with file based HSQLDB. This are my properties
spring.datasource.driver-class-name=org.hsqldb.jdbc.JDBCDriver
spring.datasource.url=jdbc:hsqldb:file:${user.dir}/src/main/resources/userdb
spring.jpa.database-platform=org.hibernate.dialect.HSQLDialect
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.hibernate.ddl-auto=update
After application start I use that DB and add some Elements into it. Everything works, after that I expect under the path src/main/resources/ following files.
userdb.log (exists)
userdb.properties (exists)
userdb.script (exists)
userdb.data (where is this?)
But userdb.data is not there, after application restart all data are gone. Userdb.script contains all INSERT commands of data I added but there is no .data file. How to configure Spring Boot to create a userdb.data file and use this with content after restart.
In short, I want a persistent HSQLDB.
The database you've already got is persistent and is fine for small (a few megabytes) data.
The .data file is created when you execute CREATE CACHED TABLE statements or when you specify the default table type to be CACHED.
spring.datasource.url=jdbc:hsqldb:file:${user.dir}/src/main/resources/userdb;hsqldb.default_table_type=cached
See the Guide: http://hsqldb.org/doc/2.0/guide/dbproperties-chapt.html#dpc_db_operations

Load different schema.sql and data.sql for different datasources in spring boot

I have two datasources in my Spring Boot application. I want to initialize database at startup for local profile for both datasource with two different schema.sql and data.sql files. How to do it?
According to the section 85.3 Initialize a Database of the documentation:
Spring Boot can automatically create the schema (DDL scripts) of your DataSource and initialize it (DML scripts). It loads SQL from the standard root classpath locations: schema.sql and data.sql, respectively. In addition, Spring Boot processes the schema-${platform}.sql and data-${platform}.sql files (if present), where platform is the value of spring.datasource.platform. This allows you to switch to database-specific scripts if necessary. For example, you might choose to set it to the vendor name of the database (hsqldb, h2, oracle, mysql, postgresql, and so on).

Why H2 file database data get cleared every time

I use H2 database for a test application, using Spring boot. Every time, when I restart the spring boot app, the data in H2 gets cleared. I am using a file instead of memory. I set the spring.jpa.hibernate.ddl-auto=update in application.properties too.
Here is my application.properties file
spring.datasource.url=jdbc:h2:file:./data/demo
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.h2.console.enabled=true
spring.jpa.hibernate.ddl-auto=update
What am I doing wrong here. It saves data fine. But once I shut down the app, all data get cleared.
I found the mistake I was doing. I had data.sql file in resources and every time Spring boot starts the app, it runs this script. In that script I was dropping and recreating all the tables. Once I removed those sql statements, it works perfect. Data is persistent to the file and won't be erased after the server restart.
By default, closing the last connection to a database closes the database. For an in-memory database, this means the content is lost. To keep the database open, add ;DB_CLOSE_DELAY=-1 to the database URL. To keep the content of an in-memory database as long as the virtual machine is alive, use jdbc:h2:mem:test;DB_CLOSE_DELAY=-1.; DB_CLOSE_ON_EXIT=FALSE;
H2 Feature Document

Import database provisioning script with JPA

I'm suing Spring Boot with JPA. I tried to create src/main/resources/import.sql script for provisioning users into application properties:
spring.datasource.jndi-name=java:/global/production
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MariaDBDialect
spring.jpa.show-sql = true
spring.jpa.hibernate.ddl-auto = update
spring.datasource.data=classpath:import.sql
But unfortunately when I deploy the application the script is not run. Do you know with JPA what is the proper way to create SQL provisioning script?
If you need to initialized your database (if I understand you correctly), all you need to do in your Spring Boot project is just provide file data.sql with your DML scripts in your root classpath location (i.e. in resources dir):
Spring Boot can automatically create the schema (DDL scripts) of your DataSource and initialize it (DML scripts). It loads SQL from the standard root classpath locations: schema.sql and data.sql, respectively.
Source.
Another approach you can find here.
With the #Sql annotation you can specify the path of the file you want to run before the tests. For example:
#TestPropertySource("classpath:application-test.properties")
#Sql("/data.sql")
class MyClassTest
You can read more in here.

Setting up multiple database with Flyway

I am trying to setup two different database with Flyway 5.0.7, MySQL for development and H2 for testing. I have configured both databases in respective files.
For Development, src/main/resource/application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/moment
spring.datasource.username=root
spring.datasource.password=root
flyway.locations=db/migration,db/specific/mysql
For Testing, src/test/resource/application.properties
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=sa
flyway.locations=db/migration,db/specific/h2
Below is the folder structure for Flyway migration files
In this case Flyway is not able to find migration files under specific folder and throws error when applying V1.1__Insert_Records.sql for table not found.
If I move the specific folder inside db/migration, I am getting error for duplicate files of same version.
Any suggestions how should I configure migration files for multiple databases to work with Flyway?
I suspect you might be using Spring Boot 2.x here? If so, flyway.locations is no longer valid and will be ignored.
Flyway will then just use the default location (db/migration), which will find only the V1.1__Insert_Records.sql script but not the V1__Create_table.sql script.
With Spring Boot 2.x, flyway.locations must be prefixed with spring.:
spring.flyway.locations=db/migration,db/specific/h2
By the way, if you use the {vendor} placeholder in the location, Spring Boot will work out the directory from the lowercase of the database driver id (h2, mysql, oracle, etc), which is nice:
spring.flyway.locations=db/migration,db/specific/{vendor}

Resources