2011-04-14 40 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也不穩定。