第四章 Spring与JDBC的整合

这里选择的是mysql数据库。


4.1引入aoptx的命名空间


为了事务配置的需要,我们引入aoptx的命名空间


 

<?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:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	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-3.0.xsd
		http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
		http://www.springframework.org/schema/tx 
		http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

 


4.2配置数据源


          在配置数据源之前,首先要导入连接数据库时所需要的jar包。

<!-- 配置数据源 -->
	<bean id="dataSource"
		class="org.apache.commons.dbcp.BasicDataSource" 
		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 id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<!-- 设置事务增强 -->
	<tx:advice id="txAdvice" 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 id="servicePointcut" expression="execution(* cn.framelife.spring.jdbc.*ServiceImpl.*(..))" />
		<aop:advisor advice-ref="txAdvice" pointcut-ref="servicePointcut"/>
	</aop:config>


4.3.2基于注解的方式


基本配置:

<!-- 配置数据源 -->
	<bean id="dataSource"
		class="org.apache.commons.dbcp.BasicDataSource" 
		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 id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<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="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	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-3.0.xsd
		http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
		http://www.springframework.org/schema/tx 
		http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

	<!-- 配置数据源 -->
	<bean id="dataSource"
		class="org.apache.commons.dbcp.BasicDataSource" 
		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 id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<!—
设置事务增强 
read-only 表示对应的事务应该被最优化为只读事务。
rollback-for="Exception" 是指出现异常的时候回滚事务
-->
	<tx:advice id="txAdvice" 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 id="servicePointcut" expression="execution(* cn.framelife.spring.jdbc.*ServiceImpl.*(..))" />
		<aop:advisor advice-ref="txAdvice" pointcut-ref="servicePointcut"/>
	</aop:config>
	
	<!-- 把相关的Bean交由Spring管理 -->
	<bean id="userDao" class="cn.framelife.spring.jdbc.UserDaoImpl">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	<bean id="userService" class="cn.framelife.spring.jdbc.UserServiceImpl">
		<property name="userDao" ref="userDao"></property>
	</bean>
</beans>


4.5.2基于注解


<?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:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	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-3.0.xsd
		http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
		http://www.springframework.org/schema/tx 
		http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
	
	<context:component-scan base-package="cn.framelife.spring"></context:component-scan>
	<!-- 配置数据源 -->
	<bean id="dataSource"
		class="org.apache.commons.dbcp.BasicDataSource" 
		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 id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<!-- 打开tx事务注解管理功能 -->
	<tx:annotation-driven transaction-manager="txManager"/>
</beans>




 

 

posted @ 2013-07-15 21:23  jlins  阅读(280)  评论(0编辑  收藏  举报