2

我使用 H2 数据库进行单元测试。在我的应用程序中,我有一个名为FooXml定义的实体对象:

@Entity
@Table(name = "T_FOOXML")
@SequenceGenerator(allocationSize = 1, name = "S_FOOXML", sequenceName = "S_FOOXML")
@NamedQueries( ... )
@Cache(usage = CacheConcurrencyStrategy.NONE)
public class FooXml implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "S_FOOXML")
    @Column(name = "FOOXML_ID")
    private Integer id;

    @Type(type = "my.app.common.HibernateXMLType")
    @Column(name = "FOOXML_CONTENT")
    @Basic(fetch = FetchType.LAZY)
    private String xmlContent;

    ...

}

因此,为了从数据库中读取/写入 XML 内容,我创建了自己的 XMLType my.app.common.HibernateXMLType,它实现了org.hibernate.usertype.UserType. 方法nullSafeSetnullSafeGet在那里定义。

现在,我想为我的测试使用 H2 内存数据库,并且一些测试正在使用这个FooXml类。由于 H2 不支持 Oracle XmlType,我必须自定义我的my.app.common.HibernateXMLType. 例如,我添加了该部分:

public void nullSafeSet(PreparedStatement st, Object value, int index) throws HibernateException, SQLException {
    ...
    // Case where H2 Database is used as the dataSource...
    if (st.getConnection() instanceof org.h2.jdbc.JdbcConnection) {
        // Set the XML as a String...
        st.setObject(index, (String) value);
    } else {
        // Case of "normal" behavior (outside tests context)
        ...
    }
}

我对这种方法有几个担忧:

  • 我在应用程序的生产代码中添加了与测试目的直接相关的代码(即不在测试代码中);
  • 由于此类依赖于org.h2.jdbc.JdbcConnection,因此我必须在我的 WAR 包中添加 h2-database 依赖项。

问题

  • 这是解决我的问题的最佳方法,还是有更好的方法?
  • 有没有办法告诉 Hibernate 使用另一种类型(my.app.common.HibernateXMLTypeForH2而不是my.app.common.HibernateXMLType)进行测试?

ps:在H2数据库中创建我的表的脚本如下:

create table T_FOO_XML (
    FOOXML_ID NUMBER(9, 0) not null,
    FOOXML_CONTENT CLOB(400000)
);

技术细节:H2 Database v1.3.153、JUnit 4.8.1、Java 1.6、Hibernate 3.2.2、Oracle 10g 用于非测试环境

4

2 回答 2

3

我在生产代码中添加了与测试目的直接相关的代码......

在某种程度上,是的,因为您使用 H2 进行测试。但是,您可能会争辩说您使您的应用程序更加独立于数据库,并且仅使用 H2 进行测试只是一个巧合。稍后,您可以使用 H2 作为产品试用版附带的数据库。或者您可以稍后支持除 Oracle 和 H2 之外的其他数据库。

h2-数据库依赖

为了避免对 H2 的编译时依赖,您可以使用:

String url = st.getConnection().getMetaData().getURL();
boolean isH2 = url.startsWith("jdbc:h2:");
if (isH2) {
    ...
}

还有其他方法,例如getMetaData().getDatabaseProductName().equals("H2")- 基本上与 String 而不是 Class 对象进行比较。当然,这不是编译时安全的,另一方面,H2 将来可能会返回不同的连接类,因此JdbcConnection也是不稳定的。

于 2011-04-28T07:15:55.623 回答
1
public class Oracle10gDialectWithXMLType extends Oracle10gDialect {
    public Oracle10gDialectWithXMLType() {
        registerHibernateType(XMLType._SQL_TYPECODE, "XMLTYPE");
        registerColumnType(XMLType._SQL_TYPECODE, "XMLTYPE");
    }
}

并将其添加为属性中的方言。

于 2018-05-04T09:58:28.317 回答