第四章 Spring與JDBC的整合
這裏選擇的是mysql數據庫。
4.1引入aop、tx的命名空間
為了事務配置的需要,我們引入aop、tx的命名空間
<?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配置數據源
<!-- 配置數據源 --> <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事務的隔離級別
事務的隔離級別是由數據庫本身提供的,一般不需要我們去改變什麼東西。
-
事務並發會產生的問題
-
髒讀 如:事務A讀到事務B未提交的數據
-
不可重複讀如:多次讀取同一個事務得到的結果不同
-
幻讀如:事務A讀到事務B已提交的數據
-
隔離級別
|
隔離級別 |
解釋 |
允許並發的問題 |
相應數據庫 |
|
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>
<?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