事务操作
1、创建数据库表,添加记录。
2、创建service,搭建dao,完成对象的创建和注入关系。
(1)在service中注入dao,在dao中注入JDBCTemplate,在JDBCTemplate中注入DataSource
@Service
public class UserService {
@Autowired
private UserDao userDao;
}
@Repository
public class UserDaoImpl implements UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
}
<!--jdbcTemplate对象-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--注入DataSource-->
<property name="dataSource" ref="dataSource"></property>
</bean>
3、在Dao中创建两个方法,多钱和少钱的方法,在service中创建(转账)方法
@Service
public class UserService {
@Autowired
private UserDao userDao;
public void accountMoney() {
userDao.reduceMoney();
//模拟异常
//int a=10/0;
userDao.addMoney();
}
}
@Repository
public class UserDaoImpl implements UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public void reduceMoney() {
String sql = "update t_account set money=money-? where username=?";
jdbcTemplate.update(sql, 10, "lucy");
}
@Override
public void addMoney() {
String sql = "update t_account set money=money+? where username=?";
jdbcTemplate.update(sql, 10, "mary");
}
}
有异常
@Service
public class UserService {
@Autowired
private UserDao userDao;
public void accountMoney() {
userDao.reduceMoney();
//模拟异常
//int a=10/0;
userDao.addMoney();
}
}
使用事务的编程式事务管理方式解决上述的异常问题。
try{
//第一步,开启事务,
//第二步,进行业务操作
//第三步,若无发生异常,提交事务
}catch (Exception e){
//第四步,若出现异常,事务回滚。
}
事务操作(Spring事务管理介绍)
1、事务添加到javaee三层结构里面Service层(业务逻辑层)
2、在Spring进行事务管理操作
(1)编程式事务管理(上述)
(2)声明式事务管理:基于注解;基于xml配置文件。底层就是AOP原理
3、Spring中事务管理API。
(1)提供一个接口,代表书屋管理器,接口针对不同框架提供不同的实现类
事务操作(注解声明式事务管理)
1、在Spring配置文件中配置事务管理器
<!--创建事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入数据源-->
<property name="dataSource" ref="dataSource"></property>
</bean>
2、在Spring配置文件中开启事务注解。
1)Spring配置文件引入命名空间 tx
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:tx="http://www.springframework.org/schema/tx"
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
2)开始事务注解
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
3、在Service类中,添加事务注解
@Transactional加到类上面,则类中所有方法都添加了注解
@Transactional加到方法上面,则只是该方法加了注解。
@Service
@Transactional
public class UserService {
事务操作(声明式事务管理参数配置)
propagation:事务传播行为(有事务的方法调用了没事务的方法,或者其他情况多事务都叫事务传播行为) REQUIRED和REQUIRED_NEW。
ioslation:事务隔离级别
事务有一个特性叫隔离性,在多事务之间不会产生影响,不考虑隔离性就会产生问题:
脏读问题:一个事物未提交读取到另一个未提交事物的数据。A和B都要读数据100,A把100改为200后,B再读就是200了,然后A又回滚了。这时B读的数据就是脏读。
不可重复读现象:一个未提交的事务读取到另一个提交事务修改数据
幻读:一个未提交的事务读取到另一个提交事务添加数据
解决上述三个问题:通过设置事务的隔离级别:
timeout:超时时间。事务必须在一定时间内提交,否则就会回滚。单位:秒
readOnly:是否只读。
读:查询。写:增删改
readOnly默认为false,表示可以查询,也可以增删改。
把readOnly设置为true,只能查询
rollbackFor:回滚
设置出现哪些异常时进行回滚
noRollbackFor:不会滚
设置出现哪些异常时不进行回滚
事务操作(XML声明式)
1、xml文件配置
<!-- 1创建事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入数据源-->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--2 配置通知-->
<tx:advice id="txadvice">
<!--指定下那种规则的方法下添加事务-->
<tx:attributes>
<tx:method name="accountMoney" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!--3 配置切入点和切面-->
<aop:config>
<!--配置切 入点-->
<aop:pointcut id="pt" expression="execution(* spring5_2.service.UserService.*(..))"/>
<!--配置切面-->
<aop:advisor advice-ref="txadvice" pointcut-ref="pt"></aop:advisor>
</aop:config>
配置事务管理器
配置通知(增强的部分)
配置切入点和切面
事务操作(完全注解方式,声明式事务管理)
1、创建配置类,能完全替换xml了。删除xml都可以
package config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
import java.util.DoubleSummaryStatistics;
@Configuration//配置类
@ComponentScan(basePackages = " ")// 组件扫描
@EnableTransactionManagement //开启事务
public class Txconfig {
@Bean
public DruidDataSource getDruidDataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/user_db?serverTimezone=UTC");
dataSource.setUsername("root");
dataSource.setPassword("root");
return dataSource;
}
@Bean
public JdbcTemplate getJdbcTemplate(DataSource dataSource) {
//到IOC容器中根据类型找到DataSource
JdbcTemplate jdbcTemplate = new JdbcTemplate();
//注入dataSource
jdbcTemplate.setDataSource(dataSource);
return jdbcTemplate;
}
@Bean
public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource) {
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource);
return transactionManager;
}
}