一文搞懂 Spring 数据库事务操作!
作者 | 阿文,责编 | 郭芮
头图 | CSDN 下载自东方IC
出品 | CSDN(ID:CSDNnews)
Spring 事务的核心接口
PlatformTramsactionManager 主要用于管理事务,包括获取事务的状态、提交事务和回滚事务;
TramsactionDefinition 该接口是事务定义的对象,包括了获取事务的名称、隔离级别、事务的传播行为、超时时间、事务是否只读等;
TramsactionStatus 该接口是事务的状态,描述了某一个时间点事务状态信息,包括刷新事务、获取是否存在保存点、是否是新事务、是否回滚、设置事务回滚。
实例讲解
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
CREATE TABLE IF NOT EXISTS `user`(
`id` INT UNSIGNED AUTO_INCREMENT,
`username` VARCHAR(100) NOT NULL,
`password` VARCHAR(40) NOT NULL,
`jifen` int(10) NOT NULL,
PRIMARY KEY ( `id` ))ENGINE=InnoDB DEFAULT CHARSET=utf8;
MariaDB [spring_db]> select * from user;
+----+----------+----------+-------+
| id | username | password | jifen |
+----+----------+----------+-------+
| 1 | zhangsan | 123 | 1000 |
| 2 | lisi | 1234 | 1000 |
| 3 | wangwu | 1234 | 1000 |
+----+----------+----------+-------+
3 rows in set (0.000 sec)
package com.SpringDemo;
public class User {
private Integer id;
private String username;
private String password;
private Integer jifen;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setJifen(Integer jifen){
this.jifen = jifen;
}
public Integer getjifen() {
return jifen;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String toString() {
return "User [id=" + id + ", username=" + username + ", password=" + password + "]";
}
}
package com.SpringDemo;
import java.util.List;
public interface UserDao {
public int addUser(User user);
public int updateUser(User user);
public int deleteUser(int id);
//通过id查询用户
public User findUserById(int id);
//查询所有用户
public List<User> findAllUser();
public void transfer(String outUser,String inUser,Integer jifen);
}
package com.SpringDemo;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
public class UserDaoImpl implements UserDao {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@Override
public int addUser(User user) {
String sql="insert into user(username,password) value(?,?)";
Object[] obj=new Object[]{
user.getUsername(),
user.getPassword()
};
int num=this.jdbcTemplate.update(sql,obj);
return num;
}
@Override
public int updateUser(User user) {
String sql="update user set username=?,password=? where id=?";
Object[] params=new Object[]{
user.getUsername(),
user.getPassword(),
user.getId()
};
int num=this.jdbcTemplate.update(sql,params);
return num;
}
@Override
public int deleteUser(int id) {
String sql="delete from user where id=?";
int num=this.jdbcTemplate.update(sql,id);
return num;
}
@Override
public User findUserById(int id) {
String sql="select * from user where id=?";
RowMapper<User> rowMapper=new BeanPropertyRowMapper<User>(User.class);
return this.jdbcTemplate.queryForObject(sql,rowMapper,id);
}
@Override
public List<User> findAllUser() {
String sql="select * from user";
RowMapper<User> rowMapper=new BeanPropertyRowMapper<User>(User.class);
return this.jdbcTemplate.query(sql,rowMapper);
}
@Override
public void transfer(String outUser, String inUser, Integer jifen) {
// 赠送积分
this.jdbcTemplate.update("update user set jifen=jifen+? where username=?",jifen,inUser);
// 模拟系统运行时的突发性问题
int i =1/0;
//赠送出积分
this.jdbcTemplate.update("update user set jifen=jifen-? where username=?",jifen,outUser);
}
}
<?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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
<!--1.配置数据源 -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<!--数据库驱动 -->
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<!--连接数据库的ur1 -->
<property name="url" value="jdbc:mysql://192.168.10.128:3306/spring_db" />
<!--连接数据库的用户名 -->
<property name="username" value="root" />
<!--连接数据库的密码 -->
<property name="password" value="123456" />
</bean>
<!--2.配置JDBC模板 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--默认必须使用数据源 -->
<property name="dataSource" ref="dataSource" />
</bean>
<!--3.定义id为userDao的Bean -->
<bean id="userDao" class="com.SpringDemo.UserDaoImpl">
<!--将 jdbcTemplate注入到 userDao实例中 -->
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>
<!--4.事务管理器,依赖于数据源 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--5.注册事务管理驱动 -->
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
</beans>
@Override
@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,
readOnly = false)
public void transfer(String outUser, String inUser, Integer jifen) {
// 赠送积分
this.jdbcTemplate.update("update user set jifen=jifen+? where username=?",jifen,inUser);
// 模拟系统运行时的突发性问题
int i =1/0;
//赠送出积分
this.jdbcTemplate.update("update user set jifen=jifen-? where username=?",jifen,outUser);
}
@Transactional 除了 DEFAULT,还有其他属性,我们可以在Isolation 这个类中看到相对于的定位 @Transactional 注解也可以添加到类级别上。当把@Transactional 注解放在类级别时,表示所有该类的公共方法都配置相同的事务属性信息。
public enum Isolation {
DEFAULT(-1),
READ_UNCOMMITTED(1),
READ_COMMITTED(2),
REPEATABLE_READ(4),
SERIALIZABLE(8);
private final int value;
private Isolation(int value) {
this.value = value;
}
public int value() {
return this.value;
}
}
public enum Propagation {
REQUIRED(0),//表示当前方法必须运行在一个事务环境中,如果存在就直接使用,否则开启一个新的事务执行该方法
SUPPORTS(1),//如果当前方法处于事务环境中则使用,否则不使用事务
MANDATORY(2),//表示该方法的线程必须在事务中否则抛出异常
REQUIRES_NEW(3), //要求在新事务中执行,如果已经在事务中了则先暂停然后启动新事务执行,如果不在则启动一个新事务后执行
NOT_SUPPORTED(4), //不支持当前事务,总是以非事务状态执行,如果调用该方法的线程处于事务中泽先暂停然后执行
NEVER(5), //不支持当前执行的方法在事务中,如果在抛出异常
NESTED(6); //即便当前执行的方法在事务中也会启动一个新事务,然后执行该方法
private final int value;
private Propagation(int value) {
this.value = value;
}
public int value() {
return this.value;
}
}
package com.SpringDemo;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TransactionTest {
public static void main(String[] args) {
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = (UserDao) applicationContext.getBean("userDao");
userDao.transfer("zhangsan","lisi",100);
System.out.println("赠送积分成功");
}
}
Exception in thread "main" java.lang.ArithmeticException: / by zero
MariaDB [spring_db]> select * from user;
+----+----------+----------+-------+
| id | username | password | jifen |
+----+----------+----------+-------+
| 1 | zhangsan | 123 | 1000 |
| 2 | lisi | 1234 | 1000 |
| 3 | wangwu | 1234 | 1000 |
+----+----------+----------+-------+
3 rows in set (0.000 sec)
MariaDB [spring_db]> select * from user;
+----+----------+----------+-------+
| id | username | password | jifen |
+----+----------+----------+-------+
| 1 | zhangsan | 123 | 900 |
| 2 | lisi | 1234 | 1100 |
| 3 | wangwu | 1234 | 1000 |
+----+----------+----------+-------+
3 rows in set (0.000 sec)
【END】
☞
今日福利:评论区留言入选,可获得价值299元的「2020 AI开发者万人大会」在线直播门票一张。 快来动动手指,写下你想说的话吧。