一、spring、hibernate整合
Spring中不但可以選擇SpringJDBC作為持久化技術,還可以選擇Hibernate、iBatis、JPA、JDO等多種類型的持久化技術。Spring提供了方便的模板類對原ORM進行簡化封裝。讓我們先回憶一下單獨使用Hibernate時的過程,我們需要編寫好一個對象關系的映射文件命名形式如xxx.hbm.xml,然后通過Hibernate的配置文件hibernate.cfg.xml 將所有的xxx.hbm.xml 映射文件組裝起來,最后通過兩行經典的代碼得到SessionFactory的實例,如
Configuration cfg = new Configuration().configure("hiberante.cfg.xml");
如果使用注解的話使用AnnotationConfiguration對象,現在Spring為創建SessionFactory提供了一個好用的FactoryBean工廠類:org.springframework.orm.hibernate3.LocalSessionFactoryBean,通過配置一些必要的屬性,即可獲取一個SessionFactoryBean。
1.使用HibernateTemplate
Hibernate.cfg.xml文件中配置了數據源、對象關聯映射文件以及Hibernate控制屬性信息。因此集成到spring中以后要把該文件中內容都拿過來如下:
<context:componet-scan base-package="com.demo" />
< bean id ="dataSource" class ="org.apache.commons.dbcp.BasicDataSource" destroy-method ="close" >
< property name ="driverClassName" value ="${jdbc.driverClassName}" />
< property name ="url" value ="${jdbc.url}" />
< property name ="username" value ="${jdbc.username}" />
< property name ="password" value ="${jdbc.password}" />
</ bean >
< bean id ="sessionFactory" class ="org.springframework.org.hiberante3.LocalSessionFactoryBean" >
< property name ="dataSource" ref ="dataSource" />
< property name ="mappingResources" >
< list >
< value >com.demo.hibernate.domain/xxx.hbm.xml </ value >
</ list >
</ property >
< property name ="hiberanteProperties" >
< props >
< prop key ="hibernate.dialect" >org.hibernate.dialect.MySQLDialect </ prop >
< prop key ="hibernate.show_sql" >true </ prop >
</ props >
</ property >
</ bean >
< bean id ="hiberanteTemplate" class ="org.springframework.orm.hiberante3.HibernateTemplate" >
< property name ="sessionFactory" ref ="sessionFactory" />
</ bean >
< bean id ="transactionManager" class ="org.springframework.orm.hibernate3.HibernateTransactionManager" >
< property name ="sessionFactory" ref ="sessionFactory" />
</ bean >
< tx:annotation-driven transaction-manager ="transactionManager" />
如上面的配置所示,基於模板類使用hibernate比較簡單,spring提供了使用模板的支持類HibernateDaoSupport類,並通過getHibernateTemplate()方法向子類開放模板類實例的調用。如果不想在每個dao里面都加上HibernateTemplate,可以將其放在一個BaseDao里面,然后通過擴展該類創建一個使用HibernateTemplate的Dao,使用時直接getHibernateTemplate().op(obj) 就可以了。也可以將我們自己的Dao實現直接繼承HibernateDaoSupport類同時實現Dao接口,該方式也很簡單。剩下的就和單獨使用Hibernate區別很小了。
對於lob類型的數據,我們還需要在Spring配置文件重定一個Lob數據處理器,讓SessionFactory擁有處理Lob數據的能力。在SessionFactory里引用該bean:
<bean id="lobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler" lazy-init="true" />
2.使用原生Hibernate API
我們可以通過注入SessionFactory 直接通過getCurrentSession()能夠獲取和當前線程綁定的Session。Hibernate自身具備了獲取和事務線程綁定的Session對象的功能,這與在Spring的HibernateTemplate中使用和事務綁定的Session相同。因此使用原生的API,同樣和spring和事務管理器一起工作。和使用template不同的是原生API拋出的異常是Hibernate異常。
3.使用注解
Hibernate通過AnnotationConfiguration的addAnnotatedClass和addPackage方法加載使用JPA注解的實體類,獲取映射的元數據信息,並在此基礎上創建SessionFactory實例。spring專門提供了一個配套的AnnotationSessionFactoryBean,用以創建基於JPA注解的SessionFactory,該類擴展了LocalSessionFactoryBean類,增強的功能是可以根據實體類的注解獲取ORM的配置信息。也允許混合使用XML配置和注解配置對象關系映射,Hibernate內部自動整合這些元數據信息,並不會產生沖突。
此外,Spring以防Web層訪問Service層延遲加載的對象,專門提供了一個OpenSessionInViewFilter過濾器,它的主要功能是使每個請求過程綁定一個Hibernate Session,即使最初的事務已經完成了,也可以在Web層進行延遲加載的操作。OpenSessionInViewFilter過濾器將HibernateSession綁定到請求線程中,它將自動被Spring的事務管理器探測到,因此其使用與使用HibernateTransactionManager或JtaTransactionManager進行事務管理的環境,也可以用於非只讀事務的數據操作中。
二、spring集成ibatis/mybatis
ibatis的后續版本改名叫mybatis,現在兩者都被大家經常使用。兩者的最大不同個人感覺是mybatis提供了接口綁定,你不需要再去實現Dao接口,而直接可在Service層調用,將注意力集中在映射文件上即可。ibatis的核心類是SqlMapClient,XmlSqlMapClientFactoryBean通過讀取文件中的sqlMapConfig(當然包括很多的sqlMap),構建一個SqlMapClient,其通過sqlMap來執行映射的每個SQL語句;mybatis的核心類是SqlSessionFactory,SqlSessionFactoryBuilder讀取配置文件(或注解)創建一個SqlSessionFactory,其通過SqlSession來執行已經映射的SQL語句。下面是兩者和spring集成的配置:
1.Ibatis需要自己在單獨注入各個DAO文件,如
< property name ="sqlMapClient" ref ="sqlMapClient" />
</ bean >
< bean id ="yyyDao" class = "com.demo.ibatis.dao.impl.yyyDaoImpl" >
< property name ="sqlMapClient" ref ="sqlMapClient" />
</ bean >
< bean id ="zzzDao" class = "com.demo.ibatis.dao.impl.zzzDaoImpl" >
< property name ="sqlMapClient" ref ="sqlMapClient" />
</ bean >
在spring-prop.xml文件中配置sqlMapClient,如
< bean id = "sqlMapClient" class = "org.springframework.orm.ibatis.SqlMapClientFactoryBean" >
< property name ="configLocation" value = "classpath:ibatis/ibatis-config.xml" />
< property name ="dataSource" ref ="clopsDataSource" />
< property name ="lobHandler" ref ="lobHandler" />
</ bean >
如property指定的configuration的位置一樣,要有 < sqlMapConfig >的配置,並將各個xml文件引入進來,ibatis-config.xml如下:
< sqlMapConfig >
< settings useStatementNamespaces = "true" cacheModelsEnabled = "true" enhancementEnabled = "true"
lazyLoadingEnabled = "true" maxRequests = "32" maxSessions = "10" maxTransactions = "5" />
< sqlMap resource ="ibatis/xxx.xml" />
< sqlMap resource ="ibatis/yyy.xml" />
< sqlMap resource ="ibatis/zzz.xml" />
......
</ sqlMapConfig >
2.而在Mybatis中則不需要這樣配置:
在spring-prop中指定sqlSessionFactory,如,
<bean id= "sqlSessionFactory" class= "org.mybatis.spring.SqlSessionFactoryBean" >
<property name ="dataSource" ref="dataSource" />
<property name ="typeAliasesPackage" value= "com.demo.mybatis.model" />
<property name ="mapperLocations" value= "classpath*:mapper/**/*.xml" />
</bean >
<bean id ="sqlSession" class= "org.mybatis.spring.SqlSessionTemplate" >
<constructor-arg index ="0" ref="sqlSessionFactory" />
<constructor-arg index ="1" value="BATCH" />
</bean >
<bean class ="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name ="basePackage" value= "com.demo.mybatis.dao" />
<property name ="sqlSessionTemplate" ref= "sqlSession" />
</bean >
其中各種mapper文件在由mapperLocations指定。mybatis相對簡單些。
使用時類似上面的Hibernate,ibatis可將sqlMapClientTemplate直接注入,或者繼承SqlMapClientDaoSupport類同時實現Dao接口,通過getSqlMapClientTemplate()方法或者sqlMapClient進行操作。注意上述ibatis直接注入的是sqlMapClient,其實sqlMapClientTemplate的構造函數引入了一個sqlMapClient,其使用的方法均來自sqlMapClient。
Mybatis與spring的集成因對數據處理的不同方式而不同,上述方式是采用MapperScannerConfigurer的處理方式,且采用了注解形式,還可以使用MapperFactoryBean、SqlSession、SqlSessionDaoSupport的數據處理方式,使用后兩種方式時需要自己實現Dao接口,而對於MapperFactoryBean其直接指定Dao接口mapperInterface。