如何在 H2 数据库上管理 XmlType

Posted

技术标签:

【中文标题】如何在 H2 数据库上管理 XmlType【英文标题】:How to manage XmlType on H2 database 【发布时间】:2011-04-14 09:33:54 【问题描述】:

我使用 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 用于非测试环境

【问题讨论】:

【参考方案1】:

我添加了直接链接到的代码 在生产中测试目的 代码...

在某种程度上,是的,因为您使用 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 也是不稳定的。

【讨论】:

【参考方案2】:
public class Oracle10gDialectWithXMLType extends Oracle10gDialect 
    public Oracle10gDialectWithXMLType() 
        registerHibernateType(XMLType._SQL_TYPECODE, "XMLTYPE");
        registerColumnType(XMLType._SQL_TYPECODE, "XMLTYPE");
    

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

【讨论】:

以上是关于如何在 H2 数据库上管理 XmlType的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 PL SQL 函数从 xmltype 数据生成 xml 报告

如何在 Oracle 中通过 xmltype 解析 XML

如何按属性从 XMLTYPE 字段中提取数据?

初识Oracle的XMLType

如何使用 java.sql 包中的 rs.getSQLXML() 函数从 Oracle 数据库中获取 XMLType 列?

如何在 oracle XMLTYPE XMLTABLE 中支持 1 级路径目录