H2 DB and Flyway DB Migration using Spring - spring-boot

As am learning i am creating a simple application which uses H2 database to store a table using spring boot. I am using flyway to migrate/create a new table from JAVA program. I have specified the below properties in the 'application.properties' file:
logging.level.org.springframework.web=DEBUG
server.port=8080
spring.h2.console.enabled=true
spring.h2.console.path=/h2
spring.datasource.url=jdbc:h2:file:~/dasboot
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driver-class-name=org.h2.driver
spring.datasource.max-active=10
spring.datasource.max-idle=8
spring.datasource.max-wait=10000
spring.datasource.min-evictable-idle-time-millis=1000
spring.datasource.min-idle=8
spring.datasource.time-between-eviction-run-millis=1
flyway.baseline-on-migrate=true
spring.jpa.hibernate.ddl-auto=validate
spring.jpa.shows-sql=true
Below is the query for H2 am using (V2__create_shipwreck.sql). This query is under src/main/resources/db/migration directory and am using maven packaging:
CREATE TABLE SHIPWRECK(
ID INT AUTO_INCREMENT,
NAME VARCHAR(255),
DESCRIPTION VARCHAR(2000),
CONDITION VARCHAR(255),
DEPTH INT,
LATITUDE DOUBLE,
LONGITUDE DOUBLE,
YEAR_DISCOVERED INT
);
in the final output console i expect to have a 'SCHEMA_VERSION' and my 'SHIPWRECk' table. But am getting nothing:
it would be great if someone can help me to resolve the same.

Related

H2: Column "SYSDATE" not found after upgrade

I upgraded the version of h2 from 1.4.200 to 2.1.214 and tests fails now because of the use of "SYSDATE" in a liquibase file (we use an Oracle database when the app is deployed).
Content of liquibase file:
<createTable tableName="myTable">
<column defaultValueComputed="SYSDATE" name="CREATION_DATE" type="TIMESTAMP(6)">
<constraints nullable="true" />
</column>
</createTable>
When the liquibase file is loaded to initialize the database for tests, then it fails with this error:
Column "SYSDATE" not found
The executed query is like this:
CREATE TABLE PUBLIC.my_table (..., CREATION_DATE TIMESTAMP(6) DEFAULT SYSDATE,...)
I tried to force the Oracle compatibility mode of H2 like this:
spring:
datasource:
url: jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;MODE=Oracle
I saw that h2, in Oracle compatibility mode, should accept "SYSDATE" keyword but I still have the error.
Do you know what I have to do to solve the issue please?
I found a solution for this error.
For local tests, a configuration of the DataSource was done like this:
#Bean
#Profile(SpringProfiles.H2)
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()//
.setType(EmbeddedDatabaseType.H2) //
.setName("local") //
.build();
}
I had to change it by adding the mode in the name:
#Bean
#Profile(SpringProfiles.H2)
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()//
.setType(EmbeddedDatabaseType.H2) //
.setName("local;MODE=Oracle") //
.build();
}
I found the solution in this link: Does Spring embedded database support different SQL dialects?

Hibernate TypeBootstrapContext not found

I am trying to map java enum to PostgreSQL enum in Spring app. I am doing completely same things as Vlad did in his tutorial (Section Mapping a Java Enum to a database-specific Enumerated column type).
So I've imported hibernate-types-55 artefact, added
#TypeDef(
name = "pgsql_enum",
typeClass = PostgreSQLEnumType.class
)
Above entity class, added
#Enumerated(EnumType.STRING)
#Column(name = "column_name",
columnDefinition = "some_enum",
nullable = false)
#Type( type = "pgsql_enum" )
private SomeEnum someProperty;
and finally added a column with newly created database enum where values corresponds with values in enum
But I am getting
java.lang.ClassNotFoundException: org.hibernate.type.spi.TypeBootstrapContext from
while trying to start the application using Wildfly.
Whole maven build completes successfully, all tests passed, so everything looks okay but this exception which causes app wont start at the server.
The Hibernate core version I am using is 5.2.10.Final
I´ve imported hibernate-types-55 artefact
As it's stated in the documentation, you should use:
<dependency>
<groupId>com.vladmihalcea</groupId>
<artifactId>hibernate-types-52</artifactId>
<version>2.12.0</version>
</dependency>
for the Hibernate 5.2 branch.

Spring Boot Data JPA with H2 and data.sql - Table not Found

I have a Spring Boot 2.5.0 project. I'm using spring-data-jap with the h2 in-memory database. I want to populate data on startup with a data.sql file but I'm getting a table not found exception. If I remove the data.sql file, I can see that a table for my entity does get created automatically. But if I include the data.sql file, I get the error saying the table doesn't exist. Maybe it is an error with my sql syntax of I have misconfigured the h2 database?
applicaltion.yml
spring:
datasource:
url: jdbc:h2:mem:test
driverClassName: org.h2.Driver
username: sa
password: sa
jpa:
database-platform: org.hibernate.dialect.H2Dialect
debug: true
data.sql
INSERT INTO BUSINESS_SUMMARY VALUES (1, "ALM470", "B48", 3);
BusinessSummary.java entity
#NoArgsConstructor(access = AccessLevel.PROTECTED)
#Getter
#Entity
public class BusinessSummary {
#Id
private Long id;
private String businessId;
private String businessDomainId;
private Integer cityCode;
}
BusinessSummaryRepository.java
#Repository
public interface BusinessSummaryRepository extends JpaRepository<BusinessSummary, Long> {
}
Exception:
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "BUSINESS_SUMMARY" not found; SQL statement:
INSERT INTO BUSINESS_SUMMARY VALUES(1, "ALM470", "B48", 3) [42102-200]
spring.jpa.defer-datasource-initialization=true
By default, data.sql scripts are now run before Hibernate is
initialized. This aligns the behavior of basic script-based
initialization with that of Flyway and Liquibase.
If you want to use
data.sql to populate a schema created by Hibernate, set
spring.jpa.defer-datasource-initialization to true. While mixing
database initialization technologies is not recommended, this will
also allow you to use a schema.sql script to build upon a
Hibernate-created schema before it’s populated via data.sql.
you'll have to convert spring.jpa.defer-datasource-initialization to yml.
If you're using hibernate as a JPA implementation, the best way I think is by using the file import.sql instead of data.sql for Database Initialization.
for more information on database initialization see the official Spring Boot documentation Database Initialization
in addition to defer-datasource-initialization: true, you may also need
spring:
sql:
init:
mode: always
spring.jpa.defer-datasource-initialization = true
spring.sql.init.mode = always
if still doesn`t work try renaming the file from data.sql to import.sql

Hibernate JPA Spring Boot

I have created all the models for my spring boot application and successfully specified the relation between them as per business logic. In my properties file, I set the hibernate auto-ddl option as create to generate all the tables as per the relationship between the entities. I am also using liquibase for database migration.
The problem is that, from the logs I can see that hibernate is altering the table before creating it and therefore throwing the run time exception saying "Table not found". Why it is altering the table before creating it? How to solve this issue?
Any help would be highly appreciable. Thanks in advance.
Some logs example
Error executing DDL "alter table application drop foreign key FKrtuepaxepo3o6x0pkn0w62ucg" via JDBC Statement.
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "APPLICATION" not found; SQL statement:
alter table application drop foreign key FKrtuepaxepo3o6x0pkn0w62ucg
.......
.......
.......
Hibernate: drop table if exists application
create table application (id bigint not null auto_increment
alter table application add constraint UK_5jl5nuoh207t0japuutb4avd4 unique (application_name)
Why it is expecting table name as "APPLICATION" before creating "application"
#Table(name = "application")
#EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class Application extends AbstractAuditingEntity implements Serializable {
private static final long serialVersionUID = 1L;
}
I am using H2 database in the development and MYSQL in production. But, previously, I was using the "org.hibernate.dialect.MySQL5InnoDBDialect" dialect in "application-dev.yml". Changing it to h2 dialect(org.hibernate.dialect.H2Dialect) solved the problem.
But,what should be the proper dialect in application-prod.yml? I am using MYSQL in production. Current dialect I am using here is "org.hibernate.dialect.MySQL5InnoDBDialect". This will further create problem in production.
application-prod.yml
datasource:
# type: com.zaxxer.hikari.HikariDataSource
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/appscoredb
username:
password:
hikari:
poolName: Hikari
auto-commit: false
# h2:
# console:
# enabled: true
# settings:
# web-allow-others: true
jpa:
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
database: mysql
hibernate:
ddl-auto: none
show-sql: true
properties:
hibernate.id.new_generator_mappings: true
hibernate.connection.provider_disables_autocommit: true
hibernate.cache.use_second_level_cache: false
hibernate.cache.use_query_cache: false
hibernate.generate_statistics: false
liquibase:
# Remove 'faker' if you do not want the sample data to be loaded automatically
contexts: prod, faker
enabled: false
It is solved by using this dialect: org.hibernate.dialect.MySQL5Dialect
I hope it could help someone in near future.

Spring Boot Data Initialization

I am trying to insert some test data after my Spring Boot application has started. I have the below configuration in place. I do notice that the sql script is executed before the JPA entities are created resulting in a failure of the insert statement. Is there any other configuration I am missing here? As noted in my configuration I am using Spring Boot with H2 and EclipseLink for JPA.
Reference
https://docs.spring.io/spring-boot/docs/current/reference/html/howto-database-initialization.html
Configuration
# H2
spring.h2.console.enabled=true
# Datasource
spring.datasource.url=jdbc:h2:mem:testdb;MODE=ORACLE
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driver-class-name=org.h2.Driver
# JPA
spring.jpa.generate-ddl=true
spring.jpa.show-sql=true
spring.jpa.properties.eclipselink.weaving=false
data.sql is placed under /src/main/resources
Logs
2017-09-05 20:37:37,989 [restartedMain ] INFO
o.s.j.d.e.EmbeddedDatabaseFactory - Starting embedded database:
url='jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false',
username='sa'
2017-09-05 20:37:38,141 [restartedMain ] INFO
j.LocalContainerEntityManagerFactoryBean - Building JPA container
EntityManagerFactory for persistence unit 'default'
2017-09-05 20:37:38,446 [restartedMain ] INFO
o.s.o.j.AbstractEntityManagerFactoryBean - Initialized JPA
EntityManagerFactory for persistence unit 'default'
2017-09-05 20:37:38,510 [restartedMain ] INFO o.s.j.d.i.ScriptUtils
- Executing SQL script from URL [file:/develop/src/data-init/target/classes/data.sql]
error...
Entity
#Entity
#Table(name = "TEMPLATE_CONFIG")
#Data
public class TemplateUser {
#Id
#Column(name = "TEMPLATE_CONFIG_ID", nullable = false)
private Long configId;
#Column(name = "APP_CODE", nullable = false, length = 100)
private String appCode;
...
}
Update
Uploaded a sample project:
https://git.io/v5SWx
Spring-Boot loads data.sql or data-${somthing}.sql
You can do:
spring.datasource.platform=h2.
spring.datasource.data=myscript-test.sql. ( locations can be changed with this property)
I have a project on that way and is working with h2.
And just how last alternative, if you are not able to load the information maybe you can use the CommandLineRunner in your application file with jdbc template.
This is an existing bug in Spring as confirmed here by the Spring Team.
https://github.com/spring-projects/spring-boot/issues/10365

Resources