Spring整合JDBC
1 Spring提供了很多持久層技術模板類
ORM持久化技術 模板類
JDBC org.springframework.jdbc.core.JdbcTemplate
Hibernate3.0 org.springframework.orm.hibernate3.HibernateTemplate
IBatis(MyBatis) org.springframework.orm.ibatis.SqlMapClientTemplate
JPA org.springframework.orm.jpa.JpaTemplate
2 Spring與Jdbc
(1)原生JDBC模板
<1>連接池的使用
1.使用C3p0連接池(com.mchange.v2.c3p0.ComboPooledDataSource)
代碼示例如下:
ComboPooledDataSource dataSource=new ComboPooledDataSource();
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql:///hibernate_crm");
dataSource.setUser("root");
dataSource.setPassword("root");
2.使用spring內置連接池(org.springframework.jdbc.datasource.DriverManagerDataSource)
代碼示例如下:
DriverManagerDataSource dataSource=new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///hibernate_crm");
dataSource.setUsername("root");
dataSource.setPassword("root");
<2>JDBC模板對象的調用
//1 創建JDBC模板對象
JdbcTemplate jt=new JdbcTemplate();
//2連接進連接池
jt.setDataSource(dataSource);
//3 書寫sql語句,並執行
String sql="insert into t_user values(null,'rose')";
jt.update(sql);
(2)Spring對連接池進行管理
<1>配置Spring內置的連接池DriverManagerDataSource
<bean name="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql:///hibernate_crm"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
<!--配置JDBCTemplate對象並關聯Spring內置的連接池 -->
<bean name="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<2>配置C3P0連接池
導入jar包: com.springsource.com.mchange.v2.c3p0-0.9.1.2.jar
<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql:///hibernate_crm"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
</bean>
<!--配置JDBCTemplate對象並關聯C3p0連接池 -->
<bean name="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<3>配置db連接池
導入jar包:
com.springsource.org.apache.commons.dbcp-1.2.2.osgi.jar
com.springsource.org.apache.commons.pool-1.5.3.jar
<!-- 配置 DBCP 連接池 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///spring_day02"/>
<property name="username" value="root"/>
<property name="password" value="123"/>
</bean>
(3)JdbcTemplate對象的增刪改查
概述:JdbcTemplate的增刪改都使用 update()方法。而查詢則使用queryForObject()
//增
@Override
public void save(User u) {
String sql="insert into t_user values(null,?)";
jt.update(sql,u.getName());
}
//刪(根據id刪除)
@Override
public void delete(Integer id) {
String sql="delete from t_user where id=?";
jt.update(sql,id);
}
//改
@Override
public void update(User u) {
String sql="update t_user set name=? where id=?";
jt.update(sql,u.getName(),u.getId());
}
//查(根據id進行查詢,獲取一個對象)
@Override
public User getById(Integer id) {
String sql="select * from t_user where id=?";
User user = jt.queryForObject(sql, new RowMapper<User>() {
@Override
public User mapRow(ResultSet rs, int arg1) throws SQLException {
//封裝實體 User對象返回給這個方法
User u=new User();
u.setId(rs.getInt("id"));
u.setName(rs.getString("name"));
return u;
}},id);
return user;
}
//查(查詢表中總共有幾條記錄)
@Override
public int getTotalCount() {
String sql="select count(*) from t_user";
Integer count = jt.queryForObject(sql,Integer.class);
return count;
}
//查(查詢獲取表中的所以記錄對象,獲取的是集合對象)
@Override
public List<User> getAll() {
String sql="select * from t_user";
List<User> userList = jt.query(sql, new RowMapper<User>(){
@Override
public User mapRow(ResultSet rs, int arg1) throws SQLException {
User user=new User();
user.setId(rs.getInt("id"));
user.setName(rs.getString("name"));
return user;
}});
return userList;
}
(4)將數據庫信息配置到屬性文件中
<1>在src下創建一個配置文件,如 jdbc.properties
內容如下:
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///spring_crm
jdbc.username=root
jdbc.password=123
<2>在applicationContext主配置文件中
方式一:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:jdbc.properties"/>
</bean>
方式二:
<context:property-placeholder location="classpath:jdbc.properties"/>
Spring事務管理
1事務回顧
<1>什麼是事務:
事務邏輯上的一組操作,組成這組操作的各個邏輯單元,要麼一起成功,要麼一起失敗.
<2>事務特性:
原子性 :強調事務的不可分割.
一致性 :事務的執行的前後數據的完整性保持一致.
隔離性 :一個事務執行的過程中,不應該受到其他事務的干擾
持久性 :事務一旦結束,數據就持久到數據庫
<3>如果不考慮隔離性引發安全性問題:
髒讀 :一個事務讀到了另一個事務的未提交的數據
不可重複讀 :一個事務讀到了另一個事務已經提交的 update 的數據導致多次查詢結果不一致.
虛幻讀 :一個事務讀到了另一個事務已經提交的 insert 的數據導致多次查詢結果不一致.
<4>解決讀問題: 設置事務隔離級別
未提交讀 :髒讀,不可重複讀,虛讀都有可能發生
已提交讀 :避免髒讀。但是不可重複讀和虛讀有可能發生
可重複讀 :避免髒讀和不可重複讀.但是虛讀有可能發生.
串行化的 :避免以上所有讀問題.
<5>
Mysql 默認:可重複讀
Oracle 默認:讀已提交
2 相關的API接口
(1) 平臺事務管理器 PlatformTransactionManager
<1> org.springframework.jdbc.datasource.DataSourceTransactionManager
SpringJDBC 或 iBatis 使用
<2> org.springframework.orm.hibernate3.HibernateTransactionManager
Hibernate 進行持久化數據時使用
(2)事務定義信息接口 TransactionDefinition
事務定義信息內容包括:
* 隔離級別
* 傳播行爲
事務的傳播的格式爲:PROPAGION_XXX
& 保證同一個事務中
PROPAGATION_REQUIRED 支持當前事務,如果不存在 就新建一個(默認)
PROPAGATION_SUPPORTS 支持當前事務,如果不存在,就不使用事務
PROPAGATION_MANDATORY 支持當前事務,如果不存在,拋出異常
& 保證不在同一個事務中
PROPAGATION_REQUIRES_NEW 如果有事務存在,掛起當前事務,創建一個新的事務
PROPAGATION_NOT_SUPPORTED 以非事務方式運行,如果有事務存在,掛起當前事務
PROPAGATION_NEVER 以非事務方式運行,如果有事務存在,拋出異常
PROPAGATION_NESTED 如果當前事務存在,則嵌套事務執行
* 超時信息
* 是否只讀
(3) 事務狀態接口 TransactionStatus,記錄事務的狀態
2 Spring事務管理過程簡述
平臺事務管理器(PlatformTransactionManager)
根據 事務定義的信息(TransactionDefinition )
將事務管理過程中的狀態記錄到 TransactionStatus裏面
3 Spring事務管理分類
(1)傳統的事務管理方式:編程式事務方式(手動編寫代碼完成事務的管理)
<1> Jdbc相關代碼示例:
(Connection) conn.setAutoCommit(false); //設置手動管理事務
<2>Hibernate相關代碼示例:
Session.beginTransaction();
<3>特點分析:
優點:細粒度的事務控制,可以對指定方法,或指定方法的某幾行進行事務控制。
缺點:雖靈活,但繁瑣,每次要開啓 ,提交,回滾,且要釋放資源,否則耗內存。
(2)Spring提供對事務的管理,這就叫做聲明式事務管理。
<1>聲明式事務管理特點:
粗粒度的事務控制,只能給整個方法應用事務,不可以對方法的某幾行應用事務。
其核心是基於 AOP的。
<2>Spring聲明式事務管理器分類:
Jdbc技術:DataSourceTransactionManager
Hibernate技術:HibernateTransactionManager
<3>xml聲明式事務管理配置如下:
《1》<!--配置spring的事務核心管理器,封裝了所有事務操作,依賴於連接池 -->
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager ">
<property name="dataSource" ref="dataSource"></property>
</bean>
《2》<!--配置spring事務模板對象,用於service層代碼API調用,依賴於spring的事務核心管理器 -->
<bean name="transcationTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"></property>
</bean>
《3》將spring事務模板對象 依賴到service層中
<bean name="accountService" class="cn.sss.service.AccountServiceImp">
<property name="ad" ref="accountDao"></property>
<property name="tt" ref="transcationTemplate"></property>
</bean>
《4》<!-- 配置事務通知 ,依賴spring事務核心管理器-->
<tx:advice transaction-manager="transactionManager" id="txAdvice">
<tx:attributes>
<!--以方法爲單位,指定方法應用什麼事務屬性
name:要進行事務管理 的方法名
isolation:設置事務的隔離級別
propagation:事務的傳播行爲
read-only:只讀
-->
<tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
<!--下面爲企業中的事務管理 的方法配置(使用通配符 *) -->
<tx:method name="persist*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
<tx:method name="update*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
<tx:method name="modify*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
<tx:method name="delete*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
<tx:method name="remove*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
<tx:method name="get*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true"/>
<tx:method name="find*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true"/>
<tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
<tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
<tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
</tx:attributes>
</tx:advice>
《5》<!--配置織入(把事務通知織入到目標對象中) -->
<aop:config>
<!--配置切點(需增強的方法) -->
<aop:pointcut expression="execution(* cn.itheima.service.*ServiceImp.*(..))" id="txPc"/>
<!-- 配置切面(切點+通知)
advice-ref:通知名稱
pointcut-ref:切點名稱
-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPc"/>
</aop:config>
<4>註解 實現spring聲明式事務管理
* 主配置文件爲:
<!--配置spring的事務核心管理器,封裝了所有事務操作,依賴於連接池 -->
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager ">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--配置spring事務模板對象,依賴於spring的事務核心管理器 -->
<bean name="transcationTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"></property>
</bean>
<!--開啓使用註解管理aop事務 -->
<tx:annotation-driven/>
* 業務service層:
& 在類上方使用註解 注入aop事務管理的配置,作用於整個類中所有的方法
@Transactional(isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=false)
public class AccountServiceImp implements AccountService {}
& 在方法名前使用註解配置aop事務(作用於此方法,權限大於在類上寫入的註解)
@Transactional(isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=false)
public void transfer(Integer from, Integer to, Double money) {}