jOOQ 事务失效

12 天前
 wuhunyu

如题,我在使用 jOOQ 的时候,事务无法正常生效,无论是声明式事务还是编程式事务

当我以为是代码问题时,我换回了 mybatis ,发现事务是正常的

使用编程式事务时,大致代码如下

@Service("userService4Jooq")
@RequiredArgsConstructor
@Slf4j
public class UserService4Jooq {

    private final TUserDao userDao;

    @Transactional(rollbackFor = Exception.class)
    public Integer insert(final Long userId, final String userName) {
        final TUserRecord tUserRecord = new TUserRecord();
        tUserRecord.setId(userId);
        tUserRecord.setUserName(userName);
        final TUser tUser = tUserRecord.into(TUser.class);
        userDao.insert(tUser);
        return 1;
    }

    @Transactional(readOnly = true)
    public TUser selectById(final Long userId) {
        return userDao.fetchOneById(userId);
    }

    @Transactional(rollbackFor = Exception.class)
    public TUser insertRetuning(final Long userId, final String userName) {
        this.insert(userId, userName);
        return this.selectById(userId);
    }

    @Transactional(rollbackFor = Exception.class)
    public TUser insertRetuningThrow(final Long userId, final String userName) {
        final TUser tUser = this.insertRetuning(userId, userName);
        // TODO: 手动异常,待删除
        int i = 10 / 0;
        return tUser;
    }

}

完整的样例代码可以访问这里

888 次点击
所在节点    程序员
6 条回复
Gilgamesh7
12 天前
2 种框架调用方式不一样,jooq 事务注解是基于 AOP 的,同一个类会有自调用问题,事务不生效 ,mybatis 是动态代理机制调用的,可以生效,把这个逻辑拆成 2 个类,应该就可以了
fms
12 天前
可以把 org.springframework.jdbc 的 debug 级别日志打开,好找问题
wuhunyu
12 天前
@Gilgamesh7 不管是 jooq 还是 mybatis ,示例中都是使用 spring 的 @Transactional 注解来声明事务的。我的代码写的有一些歧义,但事务应该都要能正常生效才对。自调用是可能导致事务失效,但自调用的方法自身是已经开启了事务的,那么事务就应该继续生效才对。现在我换用了 jooq 的事务方法使用编程式事务,测试代码如下
```java
@Test
@DisplayName("jooq 编程式事务")
@Order(5)
public void testJooqExceptionByProgrammatic() {
TUser tUser = null;
try {
// 开启事务
tUser = dslContext.transactionResult(() -> {
return userService4Jooq.insertRetuningThrow(userId4Jooq, userName4Jooq);
});
} catch (Exception e) {
// 不需要关注此异常
}

Assertions.assertNull(tUser, "事务回滚失败");
}
```
事务可以正常运行,插入的结果正常回滚了

但声明式事务还不清楚是什么原因失效了
wuhunyu
12 天前
@fms 好的,明天摸鱼的时候 debug 调试看看
fantasy0v0
11 天前
把你在 DataSourceConfig 中自己配置的删除掉就正常了。
wuhunyu
11 天前
@fantasy0v0
嗯,我之前没有使用 `spring-boot-starter-jooq` 启动器,而是单独引入的 `jooq` 依赖。直接删除那部分配置肯定是不行的。

换成引入 `spring-boot-starter-jooq` 之后,把自己的配置删除确实可以了。

不过我发现另一个问题是默认情况下使用 spring 的事务是正常的,但换用 jooq 自身的事务 api (比如 `dslContext.transaction`),就出现异常了。具体异常提示是 `Cannot use ContextTransactionalCallable with TransactionProvider of type class org.springframework.boot.autoconfigure.jooq.SpringTransactionProvider`。此时我还需要手动将 `org.jooq.TransactionProvider` 的实现从 `org.springframework.boot.autoconfigure.jooq.SpringTransactionProvider` 换成 `org.jooq.impl.ThreadLocalTransactionProvider` 才行

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://tanronggui.xyz/t/1106864

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX