步骤:
1.xml中的配置
1.1.在xml中打开自动扫描包,扫描相关注解
1.2.在xml中声明事务管理器和将事务管理器交于spring管理
2.在目标类或方法上,使用注解@Transcational(编写事务详情)
第一步:确定目标(bean的方法):创建IAccountDao和AccountDaoImpl类
(1)IAccountDao接口
public interface IAccountDao {
//(存入)转入
public void in(String name,Double money);
//(取出)转出
public void out(String name,Double money);
}(2)AccountDaoImpl
//账户操作持久层
//技术方案:jdbctempate
/**
* @Repository("accountDao")
* 相当于容易中定义<bean id="accountDao" class="cn.itcast.spring.anntx.dao.AccountDaoImpl"/>
*/
@Repository("accountDao")
public class AccountDaoImpl extends JdbcDaoSupport implements IAccountDao {
/*
演示:注入数据源的错误方式:
//注入数据源
/*@Autowired
private DataSource dataSource;
//注入失败,@Autowired的原理是为属性生成setter方法通过setter方法注入,但是JdbcDaoSupport 类有setter方法方法且为最终方法,不可重写
注意:xml配置与注解注入数据源的区别:xml配置是在配置文件中注入数据源到dao,不生成setter方法,注解注入的@Autowired会底层生成setter方法,
*/
//注入数据源的正确方式:自定义方法,在方法内调用父类方法注入数据源
@Autowired //当初始化dao的时候,会调用该方法,通过set方法的形参注入数据源
public void setSuperDataSource(DataSource dataSource){ //方法名自定义
//调用父类的setDataSource方法,注入数据源
super.setDataSource(dataSource);
}
//(存入)转入
public void in(String name,Double money){
String sql="update t_account set money = money+ ? where name = ?";
super.getJdbcTemplate().update(sql, money,name);
}
//(取出)转出
public void out(String name,Double money){
String sql="update t_account set money = money- ? where name = ?";
super.getJdbcTemplate().update(sql, money,name);
}
}
创建IAccountService和AccountServiceImpl类
(1)IAccountService接口
public interface IAccountService {
void transfer(String outName,String inName,Double money);
}(2)AccountServiceImpl
//掌握操作的业务层
/**
* @Service("accountService")
* 相当于spring容器中定义:<bean id="accountService" class="cn.itcast.spring.anntx.service.AccountServiceImpl">
*/
@Service("accountService")
@Transactional //在类上添加事务管理,自动对类中所有的公有的方法添加事务
public class AccountServiceImpl implements IAccountService{
//注入dao
@Autowired
private IAccountDao accountDao;
//转账操作的业务逻辑
@Transactional //在方法上添加事务管理,事务管理只在此方法上
public void transfer(String outName,String inName,Double money){
//调用dao层
//先取出
accountDao.out(outName, money);
//异常
int d = 1/0;
//再转入
accountDao.in(inName, money);
}
@Transactional(readOnly=true) //在方法和类上同时定义了事务的属性,且属性值不同,局部会覆盖全局
public void findAccount(){
System.out.println("查询帐号的信息了");
}
}
第二步:创建applicationContext-tx.xml在applicationContext-tx.xml中配置:
<!-- 引入外部属性文件 -->
<context:property-placeholder location="classpath:db.properties" />
<!-- 配置数据源 -->
<!-- c3p0连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.className}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.user}" />
<property name="password" value="${jdbc.password}" />
</bean>
<!-- 1.配置注解扫描 -->
<context:component-scan base-package="cn.itcast.spring.anntx"/>
<!-- 事务管理 -->
<!-- 2.配置事务管理器(DataSource事务管理器) -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 注入数据源 -->
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 配置事务注解驱动 :识别事务的注解@transaction-manager:具体的平台事务管理器 -->
<!-- 默认的平台事务管理器的名字叫:transactionManager,如果与自定义的事务管理器id相同,transaction-manager="transactionManager"可以省略 -->
<!--3.将事务管理器交于spring-->
<tx:annotation-driven transaction-manager="transactionManager"/>
【注意】:方法与类添加事务管理:
(1)在需要管理事务的方法或者类上面 添加@Transactional 注解
(2)配置事务的定义属性信息,在注解中直接配置:
[扩展]
如果 @Transactional 标注在 Class 上面, 那么将会对这个 Class 里面所有的 public 方法都包装事务方法。等同于该类的每个公有方法都放上了@Transactional。
如果某方法需要单独的事务定义,则需要在方法上加@Transactional来覆盖类上的标注声明。 记住:方法级别的事务覆盖类级别的事务
//掌握操作的业务层
/**
* @Service("accountService")
* 相当于spring容器中定义:<bean id="accountService" class="cn.itcast.spring.anntx.service.AccountServiceImpl">
*/
@Service("accountService")
@Transactional() //会对该类中,所有的共有的方法,自动加上事务--全局的设置,默认是可写
public class AccountServiceImpl implements IAccountService{
//注入dao
@Autowired
private IAccountDao accountDao;
//转账操作的业务逻辑
@Transactional(readOnly=false)//在方法上添加事务
public void transfer(String outName,String inName,Double money){
//调用dao层
//先取出
accountDao.out(outName, money);
int d = 1/0;
//再转入
accountDao.in(inName, money);
}
@Transactional(readOnly=true) //使用局部覆盖全局的
public void findAccount(){
System.out.println("查询帐号的信息了");
}
}