使用 Spring 和 jdbc DataSourceTransactionManager 填充 H2 数据库

Posted

技术标签:

【中文标题】使用 Spring 和 jdbc DataSourceTransactionManager 填充 H2 数据库【英文标题】:Populating H2 database with Spring and jdbc DataSourceTransactionManager 【发布时间】:2017-02-22 22:17:23 【问题描述】:

我正在尝试使用带有脚本配置的 H2 嵌入式数据库在测试期间创建和加载数据库。

它工作正常,但是当我尝试为我的数据库交互添加事务支持时,我在上下文初始化期间遇到错误。

这是我的弹簧配置:

<bean id="dbcpDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="org.h2.Driver" />
    <property name="url" value="jdbc:h2:mem:embeddedH2Database;MODE=Oracle;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE" />
    <property name="username" value="sa" />
    <property name="password" value="" />
</bean>

<jdbc:embedded-database id="embeddedH2Database" type="H2">
    <jdbc:script location="classpath:db/sql/c`enter code here`reate-db.sql" />
    <jdbc:script location="classpath:db/sql/insert-data.sql" />
</jdbc:embedded-database>


<tx:advice id="txAdvice" transaction-manager="txManager">
    <!-- the transactional semantics... -->
    <tx:attributes>
        <tx:method name="*" timeout="60" />
    </tx:attributes>
</tx:advice>

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

<aop:config>
    <aop:pointcut id="serviceOperation" expression="execution(* x.y.service.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperation"/>
</aop:config>

这是 bean 创建错误:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'embeddedH2Database': Cannot create inner bean '(inner bean)#23bff419' of type [org.springframework.jdbc.datasource.init.CompositeDatabasePopulator] while setting bean property 'databasePopulator'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#23bff419': Cannot create inner bean '(inner bean)#1d2bd371' of type [org.springframework.jdbc.datasource.init.ResourceDatabasePopulator] while setting bean property 'populators' with key [0]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#1d2bd371': Cannot create inner bean '(inner bean)#65fe9e33' of type [org.springframework.jdbc.config.SortedResourcesFactoryBean] while setting bean property 'scripts'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#65fe9e33': Post-processing of FactoryBean's object failed; nested exception is java.lang.AssertionError

【问题讨论】:

【参考方案1】:

由于我使用的是事务,因此它与执行创建表和加载数据的脚本发生冲突。

这些脚本需要在外部执行而不应用spring config添加的事务语义。

所以我改变了嵌入式数据库bean如下删除脚本元素:

<jdbc:embedded-database id="embeddedH2Database" type="H2"/>

并在我的测试前添加@Sql注解来创建表和加载表。

@Sql("classpath:db/sql/create-db.sql", "classpath:db/sql/insert-data.sql")

【讨论】:

以上是关于使用 Spring 和 jdbc DataSourceTransactionManager 填充 H2 数据库的主要内容,如果未能解决你的问题,请参考以下文章

h2使用

如何强制 Testcontainers 使用特定的 docker 镜像?

2019-04-29 EasyWeb下配置Atomikos+SQLServer分布式数据源

具有多个数据源 Oracle 和 H2 的 Spring Boot

Spring Boot 使用 SSL 连接到 Postgresql

spring: 在Spring应用中使用JDBC(使用profiles选择数据源/使用基于JDBC驱动的数据源)