mybatis中SqlSession异常回滚

一、SqlSession介绍

SqlSessionFactory

SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由对它进行清除或重建。使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建 SqlSessionFactory 被视为一种代码“坏味道(bad smell)”。因此 SqlSessionFactory 的最佳范围是应用范围。有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。

SqlSession

每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的范围是请求或方法范围。绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。也绝不能将 SqlSession 实例的引用放在任何类型的管理范围中,比如 Serlvet 架构中的 HttpSession。如果你现在正在使用一种 Web 框架,要考虑 SqlSession 放在一个和 HTTP 请求对象相似的范围中。换句话说,每次收到的 HTTP 请求,就可以打开一个 SqlSession,返回一个响应,就关闭它。这个关闭操作是很重要的,你应该把这个关闭操作放到 finally 块中以确保每次都能执行关闭。

二、openSession、commit、rollback等方法

方法名作用
openSession(boolean)开启一个数据库会话,并返回一个会话对象sqlSession,参数表示该会话update,insert,delete操作是否自动提交
commitSqlSession的方法,底层调Executor的实现,提交当前会话的所有update,insert,delete操作
rollbackSqlSession的方法,回滚当前会话的操作

三、测试SqlSession异常回滚

1.事先填充好的数据
sd
2.测试代码

SqlSession session = null;
try{
    session = getSqlSessionTemplate().getSqlSessionFactory().openSession(false);
    FmEventOverview feo = new FmEventOverview();
    feo.setId(3);
    feo.setStatus(8);
    session.update(nameSpace+"updateByPrimaryKeySelective", feo);
    feo.setId(4);
    session.update(nameSpace+"updateByPrimaryKeySelective", new Object());
    session.commit();
}catch(Exception e){
    session.rollback();
    throw e;
}finally{
    session.close();
}

测试方法是,更新上面那两条ID为3和4且状态都为3的记录,修改状态为8,在第二个update的时候传入一个new Object()对象,这样会导致数据库报错,测试回滚结果,期望结果是两条记录状态都不改变,然鹅。。。
jg
不知道为什么,第一个update成功了,而且后台爆出了找不到属性的异常:

###Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'vendor' in 'class java.lang.Object'
at org.jboss.resteasy.core.SynchronousDispatcher.handleApplicationException(SynchronousDispatcher.java:365)
at org.jboss.resteasy.core.SynchronousDispatcher.handleException(SynchronousDispatcher.java:233)

那么至少可以确定,直接使用sqlSession.rollback()回滚操作是没有效果的。

四、解决方法

1.网上比较常见的是通过配置spring事务管理->Spring之事务Transaction管理
2.查看SqlSession代码可以看到,其默认实现类DefaultSqlSession中的getConnection方法:

public Connection getConnection() {
   try {
     return executor.getTransaction().getConnection();
   } catch (SQLException e) {
     throw ExceptionFactory.wrapException("Error getting a new connection.  Cause: " + e, e);
   }
 }

可以获取到事务化的数据库连接,然后在connection的基础上对事务回滚做处理是否可行?同样做一个测试:

SqlSession session = null;
Savepoint savepoint = null;
Connection conn = null;
try{
    session = getSqlSessionTemplate().getSqlSessionFactory().openSession(false);
    conn = session.getConnection();
    conn.setAutoCommit(false);
    savepoint = conn.setSavepoint();
    FmEventOverview feo = new FmEventOverview();
    feo.setId(eventOverviewId);
    feo.setStatus(8);
    session.update(nameSpace+"updateByPrimaryKeySelective", feo);
    feo.setId(2);
    session.update(nameSpace+"updateByPrimaryKeySelective", new Object());
    conn.commit();
}catch(Exception e){
    try {
        conn.rollback(savepoint);
    } catch (SQLException e1) {
        throw e1;
    }
    throw e;
}finally{
    session.close();
}

获取到数据库连接后再进行update操作前设置一个保存点savepoint(ORACLE数据库有savepoint概念,用于数据库管理员误操作或者修改操作回滚使用),当第二个update报出异常的时候捕捉到一样并对事务进行回滚到当前savepoint。
结果仍旧报异常,但是两条数据都没有更新,说明回滚操作起作用了。不知道是不是oracle数据库的原因,sqlSession的rollback确实是没有效果的,mysql暂时接触比较少,如果有不对或者需要补充的地方希望批评指正。

  • 9
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: MyBatisSqlSession的作用是提供了与数据库交互的方法,包括查询、插入、更新、删除等操作。SqlSessionMyBatis的核心接口之一,它提供了许多方法来执行SQL语句,包括selectOne、selectList、insert、update、delete等。SqlSession还提供了事务管理的方法,可以控制事务的提交和回滚。通过SqlSession,我们可以方便地与数据库进行交互,实现数据的增删改查等操作。 ### 回答2: Mybatis是一种基于Java的数据访问框架,旨在为开发人员提供更加直观、自然的持久层编程体验。其核心组件包括SqlSessionFactory、SqlSession、Mapper和XML映射文件等。其SqlSessionMybatis框架的一个核心组件,它主要负责与数据库进行交互。 SqlSession是一个面向用户的数据库会话,用于执行SQL语句、提交事务、获取Mapper接口等操作。在Mybatis框架,每次需要访问数据库时,开发人员都需要通过SqlSessionFactory创建一个SqlSession对象,并在操作完成后关闭该对象。SqlSession对象本身不是线程安全的,因此需要在每个线程创建一个新的SqlSession对象。 SqlSession的主要作用如下: 1. 执行SQL语句:SqlSession可以执行各种SQL语句,包括增删改查等操作。通过SqlSession的selectOne、selectList、insert、update和delete等方法可以执行不同类型的SQL语句,并获取执行结果。 2. 提交事务:SqlSession可以控制事务的提交和回滚。在默认情况下,每个SqlSession都是自动提交事务的,但是可以通过SqlSession的commit和rollback方法手动提交或回滚事务。 3. 获取Mapper接口:SqlSession可以获取Mapper接口,使得开发人员可以通过接口方式来执行SQL语句,并实现Java与数据库的无缝对接和映射。SqlSession的getMapper方法可以获取Mapper接口的实例,开发人员可以直接调用Mapper接口的方法进行数据操作。 总之,SqlSessionMybatis框架的一个重要组件,它可以实现与数据库的交互,执行SQL语句、提交事务、获取Mapper接口等操作,是实现Mybatis持久层开发的核心组件之一。 ### 回答3: Mybatis是一种优秀的持久层框架,它的主要作用是将Java对象与关系型数据库的数据进行映射,使得Java代码可以通过自己熟悉的语言来实现对关系型数据库的操作。在Mybatis框架SqlSession是一个线程安全的对象,代表与数据库的一次会话,其主要作用如下: 1. 数据库的CRUD操作:SqlSession提供了insert()、update()、delete()、selectOne()、selectList()等方法,可以直接通过Java代码对关系型数据库进行增、删、改、查等操作。 2. 管理事务:SqlSession可以控制事务的开启、提交、回滚等操作,保证数据的一致性和完整性。 3. 缓存管理:SqlSession有一级缓存和二级缓存,能够提高SQL查询的性能,在使用时应注意缓存的清空和刷新。 4. Mapper接口的实现:SqlSession可以将Mapper接口通过动态代理进行实现,使得Java代码不再需要手动实现Mapper接口的方法,从而简化了代码的编写。 总之,SqlSessionMybatis框架的一个重要组件,通过它可以与数据库进行交互,并且具有良好的事务控制和缓存管理功能,可以在一定程度上提高程序的性能和可维护性。在Mybatis的开发,熟练掌握SqlSession的使用是非常重要的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值