国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
利用HSQLDB 進(jìn)行Hibernate單元測試
利用HSQLDB 進(jìn)行Hibernate單元測試

時間:2005-07-15
作者:Alex Vollmer
瀏覽次數(shù): 677
本文關(guān)鍵字:Hibernate
文章工具
 推薦給朋友
 打印文章

動機(jī)

  曾經(jīng)使用許多方法在數(shù)據(jù)庫和目標(biāo)代碼之間傳輸數(shù)據(jù)。從手動編碼的SQL到JDO,然后再到EJB,我從未找到一種特別喜歡的方法。自從采用測試驅(qū)動開發(fā)(TDD)作為指導(dǎo)原則以來,這種不滿情緒變得更加強(qiáng)烈。

  單元測試的障礙應(yīng)盡可能少。在關(guān)系數(shù)據(jù)庫中,障礙的范圍從外部依賴(數(shù)據(jù)庫在運(yùn)行嗎?)到保持關(guān)系模型和對象模型同步的速度。由于這些原因,保持?jǐn)?shù)據(jù)庫訪問代碼與核心對象模型分離且無需涉及真實(shí)數(shù)據(jù)庫而進(jìn)行盡可能多的測試是很重要的。

  通常這會導(dǎo)致我們進(jìn)入下面兩種模式之一。第一種是具體化所有訪問域?qū)ο蟮臄?shù)據(jù)以及數(shù)據(jù)與單獨(dú)類或接口之間的關(guān)系。這就是典型的能夠檢索、編輯、刪除和添加域?qū)嶓w的數(shù)據(jù)存儲對象。這在單元測試中是最容易模擬出來的,但趨向于把域模型對象作為不帶有任何關(guān)系行為的純數(shù)據(jù)對象。直接從父對象訪問子記錄是最理想的,而不是將父對象處理為第三方類來決定子記錄。

  其他方法已經(jīng)使訪問接口的域?qū)ο筮M(jìn)入數(shù)據(jù)映射層(一種la Martin Fowler的數(shù)據(jù)映象模式)。這具有推動域模型中的對象關(guān)系的優(yōu)點(diǎn),在域模型中,對象關(guān)系型接口只需表達(dá)一次即可。使用域模型的類不支持持久性機(jī)制,因?yàn)樗旧韮?nèi)在化到域模型中。這使代碼集中在設(shè)法解決的業(yè)務(wù)問題,而很少關(guān)注對象關(guān)系型映射機(jī)制。

  我的當(dāng)前項(xiàng)目涉及到處理大量的棒球統(tǒng)計數(shù)據(jù),并使用這些數(shù)據(jù)進(jìn)行模擬。因?yàn)閿?shù)據(jù)已經(jīng)在關(guān)系數(shù)據(jù)庫中,所以對于我來說,有機(jī)會開發(fā)Hibernate對象關(guān)系型映射系統(tǒng)。我曾對Hibernate有很深刻的印象,但我遇到的一個問題是,在使用Hibernate進(jìn)行單元測試的數(shù)據(jù)映射時,設(shè)法插入一個間接層。該附加層非常脆弱,編寫起來感到非常困難。實(shí)際部署版本簡單地通過了特定于Hibernate的實(shí)現(xiàn)。更壞的情況是,模擬版本比真正的“產(chǎn)品級”版本更復(fù)雜,只因?yàn)槟M版本里沒有基本對象存儲器和帶有Hibernate的映射。

  我也使用很多復(fù)雜的Hibernate查詢,想要對應(yīng)用程序的重要部分進(jìn)行單元測試。然而,對活動的數(shù)據(jù)庫進(jìn)行測試不是好主意,因?yàn)檫@幾乎總是產(chǎn)生維護(hù)問題。另外,由于測試最好互相獨(dú)立,在測試上下文數(shù)據(jù)中使用相同的主鍵意味著必須在每次測試前創(chuàng)建代碼來清理數(shù)據(jù)庫,當(dāng)涉及到大量關(guān)系時就成為一個實(shí)際問題。

  通過使用HSQLDB和Hibernate強(qiáng)大的模式生成工具,能夠?qū)?yīng)用程序映射層進(jìn)行單元測試,并在對象查詢中找到不計其數(shù)的bug,這在以前手工測試時是做不到的。利用下面的技術(shù)概述,可以在開發(fā)過程中對整個應(yīng)用程序進(jìn)行測試,并且在測試有效區(qū)域內(nèi)沒有損害。

設(shè)置HSQLDB

  以前使用HSQLDB 1.7.3.0 版。為了使用數(shù)據(jù)庫的內(nèi)存版本,需要激活org.hsqldb.jdbcDriver的靜態(tài)加載程序。當(dāng)獲得JDBC連接時,就可以使用JDBC url例如jdbc:hspldb:mem:yourdb,這里’yourdb’就是想要使用的內(nèi)存數(shù)據(jù)庫的名稱。

  因?yàn)槭褂肏ibernate (3.0 beta 4),所以我?guī)缀鯚o需接觸實(shí)際活動的JDBC對象。相反,我可以讓Hibernate完成很多繁重的任務(wù),包括從Hibernate映射文件中自動創(chuàng)建數(shù)據(jù)庫模式。因?yàn)镠ibernate創(chuàng)建自身專有的連接池,所以它會基于TestSchema類中的配置代碼自動加載HSQLDB JDBC驅(qū)動程序。下面就是該類的靜態(tài)的初始化程序。

public class TestSchema {    static {        Configuration config = new Configuration().            setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect").            setProperty("hibernate.connection.driver_class", "org.hsqldb.jdbcDriver").            setProperty("hibernate.connection.url", "jdbc:hsqldb:mem:baseball").            setProperty("hibernate.connection.username", "sa").            setProperty("hibernate.connection.password", "").            setProperty("hibernate.connection.pool_size", "1").            setProperty("hibernate.connection.autocommit", "true").            setProperty("hibernate.cache.provider_class", "org.hibernate.cache.HashtableCacheProvider").            setProperty("hibernate.hbm2ddl.auto", "create-drop").            setProperty("hibernate.show_sql", "true").            addClass(Player.class).            addClass(BattingStint.class).            addClass(FieldingStint.class).            addClass(PitchingStint.class);        HibernateUtil.setSessionFactory(config.buildSessionFactory());    }

  Hibernate提供了許多不同的方式來配置該框架,包括程序方面的配置。上述代碼設(shè)置了連接池。注意,使用HSQLDB的內(nèi)存數(shù)據(jù)庫需要用戶名‘sa’。還樣要確保指定一個空格作為口令。為了啟動Hibernate的自動模式生成功能,需設(shè)置hibernate.hbm2ddl.auto屬性為’creat-drop’。

  實(shí)際測試 我的項(xiàng)目是處理將大量的棒球數(shù)據(jù),所以我添加了四個進(jìn)行映射的類(Player、PintchingStint、,BattingSint和FieldStint)。最后創(chuàng)建Hibernate的會話工廠,并將其插入HibernateUtil類,該類只為Hibernate會話的整個應(yīng)用程序提供一個訪問方法。HibernateUtil的代碼如下:

import org.hibernate.*;import org.hibernate.cfg.Configuration;public class HibernateUtil {    private static SessionFactory factory;    public static synchronized Session getSession() {        if (factory == null) {            factory = new Configuration().configure().buildSessionFactory();        }        return factory.openSession();    }    public static void setSessionFactory(SessionFactory factory) {        HibernateUtil.factory = factory;    }}


  因?yàn)樗写a(經(jīng)過單元測試的產(chǎn)品級代碼)都是從HibernateUtil獲取Hibernate會話,所以能在同一個位置對其進(jìn)行配置。為了對代碼的第一位進(jìn)行單元測試而訪問TestSchema類將會激活靜態(tài)初始化程序,該程序?qū)惭bHibernate并且將測試SessionFactory插入到HibernateUtil中。對于產(chǎn)品級代碼,可以使用標(biāo)準(zhǔn)hibernate.cfg.xml配置機(jī)制來初始化 SessionFactory。
  那么單元測試中的外部特征是什么?下面的測試代碼片段是用來檢查邏輯的,決定運(yùn)動員在棒球聯(lián)盟比賽中是哪個位置的人選:

    public void testGetEligiblePositions() throws Exception {        Player player = new Player("playerId");        TestSchema.addPlayer(player);        FieldingStint stint1 = new FieldingStint("playerId", 2004, "SEA", Position.CATCHER);        stint1.setGames(20);        TestSchema.addFieldingStint(stint1);        Set<Position> positions = player.getEligiblePositions(2004);        assertEquals(1, positions.size());        assertTrue(positions.contains(Position.CATCHER));    }


  第一次創(chuàng)建新Player實(shí)例并通過addPlayer()方法添加到TestSchema中。必須首先完成此步驟,因?yàn)镕idldStint類和Player類之間有外鍵關(guān)系。如果不首先添加該實(shí)例,在設(shè)法添加FieldingStint時將會出現(xiàn)外鍵約束違例。一旦測試上下文就位,就可以測試getEligiblePositions()方法來檢索校正數(shù)據(jù)。下面是在TsetSchema中addPlayer()方法的代碼。您將注意到使用Hibernate而不是bare-metal JDBC代碼:

    public static void addPlayer(Player player) {        if (player.getPlayerId() == null) {            throw new IllegalArgumentException("No primary key specified");        }        Session session = HibernateUtil.getSession();        Transaction transaction = session.beginTransaction();        try {            session.save(player, player.getPlayerId());            transaction.commit();        }        finally {            session.close();        }    }


  在單元測試中最重要的就是要保持測試實(shí)例是獨(dú)立的。因?yàn)樵摲椒ㄈ匀簧婕皵?shù)據(jù)庫,所以需要一種方法在每個測試實(shí)例之前清理數(shù)據(jù)庫。在我的數(shù)據(jù)庫架構(gòu)中有四個表,所以我在TestSchemaz上編寫了reset()方法,該方法從使用JDBC的表中刪除所有行。注意,因?yàn)镠SQLDB能識別外鍵,刪除表的順序是很重要的,下面是代碼:

    public static void reset() throws SchemaException {        Session session = HibernateUtil.getSession();        try {            Connection connection = session.connection();            try {                Statement statement = connection.createStatement();                try {                    statement.executeUpdate("delete from Batting");                    statement.executeUpdate("delete from Fielding");                    statement.executeUpdate("delete from Pitching");                    statement.executeUpdate("delete from Player");                    connection.commit();                }                finally {                    statement.close();                }            }            catch (HibernateException e) {                connection.rollback();                throw new SchemaException(e);            }            catch (SQLException e) {                connection.rollback();                throw new SchemaException(e);            }        }        catch (SQLException e) {            throw new SchemaException(e);        }        finally {            session.close();        }    }


  當(dāng)確定在Hibernate 3.0中進(jìn)行大量刪除操作時,應(yīng)該能從應(yīng)用程序中刪除直接JDBC的最后一位。到此時為止,必須獲取數(shù)據(jù)庫連接并向數(shù)據(jù)庫直接提交SQL。 在確保沒有關(guān)閉連接的情況下,為了釋放資源,只關(guān)閉會話就足夠了。出于手工編寫許多JCBC代碼來進(jìn)行開發(fā)的習(xí)慣,第一個版本關(guān)閉了JDBC連接。因?yàn)橥ㄟ^配置Hibernate創(chuàng)建的連接池只帶有一個鏈接,在第一個之后就完全破壞了測試。一定要注意這種情況! 既然在測試類運(yùn)行時(設(shè)想運(yùn)行所有的測試實(shí)例)不能確定數(shù)據(jù)庫的狀態(tài),應(yīng)該在setUp()方法中包含數(shù)據(jù)庫清除,如下所示:

    public void setUp() throws Exception {        TestSchema.reset();    }
結(jié)束語
  在使用像Hibernate這種復(fù)雜的O/R映射程序時,必須能夠測試實(shí)際存在(real-live)的RDBMS,而不會發(fā)生任何針對已部署數(shù)據(jù)庫的爭論。雖然Hibernate有內(nèi)置模式生成工具,讓此類測試特別簡單,但是在這里展示的例子并不排除Hibernate,并且可能與JDO或TopLink一起運(yùn)行。使用上面描述的設(shè)置,您不必離開舒適的IDE環(huán)境,但仍然可以對代碼進(jìn)行大量測試。

原文出處
http://www.theserverside.com/articles/article.tss?l=UnitTesting

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
技術(shù)文章-對DAO編寫單元測試
開源面向?qū)ο髷?shù)據(jù)庫 db4o 之旅: 初識 db4o
iBATIS中的單元測試
maven入門介紹
hibernate官方入門教程 (轉(zhuǎn)載)
初探Liferay Enterpriese Portal的數(shù)據(jù)類型持久化
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服