使用Spring的“jdbc:initialize-database”,如何使用存储过程运行脚本?

时间:2013-03-18 20:41:01

标签: mysql spring stored-procedures junit initialization

我正在使用Spring 3.1.1.RELEASE,JUnit 4.8.1和MySQL 5.5。我希望在每次测试之前截断所有表数据,但是在Spring中遇到错误,即使我可以通过命令行执行以下脚本(truncate_tables.sql)...

drop procedure if exists truncate_tables;

delimiter #
create procedure truncate_tables()
begin
 declare tab_name varchar(64);
 declare done tinyint unsigned default 0;

 declare table_cur cursor for select t.table_name
 from
  information_schema.schemata s
  inner join information_schema.tables t on s.schema_name = t.table_schema
 where
   s.schema_name = database() and t.table_type = 'BASE TABLE';

 declare continue handler for not found set done = 1;

 open table_cur;
 repeat
   fetch table_cur into tab_name;
   set @cmd = concat('truncate table ', tab_name);

   prepare stmt from @cmd;
   execute stmt;
 until done end repeat;

 close table_cur;
end #

SET FOREIGN_KEY_CHECKS=0;
CALL truncate_tables;
SET FOREIGN_KEY_CHECKS=1;

但是,使用这个Spring应用程序上下文......

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://localhost:3306/my_db" />
    <property name="username" value="myuser" />
    <property name="password" value="bypass" />
</bean>
...
<jdbc:initialize-database data-source="dataSource">
    <jdbc:script location="classpath:truncate_tables.sql"/>
    <jdbc:script location="classpath:db-test-data.sql"/>    
</jdbc:initialize-database> 

然而,我收到错误

Caused by: 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 &apos;delimiter # create procedure truncate_tables() begin  declare tab_name varchar(6&apos; at line 1
    at sun.reflect.GeneratedConstructorAccessor419.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
    at com.mysql.jdbc.Util.getInstance(Util.java:386)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1052)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3609)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3541)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2002)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2163)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2618)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2568)
    at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:842)
    at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:681)
    at org.springframework.jdbc.datasource.init.ResourceDatabasePopulator.executeSqlScript(ResourceDatabasePopulator.java:184)

    ... 50 more

我可以用任何方式修复上面的脚本吗?在我的JUnit测试中使用“extends AbstractTransactionalJUnit4SpringContextTests”扩展名不是一个选项。

2 个答案:

答案 0 :(得分:7)

<jdbc:script />不允许在包含的脚本中使用DELIMITER语句,但您可以使用具有相同结果的separator属性。

truncate_tables.sql中仅使用#分隔符并在separator属性中指定它,如下所示:

drop procedure if exists truncate_tables#

create procedure truncate_tables()
begin
 declare tab_name varchar(64);
 declare done tinyint unsigned default 0;

 declare table_cur cursor for select t.table_name
 from
  information_schema.schemata s
  inner join information_schema.tables t on s.schema_name = t.table_schema
 where
   s.schema_name = database() and t.table_type = 'BASE TABLE';

 declare continue handler for not found set done = 1;

 open table_cur;
 repeat
   fetch table_cur into tab_name;
   set @cmd = concat('truncate table ', tab_name);

   prepare stmt from @cmd;
   execute stmt;
 until done end repeat;

 close table_cur;
end #

SET FOREIGN_KEY_CHECKS=0#
CALL truncate_tables#
SET FOREIGN_KEY_CHECKS=1#

并在应用程序上下文中......

<jdbc:initialize-database data-source="dataSource">
    <jdbc:script separator="#" location="classpath:truncate_tables.sql"/>
    <jdbc:script location="classpath:db-test-data.sql"/>    
</jdbc:initialize-database> 

答案 1 :(得分:1)

它不起作用,因为分号用作语句分隔符。 您可以使用自定义分隔符定义ResourceDatabasePopulatorDataSourceInitializer bean: http://static.springsource.org/spring/docs/3.2.2.RELEASE/javadoc-api/org/springframework/jdbc/datasource/init/ResourceDatabasePopulator.html#setSeparator(java.lang.String)

见(尚未解决) https://jira.springsource.org/browse/SPR-8817