I'm trying to test JPA repository class written in kotlin, but I got error messages when I use spring boot 2.7.X.
It's okay when I conducted test with version 2.6.9, 2.6.8, and 2.4.4.
Here is a code - kotlin tutorial
After clone this tutorial, There are no errors at RepositoresTest.kt
, and I changed version of boot(and kotlin plugin) like this:
plugins {
id("org.springframework.boot") version "2.4.4"
id("io.spring.dependency-management") version "1.0.11.RELEASE"
kotlin("jvm") version "1.4.32"
kotlin("plugin.spring") version "1.4.32"
kotlin("plugin.allopen") version "1.4.32"
kotlin("plugin.jpa") version "1.4.32"
kotlin("kapt") version "1.4.32"
}
to
plugins {
id("org.springframework.boot") version "2.7.0"
id("io.spring.dependency-management") version "1.0.11.RELEASE"
kotlin("jvm") version "1.6.21"
kotlin("plugin.spring") version "1.6.21"
kotlin("plugin.jpa") version "1.6.21"
kotlin("kapt") version "1.6.21"
kotlin("plugin.allopen") version "1.6.21"
}
Except gradle script, nothing was changed. After that, I got error messages like this:
org.hibernate.exception.SQLGrammarException: could not prepare statement
javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not prepare statement
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:154)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:188)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1411)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1394)
at org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager.flush(TestEntityManager.java:171)
at com.example.blog.RepositoriesTests.When findByIdOrNull then return Article(RepositoriesTests.kt:22)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at
...(many lines)
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Syntax error in SQL statement "insert into [*]user (description, firstname, lastname, login, id) values (?, ?, ?, ?, ?)"; expected "identifier"; SQL statement:
insert into user (description, firstname, lastname, login, id) values (?, ?, ?, ?, ?) [42001-212]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:502)
at org.h2.message.DbException.getJdbcSQLException(DbException.java:477)
at org.h2.message.DbException.getSyntaxError(DbException.java:261)
at org.h2.command.Parser.readIdentifier(Parser.java:5724)
at org.h2.command.Parser.readIdentifierWithSchema(Parser.java:5684)
at org.h2.command.Parser.readTableOrView(Parser.java:8306)
at org.h2.command.Parser.parseInsert(Parser.java:1641)
at org.h2.command.Parser.parsePrepared(Parser.java:814)
at org.h2.command.Parser.parse(Parser.java:691)
at org.h2.command.Parser.parse(Parser.java:661)
at org.h2.command.Parser.prepareCommand(Parser.java:568)
at org.h2.engine.SessionLocal.prepareLocal(SessionLocal.java:631)
at org.h2.engine.SessionLocal.prepareCommand(SessionLocal.java:554)
at org.h2.jdbc.JdbcConnection.prepareCommand(JdbcConnection.java:1116)
at org.h2.jdbc.JdbcPreparedStatement.<init>(JdbcPreparedStatement.java:92)
at org.h2.jdbc.JdbcConnection.prepareStatement(JdbcConnection.java:288)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$1.doPrepare(StatementPreparerImpl.java:90)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:176)
... 107 more
Here are screenshots.
Comment From: scottfrederick
The H2 database considers user
a reserved keyword, so it can't be used as a table name. This is causing the Syntax error in SQL statement "insert into [*]user
failure. Spring Boot 2.7 includes an upgrade to H2, and apparently H2 started enforcing this with the newer version.
You can fix the problem in this tutorial by changing the name of the User
class to something that's not reserved, such as Author
. I've opened https://github.com/spring-guides/tut-spring-boot-kotlin/issues/60 to address this in the tutorial.
Comment From: steve-taylor
Rather than change the name of your table, this might help:
# application-test.properties (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