如何在 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
。
方法nullSafeSet
和nullSafeGet
在这里定义。
现在,我想为我的测试使用 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 报告
如何使用 java.sql 包中的 rs.getSQLXML() 函数从 Oracle 数据库中获取 XMLType 列?