Spring Session table-name property does not change the table name - spring

I have to be able to rename the default Spring Session table and found the following configuration options in the spring session documentation.
spring.session.jdbc.schema=classpath:org/springframework/session/jdbc/schema-##platform##.sql # Path to the SQL file to use to initialize the database schema.
spring.session.jdbc.table-name=SPRING_SESSION # Name of database table used to store sessions.
Here is what I am trying to set in application.properties:
spring.session.store-type=jdbc
spring.session.jdbc.table-name: APP_SPR_SESSION
spring.session.jdbc.schema: src/main/resources/appSpringSession.sql
Here are the contents of appSpringSession.sql which is a modified/renamed version of schema-oracle.sql
CREATE TABLE app_app.APP_SPR_SESSION (
PRIMARY_ID CHAR(36) NOT NULL,
SESSION_ID CHAR(36) NOT NULL,
CREATION_TIME NUMBER(19,0) NOT NULL,
LAST_ACCESS_TIME NUMBER(19,0) NOT NULL,
MAX_INACTIVE_INTERVAL NUMBER(10,0) NOT NULL,
EXPIRY_TIME NUMBER(19,0) NOT NULL,
PRINCIPAL_NAME VARCHAR2(100 CHAR),
CONSTRAINT APP_SPR_SESSION_PK PRIMARY KEY (PRIMARY_ID)
);
CREATE UNIQUE INDEX APP_SPR_SESSION_IX1 ON APP_SPR_SESSION (SESSION_ID);
CREATE INDEX APP_SPR_SESSION_IX2 ON APP_SPR_SESSION (EXPIRY_TIME);
CREATE INDEX APP_SPR_SESSION_IX3 ON APP_SPR_SESSION (PRINCIPAL_NAME);
CREATE TABLE app_app.APP_SPR_SESSION_ATTRIBUTES (
SESSION_PRIMARY_ID CHAR(36) NOT NULL,
ATTRIBUTE_NAME VARCHAR2(200 CHAR) NOT NULL,
ATTRIBUTE_BYTES BLOB NOT NULL,
CONSTRAINT APP_SPR_SESSION_ATTRIBUTES_PK PRIMARY KEY
(SESSION_PRIMARY_ID,
ATTRIBUTE_NAME),
CONSTRAINT APP_SPR_SESSION_ATTRIBUTES_FK FOREIGN KEY
(SESSION_PRIMARY_ID)
REFERENCES APP_SPR_SESSION(PRIMARY_ID) ON DELETE CASCADE
);
I have manually added the tables using the above ddl into the Oracle database and every time the app starts it's still looking for SPRING_SESSION table.
Seems like specifying these options has no effect. What am I reading wrong here from the docs?
Also I am using Spring Session 2.0.2 Release and Spring Boot 2.0.1.RELEASE

The reason spring.session.* do not work for you is because your are using #EnableJdbcHttpSession. That means that you are configuring Spring Session explicitly, so Spring Boot backs off with its auto-configuration.
You should remove #EnableJdbcHttpSession and ensure Spring Boot is auto-configuring Spring Session. Additionally, you could also leave spring.session.store-type out, since Spring Boot should be able to deduce which session repository implementation are you using as long as you have only only SessionRepository implementation on the classpath (i.e. you depend only on spring-session-jdbc and no other Spring Session modules).

You can also use #EnableJdbcHttpSession(tableName = "APP_SPR_SESSION")

Related

Tests failing when upgrading to Spring Boot 2.7 - "CommandAcceptanceException: Error executing DDL"

After upgrading to Boot 2.7 the integration tests that were using an embedded H2 database started failing.
I see this WARN message in the logs, but it's not very clear the cause or the solution for this:
WARN 8053 ---[ main] o.h.t.s.i.ExceptionHandlerLoggedImpl :GenerationTarget encountered exception accepting command : Error executing DDL "create table user (id bigint generated by default as identity, email varchar(255) not null, name varchar(255), primary key (id))" via JDBC Statement
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "create table user (id bigint generated by default as identity, email varchar(255) not null, name varchar(255), primary key (id))" via JDBC Statement
...
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Syntax error in SQL statement "create table [*]user (id bigint generated by default as identity, email varchar(255) not null, name varchar(255), primary key (id))"; expected "identifier"; SQL statement:
create table user (id bigint generated by default as identity, email varchar(255) not null, name varchar(255), primary key (id)) [42001-212]
...
It seems my User table is not created after the upgrade, thus making my tests fail.
It seems Boot 2.7 upgraded to its H2 dependency to 2.x, which is not backward compatible and introduces several changes:
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.7-Release-Notes#h2-21
The issue was that User is now a Keyword / reserved word (The H2 "migration-to-v2" guide was not very helpful in my case; it mentioned new keywords were added, but it didn't provide a link to ):
https://www.h2database.com/html/advanced.html#keywords
So, what I had to do is use "quoted names" to define the Table name of my Entity (it seems I can use backticks in the table annotation too instead of escaping double quotes):
#Table(name="\"user\"")
#Entity
public class User {
...
I also had to use double quotes on my data.sql files for this table:
INSERT INTO "user"(id, email, name) VALUES(1, 'test#user.com', 'Test User');
Note: the migration guide also mentions the possibility of using the SET NON_KEYWORDS command as a workaround, but it also discourages it.
Add the following to your src/test/resources/application-test.properties file (assuming your tests run with the test profile):
spring.jpa.properties.hibernate.globally_quoted_identifiers=true
spring.jpa.properties.hibernate.globally_quoted_identifiers_skip_column_definitions = true
If any of your JPA entities have UUID fields, ensure those fields are annotated with #Column and the annotation's columnDefinition defines the column as type UDID. (In its simplest form: #Column(columnDefinition="UDID").) This works around a Hibernate bug.
It could be because of Identity columns in schema.sql.Identity columns should be normally declared with GENERATED BY DEFAULT AS IDENTITY.
Ex: JOB_EXECUTION_ID BIGINT IDENTITY -- should be changed as JOB_EXECUTION_ID BIGINT GENERATED BY DEFAULT AS IDENTITY.
Refer http://www.h2database.com/html/migration-to-v2.html for more such changes occurred due to upgrade in H2 version.

Springboot, EclipseLink and MariaDB Generates VARCHAR without size

I have an application built with Sprigboot (2.4.5) Spring JPA and Eclipselink. It connects to MariaDB. The CREATE table statements the application is generating are structured as VARCHAR without a size. However, I would have expected expect VARCHAR(255). MariaDB rejects the VARCHAR statements and fails to create tables. I am sure I am missing something really really obvious here - so I apologize in advance! But hoping for some guidance. This is an example of the generated code:
CREATE TABLE api_user (ID NUMBER(19) NOT NULL, apiKey VARCHAR, assignDate TIMESTAMP, code VARCHAR UNIQUE, disabled VARCHAR, expiryDate TIMESTAMP, name VARCHAR, version NUMBER(19), PRIMARY KEY (ID))
eclipselinkDdlGeneration=drop-and-create-tables
eclipselinkDdlGenerationOutputMode=database
eclipselinkJdbcUppercaseColumns=false
eclipselinkWeaving=false
dbDriver=org.mariadb.jdbc.Driver

Spring batch metadata tables already exist exception

I have a spring batch application writing to a MySql database. On first run, everything runs as expected and the write is a success. However, after restarting the service on subsequent runs the following exception arises: Table 'BATCH_JOB_INSTANCE' already exists. This exception arises for each of the metadata tables that Spring tries to create, and the write to my actual 'business logic' database does not occur.
The full log:
INFO org.springframework.jdbc.datasource.init.ScriptUtils - Executing SQL script from class path resource [org/springframework/batch/core/schema-mysql.sql]
DEBUG org.springframework.jdbc.datasource.init.ScriptUtils - Failed to execute SQL script statement #1 of class path resource [org/springframework/batch/core/schema-mysql.sql]: CREATE TABLE BATCH_JOB_INSTANCE ( JOB_INSTANCE_ID BIGINT NOT NULL PRIMARY KEY , VERSION BIGINT , JOB_NAME VARCHAR(100) NOT NULL, JOB_KEY VARCHAR(32) NOT NULL, constraint JOB_INST_UN unique (JOB_NAME, JOB_KEY) ) ENGINE=InnoDB
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'BATCH_JOB_INSTANCE' already exists
Is there any Spring Batch configuration/annotation I can set to tell Spring to write to the existing database instead of just quitting and raising an exception if the database already exists?
The org/springframework/batch/core/schema-mysql.sql file looks like the following:
-- Autogenerated: do not edit this file
CREATE TABLE BATCH_JOB_INSTANCE (
JOB_INSTANCE_ID BIGINT NOT NULL PRIMARY KEY ,
VERSION BIGINT ,
JOB_NAME VARCHAR(100) NOT NULL,
JOB_KEY VARCHAR(32) NOT NULL,
constraint JOB_INST_UN unique (JOB_NAME, JOB_KEY)
) ENGINE=InnoDB;
so there is no error handling in the case that the table exists already.

Spring boot not creating schema correctly?

I have very simple spring boot app which is using h2 database on local. I have schema-h2.sql which has below script -
CREATE TABLE USERS(
userid NUMBER(10,0) AUTO_INCREMENT PRIMARY KEY,
email VARCHAR(256) UNIQUE NOT NULL,
fname VARCHAR(256),
lname VARCHAR(256)
);
And in application-default.properties -
spring.h2.console.enabled=true
spring.datasource.platform=h2
spring.datasource.url=jdbc:h2:mem:testdb;MODE=MSSQLServer;DB_CLOSE_DELAY=-1;DB_CLO SE_ON_EXIT=false
When I look at /h2-console, I can see table being created but it is missing unique constraint on email column.
I even tried adding alter statement in schema-h2.sql script to create constraint but that doesn't work either -
ALTER TABLE USERS ADD CONSTRAINT UQ_EMAIL UNIQUE(email);
Also, when run those script in h2-console it creates unique constraint correctly so it does seem like something to do with how spring executes them.
When debugging I can see that Alter statement gets executed without any exception in ScriptUtils class.
Not sure how to take this forward so any help will be greatly appreciated.
For anyone else coming across this, I was able to fix it by altering my JPA annotation. Adding the unique parameter in addition to creating the constraint in h2-schema.sql allowed the constraint to actually be created.
#Column(name = "email", unique = true, nullable = false)
private String email;
If schema is beign created by spring boot with schema.sql file, make sure to disable hibernate schema auto create:
spring.jpa.hibernate.ddl-auto=none
Otherwise, Hibernate will overwritte it everytime the app starts.

H2 Database - Unknown data type of MySQL script

I'm new in using in-memmory database.
I tried to use H2 database for developing project with spring boot, spring data JPA, but i got a problem when initialize application.
Caused by: org.h2.jdbc.JdbcSQLException: Unknown data type: "FK_PERSON__PERSONTYPE_IDX"; SQL statement:
Because this script was exported from MySQL. So i thinked there are some wrong syntax which H2 does not understand
For example, this is a part of script:
CREATE TABLE `person` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`firstname` varchar(255) NOT NULL,
`lastname` varchar(255) DEFAULT NULL,
`type` int(11) NOT NULL,
`address` text,
PRIMARY KEY (`id`),
KEY `fk_person__persontype_idx` (`type`),
CONSTRAINT `fk_person__persontype` FOREIGN KEY (`type`) REFERENCES `persontype` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT=' ';
And i tried some solutions from these:
Convert MySQL script to H2
http://matthewcasperson.blogspot.de/2013/07/exporting-from-mysql-to-h2.html
Replace symbols with double quotes, single quotes,... even not use quote at all but not working.
Please show me why?
Thank you.
I had a similar issue.
Removing the "KEY" line, which in your example corrosponds to:
KEY `fk_person__persontype_idx` (`type`),
worked for me.

Resources