I have a Spring Boot 2 application with a mysql database running and wanted to add the Quartz scheduler. Configuration:
spring.quartz.job-store-type=jdbc
spring.quartz.jdbc.initialize-schema=always
spring.datasource.url=jdbc:mysql://localhost:3306/test?useSSL=false
But on start-up it doesn't create the database tables and fails when accessing the QRTZ_* tables. I debugged to get the cause which I found in ScriptUtils class called by Spring to execute the quartz script tables_mysql_innodv.sql. The exception is suppressed intentionally:
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an
error in your SQL syntax; check the manual that corresponds to your
MySQL server version for the right syntax to use near 'DROP TABLE IF
EXISTS QRTZ_PAUSED_TRIGGER_GRPS; DROP TABLE IF EXISTS QRTZ_SCHEDUL' at
line 9
I cannot see any syntax error and when I execute the same script in MySQL Workbench directly then it runs fine, i.e. creates the tables etc.
The source of the executed start-up script is available here. Exception is encountered in this line. There is one observation that makes me confused: The code in the same method tries to split the SQL statements but only 2 statements are extracted - the first line # and the remaining script. Maybe this is the actual problem.
So, how can I fix this?
Version info:
Spring Boot 2.0.2.RELEASE
mysql:mysql-connector-java:5.1.46
org.quartz-scheduler:quartz:2.3.0
Add the following property to your configuration, to specify the comment character :
spring.quartz.jdbc.comment-prefix=#
In YAML configuration properties file, as suggest by Mouad EL Fakir I added:
quartz:
job-store-type: jdbc
jdbc:
initialize-schema: always
comment-prefix: '#'
There is a workaround:
Copy the script file tables_mysql_innodb.sql
to your resources folder main/resources/org/quartz/impl/jdbcjobstore/tables_mysql_innodb.sql. This will be picked up by spring boot instead of the original file.
Remove all comment lines at the start of the file. These are the problematic lines for parsing in Spring's ScriptUtils class.
the method 'ScriptUtils.containsSqlScriptDelimiters' can not resolve the scripts properly.
because the mysql scripts's comments contain some single quotes. you can replace the single quotes with blank.
Related
I have a Spring Boot app that is configured to use JPA and its default-provider Hibernate. The app, in environment Non-Local, expects, and, through Oracle, is configured to connect to, an existing SQL DB, while the app, in environment Local, must, through H2, create it...embedded, in-memory, and private.
The DB utilizes one schema, as seen in this entity:
#Entity #Table(schema="foo",name="transactions")
Environment Local must, and is configured to, create (after first dropping any existing) tables and their schema. It is the creation, and dropping, of the latter - schema - that exhibits a problem:
Hibernate: drop table if exists foo.foo_transactions CASCADE
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "drop table if exists foo.foo_transactions CASCADE " via JDBC Statement
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Schema "FOO" not found; SQL statement: drop table if exists foo.foo_transactions CASCADE [90079-200]
...and a similar one (Schema not found) for CREATE.
So as to ensure no overlap, in the classpath, between H2 and Oracle, I, in the POM, separate them by build-profile (local and non-local):
<profile><id>local</id>...<dependencies><dependency>H2</dependency></dependencies>
<profile><id>non-local</id>...<dependences><dependency>Oracle</dependency></dependencies>
My relevant configuration of Spring Boot is:
# file application.properties
spring.datasource.url=jdbc:oracle:thin...
# file application-local.properties
# blankness of following value masks default configuration, in application.properties
spring.datasource.url=
spring.jpa.properties.javax.persistence.schema-generation.create-database-schemas=true
That JPA-property, javax.persistence.schema-generation.create-database-schemas, is supposed to do EXACTLY what I desire: create, in addition to tables, any internal schema. Yet, as shown in the aforementioned errors, it doesn't work!
Does H2, or the combination of H2, JPA-provider Hibernate, and Spring Boot, not honor it??? Or, have I miscoded/misconfigured something?
I don't want to get bogged down in the following (as the preceding question is my main concern), but for full disclosure...
P.S. If I remove the schema and build and run locally, everything works fine. But, the non-local (Production) flavor mandates that schema, so I must comply, and wish to do so also locally.
P.P.S. I am, indeed, aware of H2's directive 'INIT=CREATE SCHEMA IF NOT EXISTS foo' (to be applied to the datasource URL), and it, if used, does alleviate the problem. However, if I do use it (thereby having to explicitly supply a url, thereby conceding Spring Boot's very nice and full auto-configuration [of H2]), it causes another problem, which I need to avoid:
2022-08-29 15:43:27.494 WARN 15288 --- [on(5)-127.0.0.1] o.s.b.f.support.DisposableBeanAdapter: Invocation of destroy method failed on bean with name 'inMemoryDatabaseShutdownExecutor': org.h2.jdbc.JdbcSQLNonTransientConnectionException: Database is already closed (to disable automatic closing at VM shutdown, add ";DB_CLOSE_ON_EXIT=FALSE" to the db URL) [90121-200]
P.P.P.S. Neither that recommendation (...;DB_CLOSE_ON_EXIT=FALSE) nor its sister (...;DB_CLOSE_DELAY=-1) nor their combination alleviate that problem (attempt to close an already-closed DB).
I've now figured it out - my relevant JPA-property, at least as far as Hibernate is concerned, was slightly wrong...
Whereas I used (as it had once worked for me in EclipseLink, lazily leading me to believe that it was generic to all JPA-providers)
javax.persistence.schema-generation.create-database-schemas
I should have used this
javax.persistence.create-database-schemas
I have a spring boot application which is using Postgresql and also maven. It uses the Flyway migration to migrate database changes. I want to have a specific SQL file and run it by a command to insert some records for configuration whenever I want.
Could you please help me to handle this?
The specific topic is detailed here Spring Database Initialization.
Basically set the initialization values as you require:
spring.datasource.platform=postgres
spring.jpa.hibernate.ddl-auto=update
spring.datasource.initialization-mode=always
....
E.g. (there are much more options) if you place into resources the file data.sql it will be executed and you can add your fixtures.
For specific Flyway migrations you should check Execute Flyway Database Migrations on Startup.
Basically you add every new migration version script and it will be checked for every deployment.
What is the difference between spring.jpa.hibernate.hbm2ddl and spring.jpa.hibernate.ddl?
I have found in this question: What are the possible values of spring.datasource.initialization-mode? that OP is using both in properties, however it seems like the origin of hbm2ddl is hibernate directly not Spring Data Jpa.
Nevertheless, reading the answer from another OP, it looks like pass-through only.
However in our commercial project with mariadb, when we do not close our spring boot application gracefully with spring.jpa.hibernate.hbm2ddl.auto=create, when the application is run again, it deletes old data and creates everything from scratch. On the other hand with spring.jpa.hibernate.ddl.auto=create every second run (after no graceful application shutdown) causes key constraint exceptions (DB is not being dropper before creation)
From this Link
By default, JPA databases are automatically created only if you use an embedded database (H2, HSQL, or Derby).
You can explicitly configure JPA settings by using spring.jpa.* properties. For example, to create and drop tables you can add the following line to your application.properties:
spring.jpa.hibernate.ddl-auto=create-drop
Hibernate’s own internal property name for this (if you happen to remember it better) is hibernate.hbm2ddl.auto.
From this Link
spring.jpa.hibernate.ddl-auto This is actually a shortcut for the "hibernate.hbm2ddl.auto" property.
Defaults to "create-drop" when using an embedded database and no schema manager was detected. Otherwise, defaults to "none".
From this Link
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).
I am developing a simple RESTfull service in Java Spring and using JDBCTemplate.
However, I am getting a run time error, which I don't understand. It complains about SPRING_SESSION table not existing, however I think Spring should be able to create necessary tables as needed.
application.properties:
spring.jpa.hibernate.ddl-auto=create
spring.datasource.url=jdbc:mysql://localhost:3306/getfit?useSSL=false
spring.datasource.username=root
spring.datasource.password=***
Exception:
org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [DELETE FROM SPRING_SESSION WHERE EXPIRY_TIME < ?]; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'getfit.SPRING_SESSION' doesn't exist
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:235) ~[spring-jdbc-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72) ~[spring-jdbc-5.0.4.RELEASE.jar:5.0.4.RELEASE]
Exception is triggered by some process attempting to delete record from table which doesn't exist.
Manually creating the table leads to more errors (not existing columns). Setting
hibernate.ddl-auto=update
also doesn't help.
Additionally, I have
modified MySQL configuration to allow upper case characters and this also did not help.
Interestingly enough, this issue happened after I formatted my OS and cloned project from github. Before everything was working fine.
Do you have any ideas what could go wrong? Let me know if you need me to show you some code.
Thanks for looking in to this :)
try to set the initialize-schema to always:
spring.session.jdbc.initialize-schema: always
Spring session creates a table to store sessions in the database. Since the required table doesn't exist it throws the error.
Here's a link you can refer
https://sivalabs.in/2018/02/session-management-using-spring-session-jdbc-datastore/
How do I configure derby not to drop my database between each unit/integration test ? I want to keep the data between runs.
dbDialect=DERBY
XADataSourceClassName=org.apache.derby.jdbc.ClientXADataSource
databaseName=ForumThreadDB
createDatabase=update
serverName=localhost
portNumber=1527
DriverClassName=org.apache.derby.jdbc.ClientDriver
url=jdbc:derby://localhost:1527/ForumThreadDB;create=true
user=APP
password=whatever
I just tried to connect to derby outside. It is possible that things are never persisted, although I get no error when persisting, but I remember this have happened before.
I also get this error on startup of the test
---> WARN o.Runtime - An error occurred while registering a ClassTransformer with PersistenceUnitInfo: name 'ForumThreadDomainPU',
root URL
[file:/C:/Projects/OurForum/ForumThreadDomain/target/classes/]. The
error has been consumed. To see it, set your openjpa.Runtime log level
to TRACE. Load-time class transformation will not be available.
I suppose this could be more to do with the Junit setting
try adding
#Rollback(value=false)
before the method for which you don't want the persistence to rollback
If you are running your tests within Maven, you can use a Maven plugin I wrote for Derby. It starts up an in-memory Derby database for the duration of your tests, so all of them could share the same data.
Check out the USAGE file here. The plugin is available via Maven Central so you don't need to add extra repositories.