1. 程式人生 > >四、spring的JDBC模板和事務管理

四、spring的JDBC模板和事務管理

Spring的JDBC模板

Spring是JavaEE開發的一站式框架,對各種持久化技術都提供了簡單的模板

ORM持久化技術 模板類
JDBC org.springframework.jdbc.core.JdbcTemplate
Hibernate5.0 org.springframework.orm.hibernate5.HibernateTemplate
IBatis(MyBatis) org.springframework.orm.ibatis.SqlMapClientTemplate
JPA org.springfrmaework.orm.jpa.JpaTemplate

JDBC模板的基本使用

  1. 引入jar
    • Spring專案的6個基礎開發包
    • 資料庫驅動包
    • Spring的JDBC模板的jar包
  2. 測試
    • 編寫測試類
      public class TestDemo {
      
      	@Test
      	public void demo() {
      		//建立連線池
      		DriverManagerDataSource dataSource = new DriverManagerDataSource();
      		dataSource.setDriverClassName("com.mysql.jdbc.Driver");
      		dataSource.setUrl("jdbc:mysql:///test");
      		dataSource.setUsername("root");
      		dataSource.setPassword("root");
      		
      		//建立jdbc模板
      		JdbcTemplate template = new JdbcTemplate(dataSource);
      		List<Map<String,Object>> list = template.queryForList("select * from user");
      		for (Map<String, Object> map : list) {
      			Set<String> keySet = map.keySet();
      			Iterator<String> iterator = keySet.iterator();
      			while (iterator.hasNext()) {
      				String key = iterator.next();
      				System.out.println(key+" : "+map.get(key));
      			}
      		}
      	}
      }
    • 測試結果
      id : 1
      name : test
      password : 0
      id : 2
      name : wxf
      password : 1
      id : 3
      name : admin
      password : 123

Spring管理模板和連線池

  1. 配置檔案配置Spring管理
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns:aop="http://www.springframework.org/schema/aop"
            xmlns:tx="http://www.springframework.org/schema/tx" 
            xsi:schemaLocation="
            http://www.springframework.org/schema/beans
    		http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/tx 
            http://www.springframework.org/schema/tx/spring-tx.xsd"> 
            <!-- 管理資料庫連線池 -->    
    	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    		<property name="url" value="jdbc:mysql:///test"></property>
    		<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
    		<property name="username" value="root"></property>
    		<property name="password" value="root"></property>
    	</bean>        
            
    	<!-- 管理JDBC模板 -->
    	<bean id="template" class="org.springframework.jdbc.core.JdbcTemplate">
    		<property name="dataSource" ref="dataSource"/>
    	</bean>
    </beans>
  2. 測試方法
    @Test
    public void demo2() {
    	
    	ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    	JdbcTemplate template = (JdbcTemplate) context.getBean("template");
    	
    	List<Map<String,Object>> list = template.queryForList("select * from user");
    	for (Map<String, Object> map : list) {
    		Set<String> keySet = map.keySet();
    		Iterator<String> iterator = keySet.iterator();
    		while (iterator.hasNext()) {
    			String key = iterator.next();
    			System.out.println(key+" : "+map.get(key));
    		}
    	}
    }

Spring中使用開源資料庫連線池

DBCP的使用

  1. 引入jar包
    • com.springsource.org.apache.commons.pool-1.5.3.jar
    • com.springsource.org.apache.commons.dbcp-1.2.2.osgi.jar  
  2. Spring配置連線池
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    	<property name="url" value="jdbc:mysql:///test"></property>
    	<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
    	<property name="username" value="root"></property>
    	<property name="password" value="root"></property>
    </bean>

C3P0的使用

  1. 引入jar包
    • com.springsource.com.mchange.v2.c3p0-0.9.1.2.jar
  2. Spring配置連線池
    <!-- 管理c3p0資料庫連線池 --> 
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    	<property name="jdbcUrl" value="jdbc:mysql:///test"></property>
    	<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
    	<property name="user" value="root"></property>
    	<property name="password" value="root"></property>
    </bean>

 

抽取連線池屬性配置值到Properties檔案 

  1. 定義一個properties檔案:jdbc.properties
    jdbc.url=jdbc:mysql:///test
    jdbc.driverClassName=com.mysql.jdbc.Driver
    jdbc.username=root
    jdbc.password=root
  2. Spring引入jdbc.properties檔案
    • 第一種:使用<bean>標籤
      <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
      	<property name="location" value="classpath:jdbc.properties"/>
      </bean>
    • 第二種:使用<context:property-placeholder>標籤
      <context:property-placeholder location="classpath:jdbc.properties" />
       
  3. Spring配置檔案使用jdbc.properties的屬性值
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    	<property name="url" value="${jdbc.url}"></property>
    	<property name="driverClassName" value="${jdbc.driverClassName}"></property>
    	<property name="username" value="${jdbc.username}"></property>
    	<property name="password" value="${jdbc.password}"></property>
    </bean>

 

Spring的事務管理

常用API

PlatformTransactionManager

  • Spring的事務基礎結構的中心介面,常用實現類
    • DataSourceTransactionManager:使用JDBC管理事務
    • HibernateTransactionManager:使用Hibernate管理事務    

TransactionDefinition

  • Spring的事務定義,用於定義事務相關的資訊。例如,隔離級別、傳播行為、是否只讀、超時資訊等  

TransactionStatus

  • 用於記錄事務管理的過程中,事務的狀態資訊  

Spring進行事務管理時,PlatformTransactionManager根據TransactionDefinition進行事務的管理,這個過程中會產生各種狀態,將這些狀態記錄到TransactionStatus中

傳播行為

基本認識

事務傳播行為用來描述由某一個事務傳播行為修飾的方法被巢狀進另一個方法的時事務如何傳播

主要用來解決業務層方法(每個業務層方法有自己的事務)相互呼叫的問題

7種傳播行為

class TestServiceImpl01 {
	...
	public void A() {
		testDao1.test1();
		testDao2.test2();
	}
}

class TestServiceImpl02 {
	...
	public void B() {
		new TestServiceImpl01().A();//A操作
		testDao3.test3();//B操作
		testDao4.test4();//B操作
	}
}

  

分類 傳播行為型別 說明

多個操作在同一個事務中

(A、B操作在一個事務中)

PROPAGATION_REQUIRED 預設值,如果A中有事務,使用A中的事務;如果A中沒有事務,建立一個新的事務,將操作(A、B)包含進來
PROPAGATION_SUPPORTS 如果A中有事務,使用A中的事務;如果A中沒有事務,就不使用事務
PROPAGATION_MANDATORY 如果A中有事務,使用A中的事務;如果A中沒有事務,就丟擲異常

多個操作不在同一個事務中

(A、B操作不在一個事務中)

PROPAGATION_REQUIRES_NEW 如果A中有事務,將A的事務掛起,新建一個事務,只將自身操作(B)包含進來
PROPAGATION_NOT_SUPPORTED 如果A中有事務,將A的事務掛起,不使用事務
PROPAGATION_NEVER 如果A中有事務,丟擲異常
巢狀式事務 PROPAGATION_NESTED

如果A中有事務,執行A事務,執行完成後設定一個儲存點;再執行B中的操作,如果沒有異常,執行通過;如果有異常

可以回滾到最初始位置(A操作前),也可以回滾到A操作後設置的儲存點位置

基本使用

案例要求:

  賬戶之間相互轉賬,一方轉出的同時另一方必須轉入才行

實現一:不使用事務

  1. 建立service層、dao層的介面和實現類
    • dao層
      • 介面
      • 實現類  
    • service層 
      • 介面
      • 實現類   
  2. Spring管理service和dao的實現類
  3. 測試

程式設計式、宣告式事務管理