使用 HSQL 而不是 Oracle 对 MyBatis 进行单元测试

发布于 2024-12-10 20:50:03 字数 2532 浏览 0 评论 0原文

我想使用 HSQL 内存数据库对 MyBatis 持久层进行单元测试。实际应用使用Oracle数据库。在我们开始为 id 列添加自动递增数字之前,这工作得很好。 Oracle 需要使用序列来获取递增的数字,因此在 Oracle 数据库中创建了一个名为 basic_seq 的序列。在我的 MyBatis 映射器 XML 文件中,我有以下内容:

<insert id="insertBasis" parameterType="com.foo.Basis" useGeneratedKeys="true" keyProperty="id">
        <selectKey resultType="long" keyProperty="id" order="BEFORE">
            SELECT basis_seq.NEXTVAL FROM DUAL
        </selectKey>
        insert into basis
        (id, name)
        values
        (#{id}, #{name})
</insert>

当我运行应用程序但单元测试出现错误时,此方法有效:

org.springframework.jdbc.BadSqlGrammarException:选择密钥时出错 或将结果设置为参数对象。原因: java.sql.SQLSyntaxErrorException:用户缺乏权限或对象没有 发现:双;错误的 SQL 语法 [];嵌套异常是 java.sql.SQLSyntaxErrorException:用户缺乏权限或对象没有 发现:双

据我了解,“DUAL”是 Oracle 中存储序列的某种虚拟表,但我的测试数据库中没有此表。如果我删除 标签,则单元测试可以工作(因为 HSQL 可以为标记为 identity 的列自动生成 id),但不能用于真正的应用程序。一种解决方法是为单元测试创​​建单独的 MyBatis 映射器 XML 文件,而不使用 标签,但这是不希望的,因为我想测试真实的配置。

有没有办法在 HSQL 中创建和使用序列,或者可能有一些 MyBatis 解决方法?或者我应该使用另一个数据库(例如 H2)进行单元测试?


我使用:

  • Spring 3.0.5
  • HSQL 2.2.4
  • MyBatis 3.0.5

更新:

fredt 得到答案后,这是我编辑 Spring 配置的方式:

在我定义数据源之前:

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

现在我这样做:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close">
    <property name="driverClassName" value="org.hsqldb.jdbcDriver" />
    <property name="url" value="jdbc:hsqldb:mem:test;sql.syntax_ora=true" />
    <property name="username" value="sa" />
    <property name="password" value="" />
</bean>

<jdbc:initialize-database data-source="dataSource">
    <jdbc:script location="classpath:test-data/schema.sql" />
    <jdbc:script location="classpath:test-data/data.sql" />
</jdbc:initialize-database>

此外,在 schema.sql 中,我需要创建序列:(

CREATE SEQUENCE BASIS_SEQ START WITH 1000 INCREMENT BY 1;
CREATE SEQUENCE OTHER_SEQ START WITH 1000 INCREMENT BY 1;

如果在单元测试期间多次运行此脚本,请记住添加 drop sequence BASIS_SEQ if isn't; 到顶部架构.sql)

I would like to unit test my MyBatis persistence layer using an HSQL in-memory database. The real application uses an Oracle database. This worked fine unitl we started adding auto incremented numbers for the id columns. Oracle requires the use of a sequence to get the incremented number so a sequence called basis_seq was created in the Oracle database. In my MyBatis mapper XML file I have this:

<insert id="insertBasis" parameterType="com.foo.Basis" useGeneratedKeys="true" keyProperty="id">
        <selectKey resultType="long" keyProperty="id" order="BEFORE">
            SELECT basis_seq.NEXTVAL FROM DUAL
        </selectKey>
        insert into basis
        (id, name)
        values
        (#{id}, #{name})
</insert>

This works when I run the application but the unit test gets an error:

org.springframework.jdbc.BadSqlGrammarException: Error selecting key
or setting result to parameter object. Cause:
java.sql.SQLSyntaxErrorException: user lacks privilege or object not
found: DUAL ; bad SQL grammar []; nested exception is
java.sql.SQLSyntaxErrorException: user lacks privilege or object not
found: DUAL

As I understand 'DUAL' is some kind of virtual table in Oracle that stores the sequences and I don't have this in my test database. If I remove the <selectKey>-tag the unit test work (since HSQL can autogenerate ids for columns marked identity) but not the real application. One workaround would be to create separate MyBatis mapper XML files for the unit tests without the <selectKey>-tag but this is undesired since I want to test the real configuration.

Is there a way to create and use a sequence in HSQL as well or maybe some MyBatis workaround for this? Or should I use another database for my unit test like H2?


I use:

  • Spring 3.0.5
  • HSQL 2.2.4
  • MyBatis 3.0.5

UPDATE:

After getting the answer from fredt, here is how I edited my Spring configuration:

Before I defined my data source with:

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

Now I do this:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close">
    <property name="driverClassName" value="org.hsqldb.jdbcDriver" />
    <property name="url" value="jdbc:hsqldb:mem:test;sql.syntax_ora=true" />
    <property name="username" value="sa" />
    <property name="password" value="" />
</bean>

<jdbc:initialize-database data-source="dataSource">
    <jdbc:script location="classpath:test-data/schema.sql" />
    <jdbc:script location="classpath:test-data/data.sql" />
</jdbc:initialize-database>

Also, in schema.sql I need to create the sequences:

CREATE SEQUENCE BASIS_SEQ START WITH 1000 INCREMENT BY 1;
CREATE SEQUENCE OTHER_SEQ START WITH 1000 INCREMENT BY 1;

(if you run this script many times during unit testing, remember to add drop sequence BASIS_SEQ if exists; to top of schema.sql)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

反差帅 2024-12-17 20:50:03

最新的 HSQLDB 提供了广泛的 Oracle 语法兼容性。您只需将 sql.syntax_ora=true 添加到数据库 URL 即可。例如:

jdbc:hsqldb:mem:test;sql.syntax_ora=true

请参阅指南

http://hsqldb.org/doc/2.0/guide/deployment-chapt。 html

http://hsqldb.org/doc/2.0/guide/dbproperties-chapt.html

SQL 语法兼容性在新版本的 HSQLDB 中不断扩展,因此最好使用最新的可用版本。

Latest HSQLDB provides extensive Oracle syntax compatibility. All you need is add sql.syntax_ora=true to your database URL. For example:

jdbc:hsqldb:mem:test;sql.syntax_ora=true

See the Guide

http://hsqldb.org/doc/2.0/guide/deployment-chapt.html

http://hsqldb.org/doc/2.0/guide/dbproperties-chapt.html

SQL syntax compatibility is constantly extended in new versions of HSQLDB, so it's best to use the latest available version.

楠木可依 2024-12-17 20:50:03

您仍然可以使用 来使用原来的 4 行配置。只需在 test-data/schema.sql 文件的开头添加以下行:

SET DATABASE SQL SYNTAX ORA TRUE;

这实际上与将 sql.syntax_ora=true 附加到 JDBC URL 相同。

You can still use your original 4 line configuration using <jdbc:embedded-database ...>. Just add following line at the beginning of your test-data/schema.sql file:

SET DATABASE SQL SYNTAX ORA TRUE;

This is effectivelly same as appending sql.syntax_ora=true to your JDBC URL.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文