第四章 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>




 

 

你可能感兴趣的:(spring)