【问题标题】:MyBatis without Spring, transaction using provided connectionMyBatis 没有 Spring,事务使用提供的连接
【发布时间】:2020-04-04 06:38:45
【问题描述】:

我正在使用没有 Spring 的 MyBatis。我还必须使用另一个 API 提供的 JDBC 连接。

所以我正在像这样创建我的 SqlSession:

    Connection conn = //... provided by some API
    LOGGER.debug("Connection autocommit: " + conn.getAutoCommit()); // Autocommit is true by default
    conn.setAutoCommit(false); // So I set it to false first
    LOGGER.debug("Connection autocommit after: " + conn.getAutoCommit()); // It is now false
    return factory.openSession(conn);

然后在我的代码中:

    try (SqlSession session = ...) {
        // Invoke mapper method here
        session.commit();
    } catch (Exception ex) {
        session.rollback();
        throw ex;
    }

但是,我发现调用 session.commit() 什么都不做(即没有找到关于提交的日志),并且确实没有提交更改。 MyBatis 的 commit() 似乎由于某种原因被忽略了。

如果我不强制 autocommit 为 false,则将提交更改(无需调用 session.commit()),但我也无法回滚错误。

我的 SqlSessionFactory 是这样创建的:

configuration = new Configuration();
configuration.setDatabaseId(SQLSERVER_DATABASE_ID);                 
configuration.addMapper(ApprovalHierarchyMapper.class);     
factory = new SqlSessionFactoryBuilder().build(configuration);

如何在没有 Spring 和提供的 JDBC 连接的情况下实现编程控制的事务?

【问题讨论】:

    标签: mybatis


    【解决方案1】:

    我认为这是因为我没有为 SqlSessionFactory 的 cosnstructor 提供环境导致了这种怪异。 Environment 包含对 TransactionManager 的引用。

    所以我尝试添加 Apache Commons Pool 和 DBCP,并使用虚拟 BasicDataSource 和 JdbcTransactionManager 来构建环境。但是我发现代码确实会尝试连接到 BasicDataSource,但我没有有效的 URL/登录名/密码,因为我从 API 获取连接。

    然后我尝试调用 session.getConnection.commit()/rollback() 而不是 session.commit()/rollback()。那行得通。

    这是由于我以编程方式构建配置引起的,我必须这样做,因为我的程序是软件的插件,并且某些数据只有在我访问插件上下文时才能在运行时访问。

    【讨论】:

      【解决方案2】:

      我刚刚进行了测试,session.commit() 按预期工作。

      SqlSessionFactory 创建如下。

      Environment env = new Environment("development",
        new JdbcTransactionFactory(), new UnpooledDataSource());
      Configuration config = new Configuration(env);
      config.addMapper(YourMapper.class);
      SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(config);
      
      • 使用JdbcTransactionFactory 代替默认的ManagedTransactionFactory
      • UnpooledDataSource 不会被使用。

      调用映射器方法的部分看起来与您的示例相同。

      con.setAutoCommit(false);
      try (SqlSession session = sqlSessionFactory.openSession(con)) {
        YourMapper mapper = session.getMapper(YourMapper.class);
        // Invoke mapper methods here
        session.commit();
      }
      

      抛出异常时回滚事务。

      【讨论】:

        猜你喜欢
        • 2020-03-16
        • 1970-01-01
        • 2018-09-24
        • 2020-02-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-07
        相关资源
        最近更新 更多