Spring
的持久層封裝
(零雨其蒙原創,轉載請注明)
一、概述
(一)基本概念
1、數據訪問的關鍵技術
???? 我們可以將數據訪問分為兩個部分:一是獲得數據源;二是進行數據庫操作(增刪改查)。
2、獲得數據源的幾種方法
因為只是為了記錄一些關鍵的東西,以實用為主,因此沒有過多的考慮措辭和學術上的嚴謹。這里指的是在Java中怎么能取得和數據源(DataSource)的聯系,方法主要有傳統的在程序中硬編碼和通過XML注入。Spring提供三種XML注入:(1)使用Spring自帶的DriverManagerDataSource;(2)使用DBCP連接池(3)使用Tomcat提供的JNDI。其中(1)可以配合Hibernate、iBatis等ORM一起使用(在XML配置文檔中加入相應的配置段)。
(二)框架圖
XML
注入數據源的三種方式
|
Spring
自帶的DriverManagerDataSource
|
DBCP
連接池
|
Tomcat
的JNDI
|
?
|
數據庫操作的兩種方式
|
Spring
的
JdbcTemplate
|
使用
ORM
工具
|
?
|
(三)何時使用什么
????????? 現在大多數輕量級開發,都采用Hibernate作為持久層解決方案,因此可以作為首選。
二、詳細
(一)數據源注入
1、使用Spring自帶的DriverManagerDataSource??
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
?"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
?? <!
—
設
定dataSource
à
?? <bean id=
”
dataSource
” class=”
org.springframework.jdbc.datasource.DriverManagerDataSource
”>
????? <!
—使用SQL Server
數
據
庫
à
?????? <property name=
”driverClassName”>
????????? <value>com.microsoft.jdbc.sqlserver.SQLServerDriver</value>
?????? </property>
??????? <property name=
”url”>
????????? <value>jdbc:Microsoft:sqlserver://localhost:1433/stdb</value>
?????? </property>
<property name=
”name”>
????????? <value>admin</value>
?????? </property>
<property name=
”msg”>
????????? <value>admin</value>
?????? </property>
??? </bean>
?
??? <!
—設定
transactionManager
à
??? <bean id=
”
transactionManager
”
class=
”
org.springframework.jdbc.datasource.DataSourceTransactionManager
”
>
??????? <property name=
”
dataSource
”
>
??????????? <ref bean=
”
dataSource
”
/>
??????? </property>
??? </bean>
?
?? <!—示例中DAO-->
?? <bean id=
”bookDAO” class=”com.bookDAO”>
??????? <property name=
”dataSource”>
??????????? <ref bean=
”dataSource”/>
??????? </property>
??????? <property name=
”transactionManager”>
??????????? <ref bean=
”transactionManager”>
??????? </property>
?? </bean>
</beans>
?? 紅色部分顯示了所使用的類,就是用它來處理數據庫連接。
2、使用DBCP連接池
??? 要在Spring中使用DBCP連接池,需要引入spring-framework-2.0-ml\lob\jakarta-commons文件夾中的commons-collections.jar、commons-dbcp.jar和commons-pool.jar。
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
?"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
?? <!
—
設
定dataSource
à
?? <bean id=
”
dataSource
” class=”
org.apache.commons.dbcp.BasicDataSource
”>
????? <!
—使用SQL Server
數
據
庫
à
?????? <property name=
”driverClassName”>
????????? <value>com.microsoft.jdbc.sqlserver.SQLServerDriver</value>
?????? </property>
??????? <property name=
”url”>
????????? <value>jdbc:Microsoft:sqlserver://localhost:1433/stdb</value>
?????? </property>
<property name=
”name”>
????????? <value>admin</value>
?????? </property>
<property name=
”msg”>
????????? <value>admin</value>
?????? </property>
??? </bean>
?
??? <!
—設定
transactionManager
à
??? <bean id=
”
transactionManager
”
class=
”
org.springframework.jdbc.datasource.DataSourceTransactionManager
”
>
??????? <property name=
”
dataSource
”
>
??????????? <ref bean=
”
dataSource
”
/>
??????? </property>
??? </bean>
?
?? <!—示例中DAO-->
?? <bean id=
”bookDAO” class=”com.bookDAO”>
??????? <property name=
”dataSource”>
??????????? <ref bean=
”dataSource”/>
??????? </property>
??????? <property name=
”transactionManager”>
??????????? <ref bean=
”transactionManager”>
??????? </property>
?? </bean>
</beans>
?? 紅色部分為不同之處,可以看出,Spring為各種不同的數據源提供了統一的方式,下面看使用Tomcat提供的JNDI,有了一些不同。
3、使用Tomcat提供的JNDI
分兩步,第一步是配置Tomcat的server.xml;第二步是編寫Spring的配置文件。
Tomcat
的server.xml
<Context path=”/demo” reloadable=”true” docBase=”c: \eclipse\workspace\demo” workDir=” c: \eclipse\workspace\demo\work”>
<
Resource
name=”jdbc/opendb” auth=”Container” type=”javax.sql.DataSource” factory=”org.apache.tomcat.dbcp.BasicDataSourceFactory” driverClassName=”com.microsoft.jdbc.sqlserver.SQLServerDriver” url=”jdbc:Microsoft:sqlserver://localhost:1433/stdb”
<!—
設定用戶名-->
name=”admin”
<!—
設定密碼
à
msg=”admin”
<
!--設定最大連接數
à
maxActive=”10000”
<
!--設定最大空閑時間
à
maxldle=”10000”
<
!--設定最大等待時間
à
maxWait=”10000”
removeAbandoned=”true”
removeAbandonedTimeout=”10”
logAbandoned=”true”
/>
</Context>
Spring
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
?"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
?? <!
—
設
定dataSource
à
?? <bean id=
”
dataSource
” class=”
o
rg.springframework.jndi.JndiObjectFactoryBean
>
???
?<property name=”jndiName”>
???????? <value>jdbc/opendb</value>
???
?
/*
以下信息在
server.xml
中已經配置過了,不需要再配置了
?<!
—使用SQL Server
數
據
庫
à
?????? <property name=
”driverClassName”>
????????? <value>com.microsoft.jdbc.sqlserver.SQLServerDriver</value>
?????? </property>
??????? <property name=
”url”>
????????? <value>jdbc:Microsoft:sqlserver://localhost:1433/stdb</value>
?????? </property>
<property name=
”name”>
????????? <value>admin</value>
?????? </property>
<property name=
”msg”>
????????? <value>admin</value>
?????? </property>
*/
??? </bean>
?
?? ?<!
—設定
transactionManager
à
??? <bean id=
”
transactionManager
”
class=
”
org.springframework.jdbc.datasource.DataSourceTransactionManager
”
>
??????? <property name=
”
dataSource
”
>
??????????? <ref bean=
”
dataSource
”
/>
??????? </property>
??? </bean>
?
?? <!—示例中DAO-->
?? <bean id=
”bookDAO” class=”com.bookDAO”>
??????? <property name=
”dataSource”>
??????????? <ref bean=
”dataSource”/>
??????? </property>
??????? <property name=
”transactionManager”>
??????????? <ref bean=
”transactionManager”>
??????? </property>
?? </bean>
</beans>
?? 紅色部分為不同之處,可以看出,使用Tomcat提供的JNDI,有了一些不同。第一方式只是Spring包裝了一下Jdbc,跟直接使用Jdbc沒什么大的區別;后兩種采用了連接池技術,比較好。我們也可以看出,三種方式配置基本相同,而作為使用數據源的類,調用方式相同,都是使用基本的依賴注入的方式。
4、使用Hibernate
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
?"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
?? <!
—
設
定dataSource
à
?? <bean id=
”
dataSource
” class=”org.springframework.jdbc.datasource.DriverManagerDataSource”>
????? <!
—使用SQL Server
數
據
庫
à
?????? <property name=
”driverClassName”>
????????? <value>com.microsoft.jdbc.sqlserver.SQLServerDriver</value>
?????? </property>
??????? <property name=
”url”>
????????? <value>jdbc:Microsoft:sqlserver://localhost:1433/stdb</value>
?????? </property>
<property name=
”name”>
????????? <value>admin</value>
????? ?</property>
<property name=
”msg”>
????????? <value>admin</value>
?????? </property>
??? </bean>
?//
在第一種方法的基礎上加上
Hibernate
的配置段就
OK
了。
?<!—
使用
Hibernate
的
sessionFactory
à
?
?<bean id=”
sessionFactory
” class=”org.springframework.orm.hibernate.LocalSessionFactoryBean”>
?????? <property name=”dataSource”>
??????????? <ref local=”
dataSources
”>
?????? </property>
?? ????<property name=”mappingResources”>
????????
???<list>
??????????????? <value>com/demo/bo/Book.hbm.xml</value>
???????????? </list>
?????? </property>
?????? <property name=”hibernateProperties”>
??????????? <props>
???????????????? <prop key=”hibernate.dialect”>
??????????????????????? net.sf.hibernate.dialect.SQLServerDialect
???????????????? </prop>
<prop key=”hibernate.show_sql”>
????? true
<prop>
??????????? </props>
??????? </property>
??? </bean>
?
??? <!
—設定
transactionManager
à
??? <bean id=
”
transactionManager
”
class=
”
org.springframework.jdbc.datasource.DataSourceTransactionManager
”
>
??????? <property name=
”
sessionFactory
”
>
??????????? <ref bean=
”
sessionFactory
”
/>
??????? </property>
??? </bean>
?
?? <!—示例中DAO-->
?? <bean id=
”bookDAO” class=”com.demo.bo.Boo
kDAO
”>
??????? <property name=
”
sessionFactory
”>
??????????? <ref bean=
”
sessionFactory
”/>
??????? </property>
??????? <property name=
”transactionManager”>
??????????? <ref bean=
”transactionManager”>
??????? </property>
?? </bean>
</beans>
?? 紅色部分顯示了不同之處,有三點:1)、加入了<bean id=”sessionFactory”>段,引入Hibernate的sessionFactory;2)事務處理的屬性由原來的dataSource變成了sessionFactory;3)DAO引用從原來的dataSource變成了sessionFactory。其實就是說,在原來的datasouce之上加了Hibernate這一層,來處理相應的數據訪問問題。因此在Spring中引入ORM是很容易的。
??Book.hbm.xml和Book.java是通過工具互相生成的,在這里不展示代碼了,而Book就是一個POJO。
4、使用iBatis
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
?"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
?? <!
—
設
定dataSource
à
?? <bean id=
”
dataSource
” class=”org.springframework.jdbc.datasource.DriverManagerDataSource”>
????? <!
—使用SQL Server
數
據
庫
à
?????? <property name=
”driverClassName”>
????????? <value>com.microsoft.jdbc.sqlserver.SQLServerDriver</value>
?????? </property>
??????? <property name=
”url”>
????????? <value>jdbc:Microsoft:sqlserver://localhost:1433/stdb</value>
?????? </property>
<property name=
”name”>
????????? <value>admin</value>
?????? </property>
<property name=
”msg”>
????????? <value>admin</value>
????? ?</property>
??? </bean>
?//
在第一種方法的基礎上加上
iBatis
的配置段就
OK
了。
?<!—
使用
iBatis
à
?
?<bean id=”
sqlMap
” class=”org.springframework.orm.ibatis.SqlMapClientFactoryBean”>
?????? <property name=”configLocation”>
??????????? <value>WEB/sqlMapConfig.xml</value>
?????? </property>
??? </bean>
??? <!
—設定
transactionManager
à
??? <bean id=
”
transactionManager
”
class=
”
org.springframework.jdbc.datasource.DataSourceTransactionManager
”
>
??????? <property name=
”
dataSource
”
>
??????????? <ref bean=
”
dataSource
”
/>
??????? </property>
??? </bean>
?
?? <!—示例中DAO-->
??<bean id=
”bookDAO” class=”com.demo.bo.Boo
kDAO
”>
??????? <property name=
”
dataSource
”>
??????????? <ref bean=
”
dataSource
”/>
??????? </property>
??????? <property name=
”transactionManager”>
??????????? <ref bean=
”transactionManager”>
??????? </property>
???
????<property name=”sqlMap”>
???????????? <ref bean=”sqlMap”/>
??????? </property>
?? </bean>
</beans>
?? 紅色部分顯示了不同之處,主要來看一下其與Hibernate的不同之處,1)同樣引入iBatis配置段,不過其mappingResources配置信息放在了sqlMapConfig.xml下,該文件放在WEB-INF下,示例代碼如下:
<sqlMapConfig>
???? <sqlMap resource=”com/demo/bo/Book.xml”>
</sqlMapConfig>
而這其中的Book.xml文件類似于Hibernate中的Book.hbm.xml。
?2)事務處理配置段依然引用的是dataSource,而不是sqlMap。
?3)在DAO配置段,引用dataSource的同時,又加入了sqlMap引用。
?其PO對象——Book.java與Hibernate中相同。
?(二)數據庫操作
1、使用JDBCTemplate
?
import javax.sql.DataSource;
import org.springframework.jdbc.core.*;
import org.springframework.transaction.*;
import org.springframework.dao.*;
?
public class bookDAO{
private DataSource dataSource依賴注入dataSource,管理數據庫;//
private PlatformTransationManager transactionManager;//依賴注入管理事務
?
public void setDataSource(DataSource dataSource){
??? this.dataSource=dataSource;
}
?
???? public void setTransactionManager(PlatformTransationManager transactionManager){
???????? this. transactionManager= transactionManager;
}
?
public int create(String msg){
??? JdbcTemplate jdbcTemplate=new JdbcTemplate(dataSource);
??? jdbcTemplate.update(“INSERT INFO book VALUES(1,’gf’,’Mastering Spring’)”);
}
}
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
?"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
?? <!
—
設
定dataSource
à
?? <bean id=
”dataSource” class=”org.springframework.jdbc.datasource.DriverManagerDataSource”>
????? <!
—使用SQL Server
數
據
庫
à
?????? <property name=
”driverClassName”>
????????? <value>com.microsoft.jdbc.sqlserver.SQLServerDriver</value>
?????? </property>
??????? <property name=
”url”>
????????? <value>jdbc:Microsoft:sqlserver://localhost:1433/stdb</value>
?????? </property>
<property name=
”name”>
????????? <value>admin</value>
?????? </property>
<property name=
”msg”>
????????? <value>admin</value>
?????? </property>
??? </bean>
?
??? <!
—設定
transactionManager
à
??? <bean id=
”
transactionManager
”
class=
”
org.springframework.jdbc.datasource.DataSourceTransactionManager
”
>
??????? <property name=
”
dataSource
”
>
??????????? <ref bean=
”
dataSource
”
/>
??????? </property>
??? </bean>
?
?? <!—示例中DAO-->
??<bean id=”bookDAO” class=”com.bookDAO”>
??????? <property name=
”dataSource”>
??????????? <ref bean=
”dataSource”/>
??????? </property>
?
?? </bean>
??
<!
—聲明式事務處理
-
à
?
?<bean id=
”
bookDAOProxy
”
class=
”
org.springframework.transaction.interceptor.Transation.ProxyFactoryBean
”
>
??????? <property name=
”
transacionManager
”
>
??????????? <ref bean=
”
transacionMaganer
”
/>
??????? </property>
<property name=
”
target
”
>
???????? ???<ref bean=
”
bookDAO
”
/>
??????? </property>
<property name=
”
transactionAttributes
”
>
??????????? <props>
?????????????? <!--
表示對
bookDAO
中的
create
方法進行事務處理,并指明當前沒有事務就新建一個(用
PROPAGATION_REQUIRED
常量來表示的)
à
??????????????? <prop key=
”
create*
”
>PROPAGATION_REQUIRED</prop>
??????????? </props>
??????? </property>?
?? </bean>
</beans>
?
最簡便、靈活的寫法:
?
import javax.sql.DataSource;
import org.springframework.jdbc.core.*;
import org.springframework.transaction.*;
import org.springframework.dao.*;
?
public class bookDAO{
private DataSource dataSource依賴注入dataSource,管理數據庫;//
private PlatformTransationManager transactionManager;//依賴注入管理事務
private String sql;
?
public void setDataSource(DataSource dataSource){
??? this.dataSource=dataSource;
}
?
???? public void setTransactionManager(PlatformTransationManager transactionManager){
???????? this. transactionManager= transactionManager;
}
?
public void setSql(String sql){
???? this.sql=sql;
}
?
public int create(String msg){
?/*
①
JdbcTemplate jdbcTemplate=new JdbcTemplate(dataSource);
?
?
②
jdbcTemplate.update(
“
INSERT INFO book
VALUES(1,
’gf’,’Mastering Spring’)”);
*/
//
使用下述代碼代替上面注釋的內容
?? jdbcTemplate.update(this.sql);
}
}
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
?"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
?? <!
—
設
定dataSource
à
?? <bean id=
”dataSource” class=”org.springframework.jdbc.datasource.DriverManagerDataSource”>
????? <!
—使用SQL Server
數
據
庫
à
?????? <property name=
”driverClassName”>
????????? <value>com.microsoft.jdbc.sqlserver.SQLServerDriver</value>
?????? </property>
??????? <property name=
”url”>
????????? <value>jdbc:Microsoft:sqlserver://localhost:1433/stdb</value>
?????? </property>
<property name=
”name”>
????????? <value>admin</value>
?????? </property>
<property name=
”msg”>
????????? <value>admin</value>
?????? </property>
??? </bean>
?
??? <!
—設定
transactionManager
à
??? <bean id=
”
transactionManager
”
class=
”
org.springframework.jdbc.datasource.DataSourceTransactionManager
”
>
??????? <property name=
”
dataSource
”
>
???????? ???<ref bean=
”
dataSource
”
/>
??????? </property>
??? </bean>
?
?? <!—
設定
jdbcTemplate
à
??? <bean id=”jdbcTemplate” class=”org.springframework.jdbc.core.JdbcTemplate”>
??????? <property name=”dataSource”>
?????????????? <ref bean=”dataSource”>
??????? </property>
?? <!—示例中DAO-->
??<bean id=”bookDAO” class=”com.bookDAO”>
??????? <property name=
”dataSource”>
??????????? <ref bean=
”dataSource”/>
??????? </property>
????
?//jdbcTemplate
屬性代替
①
處的代碼將dataSource注入到jdbcTemplate中
??????? <property name=”jdbcTemplate”>
???????????? <ref bean=”jdbcTemplate”>
??????? </property>
?????
//sql
屬性代替
②
處代碼
??????? <property name=”sql”>
???????????? <value>INSERT INTO hello VALUES(1,
’
gf
’
,
’
Mastering Spring
’
)</value>
???????? </property>
?? </bean>
??
<!
—聲明式事務處理
-
à
?
?<bean id=
”
bookDAOProxy
”
class=
”
org.springframework.transaction.interceptor.TransationProxyFactoryBean
”
>
??????? <property name=
”
transacionManager
”
>
??????????? <ref bean=
”
transacionMaganer
”
/>
??????? </property>
<property name=
”
target
”
>
??????????? <ref bean=
”
bookDAO
”
/>
??????? </property>
<property name=
”
transactionAttributes
”
>
??????????? <props>
?????????????? <!--
表示對
bookDAO
中的
create
方法進行事務處理,并指明當前沒有事務就新建一個(用
PROPAGATION_REQUIRED
常量來表示的)
à
??????????????? <prop key=
”
create*
”
>PROPAGATION_REQUIRED</prop>
??????????? </props>
??????? </property>?
?? </bean>
</beans>
?
?
2、使用Hibernate
import javax.sql.DataSource;
import org.springframework.jdbc.core.*;
import org.springframework.transaction.*;
import org.springframework.dao.*;
import org.springframework.orm.*;
?
public class bookDAO{
//private DataSource dataSource;
依賴注入
dataSource
,管理數據庫
private SessionFactory sessionFactory;
private PlatformTransationManager transactionManager;//依賴注入管理事務
?
/*public void setDataSource(DataSource dataSource){
??? this.dataSource=dataSource;
}*/
?
???? public void setTransactionManager(PlatformTransationManager transactionManager){
???????? this. transactionManager= transactionManager;
}
?
public void setSessionFactory(DataSource sessionFactory){
???? this. sessionFactory = sessionFactory;
}
?
public int create(String msg){
?/*
①
JdbcTemplate jdbcTemplate=new JdbcTemplate(dataSource);
?
?
②
jdbcTemplate.update(
“
INSERT INFO book
VALUES(1,
’gf’,’Mastering Spring’)”);
*/
?//
下面這行替代
①
????
?HibernateTemplate hibernateTemplate=new HibernateTemplate(sessionFactory);
?
????? Book book=new Book();
????? book.setId(1);
????? book.setAuthor(“gf”);
????? book.setName(“Mastering Spring”);
?
//
下面這行替代
②
????? hibernateTemplate.saveOrUpdate(book);
}
?
sessionFactory
里引入了book.hbm.xml
?
?
3、使用iBatis
import javax.sql.DataSource;
import org.springframework.jdbc.core.*;
import org.springframework.transaction.*;
import org.springframework.dao.*;
import org.springframework.orm.*;
?
public class bookDAO extends SqlMapClientDaoSupport{
???? private PlatformTransationManager transactionManager;
?
?
??? public void setTransactionManager(PlatformTransationManager transactionManager){
???????? this. transactionManager= transactionManager;
}
?
public int create(String msg){
??? ??
Book book=new Book();
????? book.setId(1);
????? book.setAuthor(“gf”);
????? book.setName(“Mastering Spring”);
??
???? getSqlMapClientTemplate().update(“
insertBook
”,book);
}
?
}
?
配置文件——Book.xml
該文件相當于Hibernate中的book.hbm.xml
?
<sqlMap namespace=”Book”>
<typeAlias alias=”book” type=”com.demo.bo.Book”/>
<insert id=”insertBook” parameterClass=”book”>
??? insert into book(id,author,name) values(#id#,#author#,#name#);
</insert>
</sqlMap>
BookDAO中的insertBook和配置文件中的insertBook相匹配。