我正在尝试使用spring-jdbc创建一个SQLite数据库。我正在使用这种XML配置进行自动初始化:
<jdbc:initialize-database data-source="logDbDataSource" enabled="true">
<jdbc:script location="classpath:scheme.sql" />
</jdbc:initialize-database>
scheme.sql创建一个用于记录事件的表。我还想使用触发器自动删除旧数据,因此SQL看起来像这样:
CREATE TABLE IF NOT EXISTS events (
event_id INTEGER PRIMARY KEY AUTOINCREMENT,
time DATETIME DEFAULT CURRENT_TIMESTAMP,
value TEXT NOT NULL
);
CREATE TRIGGER IF NOT EXISTS cleanup
AFTER INSERT ON events
BEGIN
DELETE FROM events WHERE time < datetime('now', '-35 days');
END;
当我使用
手动创建数据库时,这完全正常 sqlite3 eventDb.sqlite < schema.sql
。
我的问题是,它在启动程序时导致以下异常,由Spring处理:
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:53)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.jdbc.datasource.init.DataSourceInitializer#0': Invocation of init method failed; nested exception is org.springframework.dao.DataAccessResourceFailureException: Failed to execute database script; nested exception is org.springframework.jdbc.datasource.init.ScriptStatementFailedException: Failed to execute SQL script statement at line 3 of resource class path resource [homectrlLog-schema.sql]: CREATE TRIGGER IF NOT EXISTS cleanup AFTER INSERT ON events BEGIN DELETE FROM events WHERE time < datetime('now', '-35 days')
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1553)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:700)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
at org.atennert.homectrl.Main.main(Main.java:34)
... 6 more
Caused by: org.springframework.dao.DataAccessResourceFailureException: Failed to execute database script; nested exception is org.springframework.jdbc.datasource.init.ScriptStatementFailedException: Failed to execute SQL script statement at line 3 of resource class path resource [homectrlLog-schema.sql]: CREATE TRIGGER IF NOT EXISTS cleanup AFTER INSERT ON events BEGIN DELETE FROM events WHERE time < datetime('now', '-35 days')
at org.springframework.jdbc.datasource.init.DatabasePopulatorUtils.execute(DatabasePopulatorUtils.java:56)
at org.springframework.jdbc.datasource.init.DataSourceInitializer.afterPropertiesSet(DataSourceInitializer.java:84)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1612)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1549)
... 18 more
Caused by: org.springframework.jdbc.datasource.init.ScriptStatementFailedException: Failed to execute SQL script statement at line 3 of resource class path resource [homectrlLog-schema.sql]: CREATE TRIGGER IF NOT EXISTS cleanup AFTER INSERT ON events BEGIN DELETE FROM events WHERE time < datetime('now', '-35 days')
at org.springframework.jdbc.datasource.init.ResourceDatabasePopulator.executeSqlScript(ResourceDatabasePopulator.java:202)
at org.springframework.jdbc.datasource.init.ResourceDatabasePopulator.populate(ResourceDatabasePopulator.java:135)
at org.springframework.jdbc.datasource.init.CompositeDatabasePopulator.populate(CompositeDatabasePopulator.java:56)
at org.springframework.jdbc.datasource.init.DatabasePopulatorUtils.execute(DatabasePopulatorUtils.java:47)
... 21 more
Caused by: org.sqlite.SQLiteException: [SQLITE_ERROR] SQL error or missing database (near ")": syntax error)
at org.sqlite.core.DB.newSQLException(DB.java:920)
at org.sqlite.core.DB.newSQLException(DB.java:932)
at org.sqlite.core.DB.throwex(DB.java:897)
at org.sqlite.core.NativeDB.prepare(Native Method)
at org.sqlite.core.DB.prepare(DB.java:227)
at org.sqlite.jdbc3.JDBC3Statement.execute(JDBC3Statement.java:60)
at org.springframework.jdbc.datasource.init.ResourceDatabasePopulator.executeSqlScript(ResourceDatabasePopulator.java:187)
... 24 more
我最好的猜测是,自动填充和日期时间功能存在一些问题(与日期功能相同)。当我从脚本中删除触发器时,一切正常。
这是SQLite / SQL函数和/或使用Spring JDBC自动初始化的问题吗?我是否必须以不同的方式编写它以使其适用于自动初始化?
答案 0 :(得分:0)
Failed to execute SQL script statement at line 3 of resource class path resource [homectrlLog-schema.sql]: CREATE TRIGGER IF NOT EXISTS cleanup AFTER INSERT ON events ⏎ BEGIN DELETE FROM events WHERE time < datetime('now', '-35 days')
无论您使用什么代码执行脚本,都会在每个分号处拆分SQL。当你有触发器时这是错误的,因为直到最后的END的整个触发器创建必须作为单个语句执行。