【问题标题】:How to initialize in-memory HSQLDB using script via Spring如何通过 Spring 使用脚本初始化内存中的 HSQLDB
【发布时间】:2012-03-08 21:55:51
【问题描述】:

我正在尝试对我的 DAO 进行单元测试(使用 Spring 和 Hibernate)。我按照this 教程使用 HSQLDB。该教程指出内存中的 HSQLDB 数据库可以使用 SQL 脚本进行初始化,但我找不到有关如何在 Spring 中执行此操作的信息。这是相关的 Spring 上下文配置:

 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="org.hsqldb.jdbcDriver" />
    <property name="url" value="jdbc:hsqldb:mem:mydb" />
    <property name="username" value="sa" />
    <property name="password" value="" />
    <property name="initialSize" value="5" />
    <property name="maxActive" value="10" />
    <property name="poolPreparedStatements" value="true" />
    <property name="maxOpenPreparedStatements" value="10" />
</bean> 

任何帮助将不胜感激。谢谢。

【问题讨论】:

  • The difference between the in-memory and the file mode is that the in-memory database is empty, but the file mode is initialized with data. One strategy that I have employed in the past is to create a standalone database, allow Hibernate to create the tables and add data for me, save the data into a script, and then use the file-based URL to point to the script. The good thing about the script is that it is raw SQL so you are free to pre-populate the database with whatever data you want to test against.这个来自你链接的帖子,它清楚地提到了这个过程。
  • 我阅读了上面的内容,但我想我没有把 2 和 2 放在一起,然后你会使用 HSQLDB 的“文件”版本,它会在内存中使用脚本作为启动.

标签: java spring hsqldb


【解决方案1】:

如果您正在尝试使用内存数据库和 Spring,有一个新的jdbc namespace for Spring 3 可以让使用嵌入式数据库变得非常容易。

最好的部分是它充当DataSource,因此可以轻松放入以替换现有的dataSource bean。

<jdbc:embedded-database id="dataSource" type="HSQL">
    <jdbc:script location="classpath:schema.sql"/>
    <jdbc:script location="classpath:test-data.sql"/>
</jdbc:embedded-database>

如果您对使用 Java Config 执行此操作更感兴趣,请查看 EmbeddedDatabaseBuilder(Spring 3.0 中的新功能)。

@Configuration
public class DatabaseTestConfig {
    @Bean
    public DataSource dataSource() {
        return new EmbeddedDatabaseBuilder()
            .setType(EmbeddedDatabaseType.HSQL)
            .addScript("classpath:schema.sql")
            .addScript("classpath:test-data.sql")
            .build();
    }
}

【讨论】:

  • 这看起来像是答案。我正在玩弄 HSQLDB 和嵌入式数据库,试图让其中任何一个工作。到目前为止,EB 似乎运行良好。
  • +1。我的 answer 适用于 Spring 2.X;现在我们在 Spring 3.X 上,我想我们会转向这种方法。
  • 我发现这只是大约 6 个月前浏览 Spring 3 文档。它非常易于使用(并不是说您的答案的方法不是),而且我已经能够对其进行几次测试。
  • 我认为提一下对 hsqldb 所需的依赖也很好
【解决方案2】:

Nicholas 的回答很好,但您也可以使用 jdbc 命名空间来初始化外部数据库:

<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/DS"/>

<jdbc:initialize-database data-source="dataSource">
    <jdbc:script location="classpath:/META-INF/database/init.sql"/>
</jdbc:initialize-database>

【讨论】:

    【解决方案3】:

    在您链接到的教程中,其中一种设置方法是(经过明显更正后):

    • 来自脚本的内存中:jdbc:hsqldb:file:path-to-file

    我认为这似乎是相关的。我建议将path-to-file 替换为看起来像完全限定文件名的东西......

    【讨论】:

    • 但这是否将数据库保存在文件中而不是内存中?如果我回滚所有事务,我可以假设这是安全的吗?
    • @John:默认情况下,它通常将其保存在内存中(可基于每个表进行配置),尽管它会将其迁移到磁盘以便持久存在。唉,文档对确切需要的细节不是很清楚。我想您将不得不进行一些实验,一切都会变得清晰。 (这对我来说有点蹩脚……)
    • 供其他人将来参考:当你这样做时,它确实主要在内存中运行它,它非常快,但如果你进行更改,它最终会将它们刷新回磁盘,这可能是不是你想要的。要解决此问题,您需要设置 hsqldb 'files_readonly' 选项。在连接字符串中执行此操作无效,但您可以在 DB 属性文件中执行此操作:第一次运行上述内容时,如果 [path-to-file].properties 尚不存在,它将创建.在底部添加一个新行“hsqldb.files_readonly=true”,就完成了。
    【解决方案4】:

    您可以通过为两个新属性 initExecuteSqlFiledestroyExecuteSqlFile 创建一个带有 getters/setters 的 BasicDataSource 子类来解决这个问题,这两个属性可以有一个逗号分隔的 SQL 文件列表来执行。子类将具有处理 init/destroy SQL 文件的 init()destroy() 方法。

    然后使用下面的bean定义:

    <bean
        id="datasource"
        class="com.example.MyBasicDataSource"
        destroy-method="destroy"
        init-method="init"
    >
        <property name="destroyExecuteSqlFile">
            <value>h2-destroy-01.sql</value>
        </property>
        <property name="initExecuteSqlFile">
            <value>h2-init-01.sql,h2-init-02.sql,h2-init-03.sql</value>
        </property>
        <!-- Other properties -->
    </bean>
    

    【讨论】:

    • 所以我们还需要在 init() 中实现一些填充逻辑?
    【解决方案5】:

    使用嵌入式数据库,我们只能从同一个 JVM 连接到数据库。如果我们有两个 JVM,出于性能或其他限制,我们可以:

    1. 您可以使用this answer 中建议的数据源,而不是使用嵌入式数据库。

    2. 然后像Poitrek De 建议的那样初始化(在previous answer 中也建议)。您可能只想在表不存在时才创建表(如建议的here)。

    【讨论】:

      猜你喜欢
      • 2021-08-28
      • 1970-01-01
      • 2010-12-29
      • 1970-01-01
      • 2013-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-05
      相关资源
      最近更新 更多