心的方向

          新的征途......
          posts - 75,comments - 19,trackbacks - 0

          Struts+Spring+Hibernate實現上傳下載(二)

          轉自:http://lihaiyan.javaeye.com/blog/127795

          數據持久層

            1、領域對象及映射文件

            您可以使用Hibernate Middlegen、HIbernate Tools、Hibernate Syhchronizer等工具或手工的方式,編寫Hibernate的領域對象和映射文件。其中對應T_FILE表的領域對象Tfile.java為:

            代碼 1 領域對象Tfile

          1. package sshfile.model;
          2. public class Tfile
          3.{
          4. private String fileId;
          5. private String fileName;
          6. private byte[] fileContent;
          7. private String remark;
          8. …//getter and setter
          9. }

            特別需要注意的是:數據庫表為Blob類型的字段在Tfile中的fileContent類型為byte[]。Tfile的Hibernate映射文件Tfile.hbm.xml放在Tfile .java類文件的相同目錄下:

            代碼 2 領域對象映射文件

          1. <?xml version="1.0"?>
          2. <!DOCTYPE hibernate-mapping PUBLIC
          3. "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
          4. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
          5. <hibernate-mapping>
          6. <class name="sshfile.model.Tfile" table="T_FILE">
          7. <id name="fileId" type="java.lang.String" column="FILE_ID">
          8. <generator class="uuid.hex"/>
          9. </id>
          10. <property name="fileContent"
          11. type="org.springframework.orm.hibernate3.support.BlobByteArrayType"
          12. column="FILE_CONTENT" lazy="true"/>
          13. …//其它一般字段的映射
          14. </class>
          15. </hibernate-mapping>

            fileContent字段映射為Spring所提供的BlobByteArrayType類型,BlobByteArrayType是用戶自定義的數據類型,它實現了Hibernate 的org.hibernate.usertype.UserType接口。BlobByteArrayType使用從sessionFactory獲取的Lob操作句柄lobHandler將byte[]的數據保存到Blob數據庫字段中。這樣,我們就再沒有必要通過硬編碼的方式,先insert然后再update來完成Blob類型數據的持久化,這個原來難伺候的老爺終于被平民化了。關于lobHandler的配置請見本文后面的內容。

            此外lazy="true"說明地返回整個Tfile對象時,并不返回fileContent這個字段的數據,只有在顯式調用tfile.getFileContent()方法時才真正從數據庫中獲取fileContent的數據。這是Hibernate3引入的新特性,對于包含重量級大數據的表字段,這種抽取方式提高了對大字段操作的靈活性,否則加載Tfile對象的結果集時如果總是返回fileContent,這種批量的數據抽取將可以引起數據庫的"洪泛效應"。

            2、DAO編寫和配置

            Spring強調面向接口編程,所以我們將所有對Tfile的數據操作的方法定義在TfileDAO接口中,這些接口方法分別是:

            ·findByFildId(String fileId)

            ·save(Tfile tfile)

            ·List findAll()

            TfileDAOHibernate提供了對TfileDAO接口基于Hibernate的實現,如代碼 3所示:

            代碼 3 基于Hibernate 的fileDAO實現類

          1. package sshfile.dao;
          2.
          3. import sshfile.model.*;
          4. import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
          5. import java.util.List;
          6.
          7. public class TfileDAOHibernate
          8. extends HibernateDaoSupport implements TfileDAO
          9. {
          10. public Tfile findByFildId(String fileId)
          11. {
          12. return (Tfile) getHibernateTemplate().get(Tfile.class, fileId);
          13. }
          14. public void save(Tfile tfile)
          15. {
          16. getHibernateTemplate().save(tfile);
          17. getHibernateTemplate().flush();
          18. }
          19. public List findAll()
          20. {
          21. return getHibernateTemplate().loadAll(Tfile.class);
          22. }
          23. }

            TfileDAOHibernate通過擴展Spring提供的Hibernate支持類HibernateDaoSupport而建立,HibernateDaoSupport封裝了HibernateTemplate,而HibernateTemplate封裝了Hibernate所提供幾乎所有的的數據操作方法,如execute(HibernateCallback action),load(Class entityClass, Serializable id),save(final Object entity)等等。

            所以我們的DAO只需要簡單地調用父類的HibernateTemplate就可以完成幾乎所有的數據庫操作了。

            由于Spring通過代理Hibernate完成數據層的操作,所以原Hibernate的配置文件hibernate.cfg.xml的信息也轉移到Spring的配置文件中:

            代碼 4 Spring中有關Hibernate的配置信息

          1. <beans>
          2. <!-- 數據源的配置 //-->
          3. <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
          4. destroy-method="close">
          5. <property name="driverClassName" value="http://www.zhmy.com/oracle.jdbc.driver.OracleDriver"/>
          6. <property name="url" value="jdbc:oracle:thin:@localhost:1521:ora9i"/>
          7. <property name="username" value="test"/>
          8. <property name="password" value="test"/>
          9. </bean>
          10. <!-- Hibernate會話工廠配置 //-->
          11. <bean id="sessionFactory"
          12. class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
          13. <property name="dataSource" ref="dataSource"/>
          14. <property name="mappingDirectoryLocations">
          15. <list>
          16. <value>classpath:/sshfile/model</value>
          17. </list>
          18. </property>
          19. <property name="hibernateProperties">
          20. <props>
          21. <prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop>
          22. <prop key="hibernate.cglib.use_reflection_optimizer">true</prop>
          23. </props>
          24. </property>
          25. </bean>
          26. <!-- Hibernate 模板//-->
          27. <bean id="hibernateTemplate"
          28. class="org.springframework.orm.hibernate3.HibernateTemplate">
          29. <property name="sessionFactory" ref="sessionFactory"/>
          30. </bean>
          31. <!--DAO配置 //-->
          32. <bean id="tfileDAO" class="sshfile.dao.TfileDAOHibernate">
          33. <property name="hibernateTemplate" ref="hibernateTemplate" />
          34. </bean>
          35. …
          36. </beans>

            第3~9行定義了一個數據源,其實現類是apache的BasicDataSource,第11~25行定義了Hibernate的會話工廠,會話工廠類用Spring提供的LocalSessionFactoryBean維護,它注入了數據源和資源映射文件,此外還通過一些鍵值對設置了Hibernate所需的屬性。

            其中第16行通過類路徑的映射方式,將sshfile.model類包目錄下的所有領域對象的映射文件裝載進來,在本文的例子里,它將裝載進Tfile.hbm.xml映射文件。如果有多個映射文件需要聲明,使用類路徑映射方式顯然比直接單獨指定映射文件名的方式要簡便。

            第27~30行定義了Spring代理Hibernate數據操作的HibernateTemplate模板,而第32~34行將該模板注入到tfileDAO中。

            需要指定的是Spring 1.2.5提供了兩套Hibernate的支持包,其中Hibernate 2相關的封裝類位于org.springframework.orm.hibernate2.*包中,而Hibernate 3.0的封裝類位于org.springframework.orm.hibernate3.*包中,需要根據您所選用Hibernate版本進行正確選擇。

            3、Lob字段處理的配置

            我們前面已經指出Oracle的Lob字段和一般類型的字段在操作上有一個明顯的區別--那就是你必須首先通過Oracle的empty_blob()/empty_clob()初始化Lob字段,然后獲取該字段的引用,通過這個引用更改其值。所以要完成對Lob字段的操作,Hibernate必須執行兩步數據庫訪問操作,先Insert再Update。

            使用BlobByteArrayType字段類型后,為什么我們就可以象一般的字段類型一樣操作Blob字段呢?可以確定的一點是:BlobByteArrayType不可能逾越Blob天生的操作方式,原來是BlobByteArrayType數據類型本身具體數據訪問的功能,它通過LobHandler將兩次數據訪問的動作隱藏起來,使Blob字段的操作在表現上和其他一般字段業類型無異,所以LobHandler即是那個"苦了我一個,幸福十億人"的那位幕后英雄。

            LobHandler必須注入到Hibernate會話工廠sessionFactory中,因為sessionFactory負責產生與數據庫交互的Session。LobHandler的配置如代碼 5所示:

            代碼 5 Lob字段的處理句柄配置

          1. <beans>
          2. …
          3. <bean id="nativeJdbcExtractor"
          4. class="org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor"
          5. lazy-init="true"/>
          6. <bean id="lobHandler"
          7. class="org.springframework.jdbc.support.lob.OracleLobHandler" lazy-init="true">
          8. <property name="nativeJdbcExtractor">
          9. <ref local="nativeJdbcExtractor"/>
          10. </property>
          11. </bean>
          12. …
          13. </beans>

            首先,必須定義一個能夠從連接池中抽取出本地數據庫JDBC對象(如OracleConnection,OracleResultSet等)的抽取器:nativeJdbcExtractor,這樣才可以執行一些特定數據庫的操作。對于那些僅封裝了Connection而未包括Statement的簡單數據連接池,SimpleNativeJdbcExtractor是效率最高的抽取器實現類,但具體到apache的BasicDataSource連接池,它封裝了所有JDBC的對象,這時就需要使用CommonsDbcpNativeJdbcExtractor了。Spring針對幾個著名的Web服務器的數據源提供了相應的JDBC抽取器:

            ·WebLogic:WebLogicNativeJdbcExtractor

            ·WebSphere:WebSphereNativeJdbcExtractor

            ·JBoss:JBossNativeJdbcExtractor

            在定義了JDBC抽取器后,再定義lobHandler。Spring 1.2.5提供了兩個lobHandler:

            ·DefaultLobHandler:適用于大部分的數據庫,如SqlServer,MySQL,對Oracle 10g也適用,但不適用于Oracle 9i(看來Oracle 9i確實是個怪胎,誰叫Oracle 公司自己都說Oracle 9i是一個過渡性的產品呢)。

            ·OracleLobHandler:適用于Oracle 9i和Oracle 10g。

            由于我們的數據庫是Oracle9i,所以使用OracleLobHandler。

            在配置完LobHandler后, 還需要將其注入到sessionFactory的Bean中,下面是調用后的sessionFactory Bean的配置:

            代碼 6 將lobHandler注入到sessionFactory中的配置

          1. <beans>
          2. …
          3. <bean id="sessionFactory"
          4. class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
          5. <property name="dataSource" ref="dataSource"/>
          6. <!-- 為處理Blob類型字段的句柄聲明 //-->
          7. <property name="lobHandler" ref="lobHandler"/>
          8. …
          9. </bean>
          10. …
          11. </beans>

            如第7所示,通過sessionFactory的lobHandler屬性進行注入。


          posted on 2008-04-10 14:55 阿偉 閱讀(292) 評論(0)  編輯  收藏 所屬分類: 框架整合
          主站蜘蛛池模板: 旌德县| 朝阳市| 晋中市| 万州区| 牙克石市| 揭阳市| 岳池县| 卢氏县| 望江县| 鞍山市| 新闻| 泸定县| 肥城市| 麦盖提县| 涪陵区| 沿河| 诸城市| 拉孜县| 齐河县| 海晏县| 滨海县| 阜宁县| 丹江口市| 东乡| 启东市| 天峨县| 秀山| 涿州市| 长春市| 漳平市| 逊克县| 社旗县| 福州市| 娄底市| 南丰县| 泗洪县| 富川| 金沙县| 仙游县| 望都县| 武隆县|