2011-04-14 41 views
1

我使用H2数据库进行单元测试。 在我的申请,我有这样的定义称为FooXml一个实体对象:如何管理H2数据库上的XmlType

@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不支持The 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数据库依赖项。

问题

  • 是它来解决我的问题,最好的方法,还是有这样做的更好的办法?
  • 有没有办法让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数据库v1.3.153,JUnit的4.8.1,Java 1.6的, Hibernate 3.2.2,Oracle 10g用于非测试环境

回答

2

我补充一点,是直接关系到 测试目的生产 代码代码...

在某种程度上说,是的,因为你用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") - 一个基本比较字符串而不是Class对象。当然,这不是编译时安全的,另一方面,H2可能会在未来返回不同的连接类,因此JdbcConnection也不稳定。