其他分享
首页 > 其他分享> > Spring处理数据池的事务回滚

Spring处理数据池的事务回滚

作者:互联网

为什么使用事务处理?

  在我们进行操作连表操作时,当我们在数据访问层处理数据库时,若是有一方有错误的地方。按理来说我们是不希望另一张表插入数据。

这时就就需要我们在我们业务逻辑层去进行操作对事务进行出来,来实现一方错都不能实现对数据的操作。

  (一)通常情况下:

  1、我们在da层的实现层中手动加一出错误(int i=1/0):

  

@Repository("userDao")
//@Scope("singleton")
public class UserDaoImpl implements UserDao {

@Resource(name = "dataSource")
private DataSource dataSource;

@Resource
private TManager tManager;

public void insert(User user) throws SQLException {
// 正常情况
Connection connection = dataSource.getConnection();
// 使用事务回滚
// Connection connection = tManager.getConnection();
System.out.println(connection);
PreparedStatement statement = connection.prepareStatement("insert into spring_res(name,password) values (?,?)");
statement.setString(1,user.getName());
statement.setString(2,user.getPassword());
statement.executeUpdate();

}

public void insert(SpringCha springCha) throws SQLException {
// 正常情况
Connection connection = dataSource.getConnection();
// 使用事务回滚
// Connection connection = tManager.getConnection();
System.out.println(connection);
PreparedStatement statement = connection.prepareStatement("insert into spring_cha(habit,hobby) values (?,?)");
statement.setString(1,springCha.getHabit());
statement.setString(2,springCha.getHobby());
int i=1/0;
statement.executeUpdate();

}
}

  2、而在业务逻辑层:

@Service("userService")
public class UserServiceImpl implements UserService {


@Resource(name = "userDao")//这个相当于上面两个的
private UserDao userDao;


@Resource
private TManager tManager;
public void inserts(User user) throws SQLException {
// try {
// tManager.closeCommit();
userDao.insert(user);
SpringCha springCha = new SpringCha();
springCha.setHabit("先吃再睡");
springCha.setHobby("吃喝睡");
userDao.insert(springCha);
// tManager.commit();
// } catch (SQLException e) {
// tManager.rollBack();
// e.printStackTrace();
// }
}
}

在操作中注释的是后续写的事务管理器用来解决上面的错误带来的问题

  3、在使用SpringJunit来写一个测试类

 @Resource
private UserService userService;
// @Resource
// private User user;
@Test
public void testInsert() throws SQLException {
User user = new User();
user.setName("枫");
user.setPassword("201619");
userService.inserts(user);
}

在运行测试用例后,会出现正常的报错(i=1/0),但是数据库中两张表,一张是把数据插入的另一张没有。

  (二)进行事务处理

  1、先编写一个事务控制器,来处理上面的问题

@Component
public class TManager {

@Resource
private DataSource dataSource;

// 用于创建连接得ThreadLocal
private ThreadLocal<Connection> local= new ThreadLocal<Connection>();

/**
* 基于Druid连接池获取连接
* @return
* @throws SQLException
*/
public Connection getConnection() throws SQLException {
// dao方法在获取连接的时候判断是否存在连接
if (local.get()!=null){
return local.get();
}
// 创建新的连接
Connection connection = dataSource.getConnection();
// 创建新的连接可能还被使用,所以把新的连接进行保存
local.set(connection);
return connection;
}

/**
*
* @throws SQLException
*/
public void closeCommit() throws SQLException {
getConnection().setAutoCommit(false);
}
/**
*提交事务
* @throws SQLException
*/
public void commit() throws SQLException {
getConnection().commit();
}

/**
*回滚事务
* @throws SQLException
*/
public void rollBack() throws SQLException {
getConnection().rollback();
}

}

  2、在数据访问层不改动下去业务逻辑层对其进行改动处理

try {
tManager.closeCommit();
userDao.insert(user);
SpringCha springCha = new SpringCha();
springCha.setHabit("先吃再睡");
springCha.setHobby("吃喝睡");
userDao.insert(springCha);
tManager.commit();
} catch (SQLException e) {
tManager.rollBack();
e.printStackTrace();
}

  3、可以直接使用刚的测试用例;

总结:

一般来说我们在使用数据源进行操作数据库时,一般是自动进行提交事务,当我想使用手动进行提交时,需要使用Connection.setAutoCommit(false) 可以阻止自动提交 。

java使用事务非常简单,首先调用conn.setAutoCommit(boolean b)方法,传入一个false,这样将不会自动提交,而需要使用conn.commit()方法,手动提交事务,当然只有在确认两个步骤都没有出错的情况下,才能提交,这样才能保证整个操作的完整性,一旦出错,使用conn.rollback()方法,回滚事务,这样的话,整个事务都将不被提交。那么如何判断有没有出错呢,非常简单,执行数据库操作的方法,都会抛出java.sql.SQLException,所以需要使用try……catch语句块捕获异常,在catch块中,使用conn.rollback()回滚事务即可。

       在数据库调用的javabean中conn.setAutoCommit()的功能是每执行一条SQL语句,就作为一次事务提交。但一般在项目中很有可能需要执行多条SQL语句作为一个事务。若有一个执行不成功,就会rollback();

 

一般来讲,大家对数据库中的表单,主要是增、删、改、查 这四个操作,如果你的程序当中,遇到一次业务逻辑需要两次或两次以上的对相同数据表的增删改操作,那么,为了数据的一致性,(或者具体说,在你的一次业务逻辑的处理过程中,其他(线程或程序或业务处理)的对相同数据的相同两次查询所得结果相同。)我们会利用数据库的事务操作,将一次业务逻辑所包含的所有操作封装在一个事务里,一次将多个操作进行提交。

而conn的setAutoCommit方法是指,在事务当中,是否执行一条语句就自动提交一次。

想在一个事务里进行多个操作。就必然将setAutoCommit的参数设置成false,在多个操作的最后调用conn.commit()方法,进行手动提交

 

(setAutoCommit(参数))参数:true和false

 

假设如下:

1 数据库一个表格有50条记录

2 你设置参数为false

则在你执行整个查询SQL期间,一直是没有事务的,那么如果你的查询用到了一些函数,这些函数包含了多个查询语句,那么有可能会出现不一致的情况。

也就是说,函数、存储过程等,他们都将运行在非事务的环境下。

而你设置为true,则没有任何问题了,读一致性将保证不会出现问题。

标签:回滚,Spring,事务,springCha,connection,SQLException,user,throws
来源: https://www.cnblogs.com/qinsir817/p/16096035.html