Spring 框架学习第六节:Spring 中的 JdbcTemplate 与事务控制

本文详细介绍了SSM框架中的Spring与MyBatis整合,包括JdbcTemplate的配置与使用,以及Spring中事务控制的两种配置方式:基于XML和基于注解。通过实例演示了如何在DAO层使用JdbcTemplate进行数据库操作,以及如何在Service层实现转账业务的事务管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

此博客用于个人学习,来源于ssm框架的书籍,对知识点进行一个整理。

6.1 Spring 中的 JdbcTemplate:

可能有人会疑惑:Spring 中既然有 JdbcTemplate,为什么还需要与 MyBatis 框架一起使用?

两者可以在不同的场景下使用,spring JDBC的性能更好,更适合管理域的sql语句,而mybatis则可以将sql语句批量的管理起来,还可以达到sql的重用,同时mybatis还帮你做了数据库的驱动注册加载,数据库连接的创建与销毁等数据库的管理可以让你更关注于业务,更适合在业务域使用。

6.1.1 Spring 中配置数据源:


6.1.1.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"
 xsi:schemaLocation="http://www.springframework.org/schema/beans 
 http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
6.1.1.2 配置数据源:
  1. 配置 C3P0 数据源:
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> 
	<property name="driverClass" value="com.mysql.jdbc.Driver"></property> 
	<property name="jdbcUrl" value="jdbc:mysql:///spring_day02"></property> 
	<property name="user" value="root"></property>
	<property name="password" value="1234"></property>
</bean>
  1. 配置 DBCP 数据源:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> 
	<property name="driverClassName" value="com.mysql.jdbc.Driver"></property> 
	<property name="url" value="jdbc:mysql:// /spring_day02"></property> 
	<property name="username" value="root"></property> 
	<property name="password" value="1234"></property>
</bean>
  1. 配置 Spring 内置数据源:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
	<property name="driverClassName" value="com.mysql.jdbc.Driver"></property> 
	<property name="url" value="jdbc:mysql:///spring_day02"></property> 
	<property name="username" value="root"></property> 
	<property name="password" value="1234"></property>
</bean>
6.1.1.3 将数据库连接的信息配置到属性文件中:

定义属性文件:

jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///spring_day02
jdbc.username=root
jdbc.password=123

引入外部的属性文件:

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
	<property name="location" value="classpath:jdbc.properties"/>
</bean>

同样也可以这样引入:

<context:property-placeholder location="classpath:jdbc.properties"/>

6.1.2 JdbcTemplate 的增删改查操作:


6.1.2.1 前期准备:
创建数据库:
create database spring_day02;
use spring_day02;
创建表:
create table account(
id int primary key auto_increment,
name varchar(40),
money float
)character set utf8 collate utf8_general_ci;
6.1.2.2 在 Spring 配置文件中配置 JdbcTemplate:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.springframework.org/schema/beans 
 http://www.springframework.org/schema/beans/spring-beans.xsd">
 
	<!-- 配置一个数据库的操作模板:JdbcTemplate --> 
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> 
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<!-- 配置数据源 --> 
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
		<property name="driverClassName" value="com.mysql.jdbc.Driver"></property> 
		<property name="url" value="jdbc:mysql:///spring_day02"></property> 
		<property name="username" value="root"></property> 
		<property name="password" value="1234"></property>
	</bean>
</beans>
6.1.2.3 插入使用:
public class JdbcTemplateDemo2 {
	public static void main(String[] args) {
		//1.获取 Spring 容器
		ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
		//2.根据 id 获取 bean 对象
		JdbcTemplate jt = (JdbcTemplate) ac.getBean("jdbcTemplate");
		//3.执行操作
		jt.execute("insert into account(name,money)values('eee',500)");
	} 
}
6.1.2.4 保存操作:
public class JdbcTemplateDemo3 {
	public static void main(String[] args) {
		//1.获取 Spring 容器
		ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
		//2.根据 id 获取 bean 对象
		JdbcTemplate jt = (JdbcTemplate) ac.getBean("jdbcTemplate");
		//3.执行操作
		//保存
		jt.update("insert into account(name,money)values(?,?)","fff",5000);
	} 
}
6.1.2.5 更新操作:
public class JdbcTemplateDemo3 {
	public static void main(String[] args) {
		//1.获取 Spring 容器
		ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
		//2.根据 id 获取 bean 对象
		JdbcTemplate jt = (JdbcTemplate) ac.getBean("jdbcTemplate");
		//3.执行操作
		//修改
		jt.update("update account set money = money-? where id = ?",300,6);
	} 
}
6.1.2.6 删除操作:
public class JdbcTemplateDemo3 {
	public static void main(String[] args) {
		//1.获取 Spring 容器
		ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
		//2.根据 id 获取 bean 对象
		JdbcTemplate jt = (JdbcTemplate) ac.getBean("jdbcTemplate");
		//3.执行操作
		//删除
		jt.update("delete from account where id = ?",6);
	} 
}
6.1.2.7 查询所有操作:
public class JdbcTemplateDemo3 {
	public static void main(String[] args) {
		//1.获取 Spring 容器
		ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
		//2.根据 id 获取 bean 对象
		JdbcTemplate jt = (JdbcTemplate) ac.getBean("jdbcTemplate");
		//3.执行操作
		//查询所有
		List<Account> accounts = jt.query("select * from account where money > ? ", new AccountRowMapper(), 500);
		for(Account o : accounts){
			System.out.println(o);
		} 
	} 
}

public class AccountRowMapper implements RowMapper<Account>{
	@Override
	public Account mapRow(ResultSet rs, int rowNum) throws SQLException {
		Account account = new Account();
		account.setId(rs.getInt("id"));
		account.setName(rs.getString("name"));
		account.setMoney(rs.getFloat("money"));
		return account;	
	}
}
6.1.2.8 查询一个操作:
  1. 使用 RowMapper 的方式(常用的方式):
public class JdbcTemplateDemo3 {
	public static void main(String[] args) {
		//1.获取 Spring 容器
		ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
		//2.根据 id 获取 bean 对象
		JdbcTemplate jt = (JdbcTemplate) ac.getBean("jdbcTemplate");
		//3.执行操作
		//查询一个
		List<Account> as = jt.query("select * from account where id = ? ", new AccountRowMapper(), 55);
		System.out.println(as.isEmpty()?"没有结果":as.get(0));
	} 
}
  1. 使用 ResultSetExtractor 的方式(不常用的方式):
public class JdbcTemplateDemo3 {
	public static void main(String[] args) {
		//1.获取 Spring 容器
		ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
		//2.根据 id 获取 bean 对象
		JdbcTemplate jt = (JdbcTemplate) ac.getBean("jdbcTemplate");
		//3.执行操作
		//查询一个
		Account account = jt.query("select * from account where id = ?",new AccountResultSetExtractor(),3);
		System.out.println(account);
	} 
}
6.1.2.9 查询返回一行一列操作:
public class JdbcTemplateDemo3 {
	public static void main(String[] args) {
		//1.获取 Spring 容器
		ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
		//2.根据 id 获取 bean 对象
		JdbcTemplate jt = (JdbcTemplate) ac.getBean("jdbcTemplate");
		//3.执行操作
		//查询返回一行一列:使用聚合函数,在不使用 group by 字句时,都是返回一行一列。最长用的就是分页中获取总记录条数
		Integer total = jt.queryForObject("select count(*) from account where money > ? ",Integer.class,500);
		System.out.println(total);
	} 
}

6.1.3 在 dao 中使用 JdbcTemplate:


6.1.3.1 准备实体类:
/**
* 账户的实体
*/
public class Account implements Serializable {
	private Integer id;
	private String name;
	private Float money;
	
	public Integer getId() {
		return id; 
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name; 
	}
	public void setName(String name) {
		this.name = name;
	}
	public Float getMoney() {
		return money; 
	}
	public void setMoney(Float money) {
		this.money = money;
	}
	
	@Override
	public String toString() {
		return "Account [id=" + id + ", name=" + name + ", money=" + money + "]";
	} 
}
6.1.3.2 第一种方式:在 dao 中定义 JdbcTemplate:

持久层接口:

/**
* 账户的接口
*/
public interface IAccountDao {
	/**
	* 根据 id 查询账户信息
	* @param id
	* @return
	*/
	Account findAccountById(Integer id);
	/**
	* 根据名称查询账户信息
	* @return
	*/
	Account findAccountByName(String name);
	/**
	* 更新账户信息
	* @param account
	*/
	void updateAccount(Account account);
}

持久层实现类:

/**
* 账户的持久层实现类
* 此版本的 dao,需要给 dao 注入 JdbcTemplate
*/
public class AccountDaoImpl implements IAccountDao {
	private JdbcTemplate jdbcTemplate;
	
	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}
	
	@Override
	public Account findAccountById(Integer id) {
		List<Account> list = jdbcTemplate.query("select * from account where id = ? ",new AccountRowMapper(),id);
		return list.isEmpty()?null:list.get(0);
	}
	
	@Override
	public Account findAccountByName(String name) {
		List<Account> list = jdbcTemplate.query("select * from account where name = ? ",new AccountRowMapper(),name);
		if(list.isEmpty()){
			return null; 
		}
		if(list.size()>1){
			throw new RuntimeException("结果集不唯一,不是只有一个账户对象");
		}
		return list.get(0);
	}
	
	@Override
	public void updateAccount(Account account) {
		jdbcTemplate.update("update account set money = ? where id = ? ",account.getMoney(),account.getId());
	} 
}

配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.springframework.org/schema/beans 
 http://www.springframework.org/schema/beans/spring-beans.xsd">
 
	<!-- 配置一个 dao --> 
	<bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl">
		<!-- 注入 jdbcTemplate --> 
		<property name="jdbcTemplate" ref="jdbcTemplate"></property>
	</bean>
	
	<!-- 配置一个数据库的操作模板:JdbcTemplate --> 
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> 
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<!-- 配置数据源 --> 
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
		<property name="driverClassName" value="com.mysql.jdbc.Driver"></property> 
		<property name="url" value="jdbc:mysql:///spring_day04"></property> 
		<property name="username" value="root"></property> 
		<property name="password" value="1234"></property>
	</bean>
</beans>

但我们可以看出这种方式存在一个问题:就是我们的 dao 有很多时,每个 dao 都有一些重复性的代码。

6.1.3.3 第二种方式:让 dao 继承 JdbcDaoSupport:

持久层接口与上面的一致,实现类做出一些改变:

/**
* 账户的持久层实现类
* 此版本 dao,只需要给它的父类注入一个数据源
*/
public class AccountDaoImpl2 extends JdbcDaoSupport implements IAccountDao {
	@Override
	public Account findAccountById(Integer id) {
		//getJdbcTemplate()方法是从父类上继承下来的。
		List<Account> list = getJdbcTemplate().query("select * from account where id = ? ",new AccountRowMapper(),id);
		return list.isEmpty()?null:list.get(0);
	}
	
	@Override
	public Account findAccountByName(String name) {
		//getJdbcTemplate()方法是从父类上继承下来的。
		List<Account> list = getJdbcTemplate().query("select * from account where name = ? ",new AccountRowMapper(),name);
		if(list.isEmpty()){
			return null; 
		}
		if(list.size()>1){
			throw new RuntimeException("结果集不唯一,不是只有一个账户对象");
		}
		return list.get(0);
	}
	
	@Override
	public void updateAccount(Account account) {
		//getJdbcTemplate()方法是从父类上继承下来的。
		getJdbcTemplate().update("update account set money = ? where id = ? ",account.getMoney(),account.getId());
	} 
}

配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.springframework.org/schema/beans 
 http://www.springframework.org/schema/beans/spring-beans.xsd">
 
	<!-- 配置 dao2 --> 
	<bean id="accountDao2" class="com.itheima.dao.impl.AccountDaoImpl2">
		<!-- 注入 dataSource --> 
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<!-- 配置数据源 --> 
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
		<property name="driverClassName" value="com.mysql.jdbc.Driver"></property> 
		<property name="url" value="jdbc:mysql:///spring_day04"></property> 
		<property name="username" value="root"></property> 
		<property name="password" value="1234"></property>
	</bean>
</beans>

注意:
第一种在 Dao 类中定义 JdbcTemplate 的方式,适用于所有配置方式(xml 和注解都可以)。
第二种让 Dao 继承 JdbcDaoSupport 的方式,只能用于基于 XML 的方式,注解用不了。

6.2 Spring 中的事务控制:


6.2.1 基于 XML 的声明式事务控制(配置方式):


6.2.1.1 环境搭建:
  1. 创建 spring 的配置文件并导入约束。
    注:此处需要导入 aop 和 tx 两个名称空间
<?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
 http://www.springframework.org/schema/aop 
 http://www.springframework.org/schema/aop/spring-aop.xsd">
</beans>
  1. 准备数据库表和实体类。
创建数据库:
create database spring_day04;
use spring_day04;
创建表:
create table account(
id int primary key auto_increment,
name varchar(40),
money float
)character set utf8 collate utf8_general_ci;
/**
* 账户的实体
*/
public class Account implements Serializable {
	private Integer id;
	private String name;
	private Float money;
	
	public Integer getId() {
		return id; 
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name; 
	}
	public void setName(String name) {
		this.name = name;
	}
	public Float getMoney() {
		return money; 
	}
	public void setMoney(Float money) {
		this.money = money;
	}
	
	@Override
	public String toString() {
		return "Account [id=" + id + ", name=" + name + ", money=" + money + "]"; 
	} 
}
  1. 编写业务层接口和实现类。
/**
* 账户的业务层接口
*/
public interface IAccountService {
	/**
	* 根据 id 查询账户信息
	* @param id
	* @return
	*/
	Account findAccountById(Integer id);//查
	/**
	* 转账
	* @param sourceName 转出账户名称
	* @param targeName 转入账户名称
	* @param money 转账金额
	*/
	void transfer(String sourceName,String targeName,Float money);//增删改
}
/**
* 账户的业务层实现类
*/
public class AccountServiceImpl implements IAccountService {
	private IAccountDao accountDao;
	
	public void setAccountDao(IAccountDao accountDao) {
		this.accountDao = accountDao;
	}
	
	@Override
	public Account findAccountById(Integer id) {
		return accountDao.findAccountById(id);
	}
	
	@Override
	public void transfer(String sourceName, String targeName, Float money) {
		//1.根据名称查询两个账户
		Account source = accountDao.findAccountByName(sourceName);
		Account target = accountDao.findAccountByName(targeName);
		//2.修改两个账户的金额
		source.setMoney(source.getMoney()-money);//转出账户减钱
		target.setMoney(target.getMoney()+money);//转入账户加钱
		//3.更新两个账户
		accountDao.updateAccount(source);
		int i=1/0;
		accountDao.updateAccount(target);
	} 
}
  1. 编写 Dao 接口和实现类。
/**
* 账户的持久层接口
*/
public interface IAccountDao {
	/**
	* 根据 id 查询账户信息
	* @param id
	* @return
	*/
	Account findAccountById(Integer id);
	/**
	* 根据名称查询账户信息
	* @return
	*/
	Account findAccountByName(String name);
	/**
	* 更新账户信息
	* @param account
	*/
	void updateAccount(Account account);
}
/**
* 账户的持久层实现类
* 此版本 dao,只需要给它的父类注入一个数据源
*/
public class AccountDaoImpl extends JdbcDaoSupport implements IAccountDao {
	@Override
	public Account findAccountById(Integer id) {
		List<Account> list = getJdbcTemplate().query("select * from account where id = ? ",new AccountRowMapper(),id);
		return list.isEmpty()?null:list.get(0);
	}
	
	@Override
	public Account findAccountByName(String name) {
		List<Account> list = getJdbcTemplate().query("select * from account where name = ? ",new AccountRowMapper(),name);
		if(list.isEmpty()){
			return null; 
		}
		if(list.size()>1){
			throw new RuntimeException("结果集不唯一,不是只有一个账户对象");
		}
		return list.get(0);
	}
	
	@Override
	public void updateAccount(Account account) {
		getJdbcTemplate().update("update account set money = ? where id = ? ",account.getMoney(),account.getId());
	} 
}
/**
* 账户的封装类 RowMapper 的实现类
*/
public class AccountRowMapper implements RowMapper<Account>{
	@Override
	public Account mapRow(ResultSet rs, int rowNum) throws SQLException {
		Account account = new Account();
		account.setId(rs.getInt("id"));
		account.setName(rs.getString("name"));
		account.setMoney(rs.getFloat("money"));
		return account;
	} 
}
  1. 在配置文件中配置业务层和持久层。
<!-- 配置 service --> 
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"> 
	<property name="accountDao" ref="accountDao"></property>
</bean>

<!-- 配置 dao --> 
<bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl">
	<!-- 注入 dataSource --> 
	<property name="dataSource" ref="dataSource"></property>
</bean>

<!-- 配置数据源 --> 
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">   
	<property name="driverClassName" value="com.mysql.jdbc.Driver"></property> 
	<property name="url" value="jdbc:mysql:///spring_day04"></property> 
	<property name="username" value="root"></property> 
	<property name="password" value="1234"></property>
</bean>
6.2.1.2 配置步骤:
  1. 配置事务管理器。
<!-- 配置一个事务管理器 --> 
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<!-- 注入 DataSource --> 
	<property name="dataSource" ref="dataSource"></property>
</bean>
  1. 配置事务的通知引用事务管理器。
<!-- 事务的配置 --> 
<tx:advice id="txAdvice" transaction-manager="transactionManager">
</tx:advice>
  1. 配置事务的属性。

属性:

  • read-only:是否是只读事务。默认 false,不只读。
  • isolation:指定事务的隔离级别。默认值是使用数据库的默认隔离级别。
  • propagation:指定事务的传播行为。
  • timeout:指定超时时间。默认值为:-1。永不超时。
  • rollback-for:用于指定一个异常,当执行产生该异常时,事务回滚。产生其他异常,事务不回滚。没有默认值,任何异常都回滚。
  • no-rollback-for:用于指定一个异常,当产生该异常时,事务不回滚,产生其他异常时,事务回滚。没有默认值,任何异常都回滚。
<!--在 tx:advice 标签内部 配置事务的属性 --> 
<tx:attributes>
	<tx:method name="*" read-only="false" propagation="REQUIRED"/>
	<tx:method name="find*" read-only="true" propagation="SUPPORTS"/>
</tx:attributes>
  1. 配置 AOP 切入点表达式。
<!-- 配置 aop --> 
<aop:config>
	<!-- 配置切入点表达式 --> 
	<aop:pointcut expression="execution(* com.itheima.service.impl.*.*(..))" id="pt1"/>
</aop:config>
  1. 配置切入点表达式和事务通知的对应关系。
<!-- 在 aop:config 标签内部:建立事务的通知和切入点表达式的关系 --> 
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"/>

6.2.2 基于注解的配置方式:


6.2.2.1 环境搭建:
  1. 创建 spring 的配置文件导入约束并配置扫描的包。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:aop="http://www.springframework.org/schema/aop"
 xmlns:tx="http://www.springframework.org/schema/tx"
 xmlns:context="http://www.springframework.org/schema/context"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="
http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans.xsd
 http://www.springframework.org/schema/aop
 http://www.springframework.org/schema/aop/spring-aop.xsd
 http://www.springframework.org/schema/tx 
 http://www.springframework.org/schema/tx/spring-tx.xsd
 http://www.springframework.org/schema/context 
 http://www.springframework.org/schema/context/spring-context.xsd">
 
	<!-- 配置 spring 创建容器时要扫描的包 --> 
	<context:component-scan base-package="com.itheima"></context:component-scan>
	
	<!-- 配置 JdbcTemplate-->
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> 
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<!-- 配置 spring 提供的内置数据源 --> 
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
		<property name="driverClassName" value="com.mysql.jdbc.Driver"></property> 
		<property name="url" value="jdbc:mysql://localhost:3306/spring_day02"></property> 
		<property name="username" value="root"></property> 
		<property name="password" value="1234"></property>
	</bean>
</beans>
  1. 创建数据库表和实体类。
    与上面 xml 的一致。
  2. 创建业务层接口和实现类并使用注解让 spring 管理。
/**
* 账户的业务层实现类
*/
@Service("accountService")
public class AccountServiceImpl implements IAccountService {
	@Autowired
	private IAccountDao accountDao;
	//其余代码和基于 XML 的配置相同
}
  1. 创建 Dao 接口和实现类并使用注解让 spring 管理。
/**
* 账户的持久层实现类
*/
@Repository("accountDao")
public class AccountDaoImpl implements IAccountDao {
	@Autowired
	private JdbcTemplate jdbcTemplate;
	//其余代码和基于 XML 的配置相同
}
6.2.2.2 配置步骤:
  1. 配置事务管理器并注入数据源。
<!-- 配置事务管理器 --> 
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
	<property name="dataSource" ref="dataSource"></property>
</bean>
  1. 在业务层使用@Transactional 注解。
@Service("accountService")
@Transactional(readOnly=true,propagation=Propagation.SUPPORTS)
public class AccountServiceImpl implements IAccountService {
	@Autowired
	private IAccountDao accountDao;
	
	@Override
	public Account findAccountById(Integer id) {
		return accountDao.findAccountById(id);
	}
	
	@Override
	@Transactional(readOnly=false,propagation=Propagation.REQUIRED)
	public void transfer(String sourceName, String targeName, Float money) {
		//1.根据名称查询两个账户
		Account source = accountDao.findAccountByName(sourceName);
		Account target = accountDao.findAccountByName(targeName);
		//2.修改两个账户的金额
		source.setMoney(source.getMoney()-money);//转出账户减钱
		target.setMoney(target.getMoney()+money);//转入账户加钱
		//3.更新两个账户
		accountDao.updateAccount(source);
		//int i=1/0;
		accountDao.updateAccount(target);
	} 
}
  1. 在配置文件中开启 spring 对注解事务的支持。
<!-- 开启 spring 对注解事务的支持 --> 
<tx:annotation-driven transaction-manager="transactionManager"/>
  1. 不使用 xml 的配置方式。
@Configuration
@EnableTransactionManagement
public class SpringTxConfiguration {
//里面配置数据源,配置 JdbcTemplate,配置事务管理器。在之前的步骤已经写过了。
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值