H2: always try to create tabes with file database - spring-boot

I have configured the application-local.yml like this to do some tests in local:
spring:
datasource:
url: jdbc:h2:file:./data/db-test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
username: dbtest
password: dbtest
driver-class-name: org.h2.Driver
jpa:
show-sql: true
generate-ddl: false
properties:
# to prevent this issue : https://stackoverflow.com/questions/4588755/disabling-contextual-lob-creation-as-createclob-method-threw-error
hibernate.temp.use_jdbc_metadata_defaults : false
hibernate:
dialect: org.hibernate.dialect.H2Dialect
hibernate:
ddl-auto: update
h2:
console:
enabled: true
path: /public/h2-console
liquibase:
enabled: false
The first time the server is started, I see some logs from Hibernate to create tables and the file for the database is created.
The issue is that when I restart the server, I have some errors because it tries to create again the same tables, constraints... I have the ddl-auto set to update so I do not understand why. I tried to update the generate-ddl value to false but it is the same.
Here is an exemple of what I have:
Hibernate: create table myTable (id bigint not null, ..., primary key (id))
15:59:49.252 [restartedMain] WARN o.h.t.s.i.ExceptionHandlerLoggedImpl - GenerationTarget encountered exception accepting command : Error executing DDL "create table myTable (id bigint not null, ..., primary key (id))" via JDBC Statement
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "create table myTable(id bigint not null, ..., primary key (id))" via JDBC Statement
at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:67)
at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.applySqlString(AbstractSchemaMigrator.java:562)
at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.applySqlStrings(AbstractSchemaMigrator.java:507)
at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.createTable(AbstractSchemaMigrator.java:277)
at org.hibernate.tool.schema.internal.GroupedSchemaMigratorImpl.performTablesMigration(GroupedSchemaMigratorImpl.java:71)
at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.performMigration(AbstractSchemaMigrator.java:207)
at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.doMigration(AbstractSchemaMigrator.java:114)
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:184)
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:73)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:318)
What am I doing wrong please?

The spring.jpa.generate-ddl: true is forcing spring data JPA to recreate the tables. Just set this to false or delete the key as the default is false. This should fix the Problem. Docs

Related

A double sequence is generated in the Spring Boot app

I'm developing a Spring Boot application and I'm having a problem with sequence generation.
For migrations I use liquibase.
I create a sequence in liquibase.
CREATE SEQUENCE public.additional_services_id_seq
INCREMENT BY 1
MINVALUE 1
MAXVALUE 2147483647
START 1
CACHE 1
NO CYCLE;
Entity code
#Getter
#MappedSuperclass
public abstract class BaseEntity {
#Id
private Integer id;
}
After running the application and migration, there are
two sequences for the model.
First
-- auto-generated definition
create sequence additional_services_id_seq
maxvalue 2147483647;
alter sequence additional_services_id_seq owner to postgres;
Second
-- auto-generated definition
create sequence additional_services_id_seq1
as integer;
alter sequence additional_services_id_seq1 owner to postgres;
alter sequence additional_services_id_seq1 owned by additional_services.id;
application.yaml settings -
jpa:
show-sql: true
generate-ddl: false
hibernate:
ddl-auto: validate
properties:
hibernate:
format_sql: true
dialect: org.hibernate.dialect.PostgreSQL94Dialect
order_inserts: true
jdbc:
batch_size: 50
open-in-view: false
How do I set up my application so that only the sequences that I created in the migration appear?

Spring boot hibernate always drop and create index on server startup

Spring boot hibernate always drop and create ALL the indexs on server startup
spring.jpa.hibernate.ddl-auto = update
Hibernate: alter table product_category_1 drop index UKkqfeccp86g07ipixmg25dnfia
Hibernate: alter table product_category_1 add constraint
UKkqfeccp86g07ipixmg25dnfia unique (org_id, pr_ty_id, name)
Hibernate: alter table product_category_2 drop index UKqa7n4ip0gfa4qpg034ba7bkob
Hibernate: alter table product_category_2 add constraint UKqa7n4ip0gfa4qpg034ba7bkob unique (org_id, pr_ca1_id, name)
If your column type is a longtext, the index is not created so hibernate tries to recreate it.
I was experiencing the same thing, where starting my application resulted in my unique constraints being dropped and re-added:
Hibernate: alter table category drop constraint if exists UK_CATEGORY_PARENT_NAME
Hibernate: alter table category add constraint UK_CATEGORY_PARENT_NAME unique (parent_id, name)
After much internet digging and debugging, I found simply adding the following to my application properties no longer caused the constraints to be dropped:
spring.jpa.properties.hibernate.schema_update.unique_constraint_strategy=RECREATE_QUIETLY
As i observe that few of the unique key drop and create again and again with the property
spring.jpa.hibernate.ddl-auto = update
You have to change the uniqueConstraints write inside the #Table annotation and put the uniqness check at column level
Execute the drop and create unique index again and again every time you restart the project
#Table(name = "XXXX",
uniqueConstraints = {#UniqueConstraint(columnNames = { "tempUserId"}) },
)
Resolve by adding the unique=true and column level
#Column(unique = true)
private Long tempUserId;
And delete uniqueConstraints from the #Table annotation
This will resolve the problem

Tests fail to run with H2 database on Micronaut project with Flyway migrations

I've got a unit test suite in a Micronaut 2.0.3 project that's supposed to run on an H2 DB. Since I started using Flyway for my DB migrations, I'm getting an error coming from H2 being unable to run the migrations.
The error is
Bean definition [javax.sql.DataSource] could not be loaded: Migration V1__schema.sql failed
-------------------------------
SQL State : 42001
Error Code : 42001
Message : Syntax error in SQL statement "CREATE DATABASE[*] IF NOT EXISTS MY_DB"; expected "OR, FORCE, VIEW, ALIAS, SEQUENCE, USER, TRIGGER, ROLE, SCHEMA, CONSTANT, DOMAIN, TYPE, DATATYPE, AGGREGATE, LINKED, MEMORY, CACHED, LOCAL, GLOBAL, TEMP, TEMPORARY, TABLE, SYNONYM, PRIMARY, UNIQUE, HASH, SPATIAL, INDEX"; SQL statement:
CREATE DATABASE if not exists my_db [42001-200]
Location : db/migration/V1__schema.sql (/somelocation/build/resources/main/db/migration/V1__schema.sql)
Line : 1
Statement : CREATE DATABASE if not exists my_db
io.micronaut.context.exceptions.BeanInstantiationException: Bean definition [javax.sql.DataSource] could not be loaded: Migration V1__schema.sql failed
-------------------------------
My application.yml is configured to point at a MariaDB instance in Azure like so:
micronaut:
application:
name: myapp
server:
context-path: /myapp/api
cors:
enabled: true
endpoints:
all:
enabled: true
sensitive: false
datasources:
default:
url: jdbc:mariadb://${ENV_DB_HOST_PORT:myurl.mariadb.database.azure.com}:${ENV_DB_PORT:3306}/${ENV_DB_SCHEMA:my_db}?useSSL=${ENV_DB_USE_SSL:true}&useUnicode=true&serverTimezone=Europe/London&autoReconnect=true
driverClassName: org.mariadb.jdbc.Driver
username: myusername
password: mypassword
dialect: MYSQL
allow-pool-suspension: false
connection-test-query: SELECT 1
connection-timeout: 30000
max-lifetime: 60000
maximum-pool-size: 10
minimum-idle: 1
flyway:
datasources:
default:
enabled: true
But my application-test.yml points at the H2 DB for testing purposes:
datasources:
default:
url: jdbc:h2:mem:devDb;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
driverClassName: org.h2.Driver
username: sa
password: ''
jpa:
default:
properties:
hibernate:
hbm2ddl:
auto: update
And my migration file V1__schema.sql looks like the following:
CREATE DATABASE if not exists my_db;
use my_db;
DROP TABLE IF EXISTS `preset`;
CREATE TABLE `preset` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`preset_name` varchar(30) NOT NULL,
`preset_value` varchar(4000) DEFAULT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `note`;
CREATE TABLE `note` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`code` varchar(30) NOT NULL,
`text` varchar(4000) DEFAULT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
The error is pretty much self explanatory
Message : Syntax error in SQL statement "CREATE DATABASE[*] IF NOT EXISTS MY_DB";
CREATE DATABASE if not exists my_db;
According to H2 commands, CREATE DATABASE is not a valid command for H2. You probably need the command CREATE SCHEMA if not exists my_db;

Understanding SLQ syntax error in Flyway initial migration

I am configuring Flyway for a brand new Spring Boot project. This is the initial migration provided by DBA.
The application works in SQL Server, however I am struggling to make it work on H2 for in-memory testing purposes. The DBA didn't provide (and maybe is not going to provide) a dialect-neutral version of the DDL.
I tried to use H2's SQL Server mode
application.yaml
spring:
datasource:
url: jdbc:h2:mem:almc-be;Mode=MSSQLServer
flyway:
check-location: true
enabled: true
encoding: utf-8
locations: classpath:/flyway/${spring.datasource.platform:sqlserver}
create-schemas: true
default-schema: dbo
schemas: dbo
Beginning of the script
-- Create tables section -------------------------------------------------
-- Table dbo.Users
CREATE TABLE [dbo].[Users]
(
[UserId] Int NOT NULL,
[UserName] Nvarchar(50) NOT NULL,
[UserSurname] Nvarchar(50) NOT NULL,
[UserEmail] Nvarchar(100) NOT NULL
)
go
-- Add keys for table dbo.Users
On startup, I get the following error
2021-07-22 15:48:43.189 WARN 6316 --- [ restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'flywayInitializer' defined in class path resource [org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration$FlywayConfiguration.class]: Invocation of init method failed; nested exception is org.flywaydb.core.internal.command.DbMigrate$FlywayMigrateException:
Migration V202107221432__DDL.sql failed
---------------------------------------
SQL State : 42000
Error Code : 42000
Message : Syntax error in SQL statement "CREATE TABLE ""dbo"".""Users""
(
""UserId"" INT NOT NULL,
""UserName"" NVARCHAR(50) NOT NULL,
""UserSurname"" NVARCHAR(50) NOT NULL,
""UserEmail"" NVARCHAR(100) NOT NULL
)
GO[*]
ALTER TABLE ""dbo"".""Users"" ADD CONSTRAINT ""PK_Users"" PRIMARY KEY (""UserId"")
GO
Yes, the escape sequence is changed in the logs from the SQL file
What is the cause of the error and how can I fix it without rewriting the script into a dialect-neutral version myself?

Liquibase 'addCheckConstraint' for ENUM colum in Oracle DB allows any character

I have a ENUM column and I am using liquibase addCheckConstraint to allow only ENUM values. However, addCheckConstraint doesnt work and allows any value. My yaml changelog looks as follows:
- changeSet:
id: 1565352995028-1
author: Zafrullah Syed
changes:
- createTable:
columns:
- column:
constraints:
primaryKey: true
name: ID
type: NUMBER(19, 0)
- column:
name: STATUS_ENUM
type: VARCHAR2(10 CHAR)
tableName: BOOKING
- addCheckConstraint:
constraintBody: STATUS_ENUM IN ('ERROR', 'CONFIRMED', 'QUEUED', 'REJECTED')
constraintName: enumcheck
tableName: SOME_TABLE
I am Using Oracle db.
If I try to run a sql query, then constraint works well:
ALTER TABLE SOME_TABLE
ADD CONSTRAINT enumcheck CHECK (status_enum IN ('ERROR', 'CONFIRMED', 'QUEUED', 'REJECTED'));
I tried to add another enableCheckConstraint to enable the existing check constraint but nothing seems to work.
addCheckConstraint is accessible only for the pro version, do you have it?

Resources