runscript executed multiple times for @Autowired jdbcTemplate and h2 in-memory database

十年热恋 提交于 2019-12-11 01:17:59

问题


I've inherited a project and am trying to get a set of integration tests running against an in-memory h2 database. In order for them to pass some tables, relationships and reference data needs creating.

I can see the problem in that the script referenced in RUNSCRIPT is being executed multiple times and therefore generating Index "XXX_IDX" already exists errors and other violations. So is there a way to force the script to only be run once or do I need a external database? It seems that the script is run on every connection which I assume is by design.

properties file

my.datasource.url=jdbc:h2:mem:my_db;DB_CLOSE_DELAY=-1;MODE=Oracle;MVCC=TRUE;INIT=RUNSCRIPT FROM 'classpath:/create-tables-and-ref-data.sql'

XML config

<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="url" value="${my.datasource.url}"/>
    <!-- other properties for username, password etc... -->
</bean>

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="myDataSource"/>
</bean>

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="myDataSource"/>
</bean>

<tx:annotation-driven transaction-manager="transactionManager"/>

many Java classes in the following pattern

@Component
public class SomethingDAOImpl implements SomethingDAO {
  @Autowired
  public SomethingDAOImpl(JdbcTemplate jdbcTemplate) {
    this.jdbcTemplate = jdbcTemplate;
  }
}

@Component
public class SomethingElseDAOImpl implements SomethingElseDAO {
  @Autowired
  public SomethingElseDAOImpl(JdbcTemplate jdbcTemplate) {
    this.jdbcTemplate = jdbcTemplate;
  }
}

With the default bean scope being singleton I thought this would just work, but I guess i'm missing something. Also, if I switch to an real Oracle instance that already has the tables and reference data set-up, the tests all pass.


回答1:


In many cases, it is possible to write the SQL script so that no exceptions are thrown:

create table if not exists test(id int, name varchar(255));
create index if not exists test_idx on test(name);



回答2:


I ended up using an alternative approach, as I could not write the SQL in a way that could be reapplied without error.

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
    http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd">

    <jdbc:initialize-database data-source="myDataSource" enabled="true" ignore-failures="ALL">
        <jdbc:script location="classpath:create-and-alter-tables-first-then-add-test-data.sql" />
    </jdbc:initialize-database>
</beans>

which is executed once at context initialization.

Note: other namespaces and beans omitted for brevity.



来源:https://stackoverflow.com/questions/14070997/runscript-executed-multiple-times-for-autowired-jdbctemplate-and-h2-in-memory-d

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!