閱讀980 返回首頁    go 技術社區[雲棲]


第四章 Spring與JDBC的整合

這裏選擇的是mysql數據庫。


4.1引入aoptx的命名空間


為了事務配置的需要,我們引入aoptx的命名空間


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
	xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:p="https://www.springframework.org/schema/p"
	xmlns:context="https://www.springframework.org/schema/context"
	xmlns:aop="https://www.springframework.org/schema/aop"
	xmlns:tx="https://www.springframework.org/schema/tx"
	xsi:schemaLocation="https://www.springframework.org/schema/beans 
		https://www.springframework.org/schema/beans/spring-beans-3.0.xsd
		https://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context-3.0.xsd
        https://www.springframework.org/schema/aop 
        https://www.springframework.org/schema/aop/spring-aop-3.0.xsd
		https://www.springframework.org/schema/tx 
		https://www.springframework.org/schema/tx/spring-tx-3.0.xsd">


4.2配置數據源


          在配置數據源之前,首先要導入連接數據庫時所需要的jar包。

<!-- 配置數據源 -->
	<bean 
		 
		destroy-method="close">
		<!-- jdbc連接的4個必須參數 -->
		<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
		<property name="url" value="jdbc:mysql://127.0.0.1:3306/test"/>
		<property name="username" value="root"/>
		<property name="password" value="test"/>
		
		<!-- 連接池啟動初始值 -->
		<property name="initialSize" value="5"/>
		
		<!-- 最大空閑值 -->
		<property name="maxIdle" value="20"/>
		
		<!-- 最小空閑值 -->
		<property name="minIdle" value="5"/>
		
		<!-- 最大連接值 -->
		<property name="maxActive" value="500"/>
	</bean>


4.3配置事務


4.3.1 基於Schema的方式


<!-- 指定事務管理器 -->
	<bean  >
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<!-- 設置事務增強 -->
	<tx:advice  transaction-manager="txManager">
		<tx:attributes>
			<tx:method name="get*" read-only="true"/>
			<tx:method name="add*" rollback-for="Exception"/>
		</tx:attributes>
	</tx:advice>
	
	<!-- 作用Shcema的方式配置事務,這裏是把事務設置到了service層-->
	<aop:config>
		<aop:pointcut  expression="execution(* cn.framelife.spring.jdbc.*ServiceImpl.*(..))" />
		<aop:advisor advice-ref="txAdvice" pointcut-ref="servicePointcut"/>
	</aop:config>


4.3.2基於注解的方式


基本配置:

<!-- 配置數據源 -->
	<bean 
		 
		destroy-method="close">
		<!-- jdbc連接的4個必須參數 -->
		<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
		<property name="url" value="jdbc:mysql://127.0.0.1:3306/test"/>
		<property name="username" value="root"/>
		<property name="password" value="test"/>
		<!-- 連接池啟動初始值 -->
		<property name="initialSize" value="5"/>
		<!-- 最大空閑值 -->
		<property name="maxIdle" value="20"/>
		<!-- 最小空閑值 -->
		<property name="minIdle" value="5"/>
		<!-- 最大連接值 -->
		<property name="maxActive" value="500"/>
	</bean>
	
	<!-- 指定事務管理器 -->
	<bean  >
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<!-- 打開tx事務注解管理功能 -->
	<tx:annotation-driven transaction-manager="txManager"/>

@Transactional的使用

放在需要事務的類的頭上。如:我們想把事務集中在業務層管理,那就在service層的各個類上標注上@Transactional注解。


@Transactional
@Repository
public class UserDaoImpl implements UserDao {
}

4.3.3事務的傳播行為


Spring給我們提供了7種類型的事務傳播行為:

PROPAGATION_REQUIRED--支持當前事務,如果當前沒有事務,就新建一個事務。這是最常見的選擇。 
PROPAGATION_SUPPORTS
--
支持當前事務,如果當前沒有事務,就以非事務方式執行。 
PROPAGATION_MANDATORY
--
支持當前事務,如果當前沒有事務,就拋出異常。 
PROPAGATION_REQUIRES_NEW
--
新建事務,如果當前存在事務,把當前事務掛起。 
PROPAGATION_NOT_SUPPORTED
--
以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。 
PROPAGATION_NEVER
--
以非事務方式執行,如果當前存在事務,則拋出異常。 


我們可以通過事務的propagation屬性來進行配置。


4.3.4事務的隔離級別


事務的隔離級別是由數據庫本身提供的,一般不需要我們去改變什麼東西。


  1. 事務並發會產生的問題


  1. 髒讀 如:事務A讀到事務B未提交的數據

  2. 不可重複讀如:多次讀取同一個事務得到的結果不同

  3. 幻讀如:事務A讀到事務B已提交的數據


  1. 隔離級別

隔離級別

解釋

允許並發的問題

相應數據庫

READUNCOMMITED

可讀取未提交的數據

ABC


READCOMMITED

讀已提交事務

BC

SQLServer默認

REPEATABLEREAD

可重複讀

C

MySQL默認

SERIALIZABLE

序列化




4.4JDBCTemplate的使用

public class UserDaoImpl implements UserDao {
	private JdbcTemplate jdbcTemplate;
	
	/**
	 * 通過dataSource的setter方法,在運行時注入一個dataSouce對象,然後根據這個對象創建一個JdbcTemplate對象
	 * @param dataSource 
	 */
	public void setDataSource(DataSource dataSource){
		this.jdbcTemplate = new JdbcTemplate(dataSource);
	}

	/**
	 * 增加、修改、刪除都是使用的JdbcTemplate的update方法。
	 * update方法中第一個參數是sql語句,未知的值用占位符?代替
	 * 第二個參數是一個Object數組。數組裏麵的各項是上麵的占位符的值
	 * 第三個參數是一個int數組。數組的各項是第二個參數中的值在數據庫中的類型
	 */
	public void save(User user) {
		jdbcTemplate.update("insert into user(username,password) values(?,?)",
				new Object[]{user.getUsername(),user.getPassword()},
				new int[]{java.sql.Types.VARCHAR,java.sql.Types.VARCHAR}
			);
	}
	
	public void update(User user) {
		jdbcTemplate.update("update user set username=?,password=? where id=?",
				new Object[]{user.getUsername(),user.getPassword(),user.getId()},
				new int[]{java.sql.Types.VARCHAR,java.sql.Types.VARCHAR,java.sql.Types.INTEGER}
		);
	}
	
	public void delete(Integer id) {
		jdbcTemplate.update("delete from user where id = ?",
				new Object[]{id}, 
				new int[]{java.sql.Types.INTEGER}
			);
	}

	/**
	 * 根據id獲取單個數據是通過queryForObject方法
	 * 這個方法前麵三個參數都與update方法一樣
	 * 第四個參數是一個org.springframework.jdbc.core.RowMapper接口的對象
	 * 實現RowMapper接口,必須實現裏麵的mapRow(ResultSet rs, int rowNum)方法
	 * 這個方法是通過ResultSet把一條記錄放到一個實體類對象中,並返回這個實體類對象
	 */
	public User getUserById(Integer id) {
		User user = jdbcTemplate.queryForObject("select * from user where id=?",
				new Object[]{id}, 
				new int[]{java.sql.Types.INTEGER}, new RowMapper<User>() {
					public User mapRow(ResultSet rs, int rowNum) throws SQLException {
						User user = new User();
						user.setId(rs.getInt("id"));
						user.setUsername(rs.getString("username"));
						user.setPassword(rs.getString("password"));
						return user;
					}
				});
		return user;
	}

	/**
	 * 通過一條沒有占位符的select語句來查詢多條記錄,並返回一個List集合
	 * query方法裏麵的兩個參數
	 * 第一個是select語句
	 * 第二個是RowMapper接口的對象
	 */
	public List<User> getUsersBySql(String sql) {
		
		return jdbcTemplate.query(sql,  new RowMapper<User>() {
					public User mapRow(ResultSet rs, int rowNum) throws SQLException {
						User user = new User();
						user.setId(rs.getInt("id"));
						user.setUsername(rs.getString("username"));
						user.setPassword(rs.getString("password"));
						return user;
					}
				});
	}	
}



4.5完整的配置


4.5.1基於Schema

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
	xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:p="https://www.springframework.org/schema/p"
	xmlns:context="https://www.springframework.org/schema/context"
	xmlns:aop="https://www.springframework.org/schema/aop"
	xmlns:tx="https://www.springframework.org/schema/tx"
	xsi:schemaLocation="https://www.springframework.org/schema/beans 
		https://www.springframework.org/schema/beans/spring-beans-3.0.xsd
		https://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context-3.0.xsd
        https://www.springframework.org/schema/aop 
        https://www.springframework.org/schema/aop/spring-aop-3.0.xsd
		https://www.springframework.org/schema/tx 
		https://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

	<!-- 配置數據源 -->
	<bean 
		 
		destroy-method="close">
		<!-- jdbc連接的4個必須參數 -->
		<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
		<property name="url" value="jdbc:mysql://127.0.0.1:3306/test"/>
		<property name="username" value="root"/>
		<property name="password" value="test"/>
		<!-- 連接池啟動初始值 -->
		<property name="initialSize" value="5"/>
		<!-- 最大空閑值 -->
		<property name="maxIdle" value="20"/>
		<!-- 最小空閑值 -->
		<property name="minIdle" value="5"/>
		<!-- 最大連接值 -->
		<property name="maxActive" value="500"/>
	</bean>
	
	<!-- 指定事務管理器 -->
	<bean  >
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<!—
設置事務增強 
read-only 表示對應的事務應該被最優化為隻讀事務。
rollback-for="Exception" 是指出現異常的時候回滾事務
-->
	<tx:advice  transaction-manager="txManager">
		<tx:attributes>
			<tx:method name="get*" read-only="true"/>
			<tx:method name="add*" rollback-for="Exception"/>
			<tx:method name="update*"/>
		</tx:attributes>
	</tx:advice>
	
	<!-- 作用Shcema的方式配置事務 -->
	<aop:config>
		<aop:pointcut  expression="execution(* cn.framelife.spring.jdbc.*ServiceImpl.*(..))" />
		<aop:advisor advice-ref="txAdvice" pointcut-ref="servicePointcut"/>
	</aop:config>
	
	<!-- 把相關的Bean交由Spring管理 -->
	<bean  >
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	<bean  >
		<property name="userDao" ref="userDao"></property>
	</bean>
</beans>


4.5.2基於注解


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
	xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:p="https://www.springframework.org/schema/p"
	xmlns:context="https://www.springframework.org/schema/context"
	xmlns:aop="https://www.springframework.org/schema/aop"
	xmlns:tx="https://www.springframework.org/schema/tx"
	xsi:schemaLocation="https://www.springframework.org/schema/beans 
		https://www.springframework.org/schema/beans/spring-beans-3.0.xsd
		https://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context-3.0.xsd
        https://www.springframework.org/schema/aop 
        https://www.springframework.org/schema/aop/spring-aop-3.0.xsd
		https://www.springframework.org/schema/tx 
		https://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
	
	<context:component-scan base-package="cn.framelife.spring"></context:component-scan>
	<!-- 配置數據源 -->
	<bean 
		 
		destroy-method="close">
		<!-- jdbc連接的4個必須參數 -->
		<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
		<property name="url" value="jdbc:mysql://127.0.0.1:3306/test"/>
		<property name="username" value="root"/>
		<property name="password" value="test"/>
		<!-- 連接池啟動初始值 -->
		<property name="initialSize" value="5"/>
		<!-- 最大空閑值 -->
		<property name="maxIdle" value="20"/>
		<!-- 最小空閑值 -->
		<property name="minIdle" value="5"/>
		<!-- 最大連接值 -->
		<property name="maxActive" value="500"/>
	</bean>
	
	<!-- 指定事務管理器 -->
	<bean  >
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<!-- 打開tx事務注解管理功能 -->
	<tx:annotation-driven transaction-manager="txManager"/>
</beans>




最後更新:2017-04-03 16:48:36

  上一篇:go What is the purpose of @SmallTest, @MediumTest, and @LargeTest annotations in Android?
  下一篇:go Just Do It!