Spring知識複習之三
阿新 • • 發佈:2018-11-12
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) {}