首页 > 解决方案 > 多个存储库上的 JOOQ @Transactional

问题描述

情况:

我已经安排了 15 分钟的长期任务。它重新生成 2 个表。我想在 ONE 交易中进行,但是对于大量的 repo 调用,使用 @Transational 的 repo 调用有 2 个不同的交易。

这是一个带有 postgres 的 spring boot 2 项目。

回购协议是否可能有不同的连接?

(我删除并简化了一些 DI。)

代码示例:

@Scheduled(...)
public class ScheduledTaskRunner
{
    @Transactional
    public void run()
    {
        aService.parseXML();
        bService.parseCSV();
    }
}

@Service
public class AService
{
    public function parseXML()
    {
         for (Node node : parserMethodSomewhere())
         {
            aRepository.save(node.getDataA(), node.getDataB());
         }
    }
}

@Service
public class BService
{
    public function parseCSV()
    {
         for (Node node : parserMethodSomewhere())
         {
            bRepository.save(node.getDataA(), node.getDataB());
         }
    }
}

@Service
public class ConnectionService
{
    @Autowired
    private DataSource dataSource;
    private Connection connection = null;

    public Connection getConnection() throws SQLException
    {
        if (null == connection)
        {
            connection = dataSource.getConnection();
        }

        return connection;
    }
}

@Service
public class JooqService
{
    @Autowired
    private Connection connection;
    private DSLContext dslContext = null;

    public DSLContext createQueryBuilder()
    {
        if (null == dslContext)
        {
           this.dslContext = DSL.using(connection, SQLDialect.POSTGRES);
        }

        return dslContext;
    }
}

@Repository
public abstract class AbstractRepository
{
    @Autowired
    private JooqService jooqService;

    DSLContext createQueryBuilder()
    {
        return jooqService.createQueryBuilder();
    }
}

public function ARepository extends AbstractRepository
{
    public function save(int a, int b)
    {
        createQueryBuilder().insertInto(table, table.a, table.b).values(a, b).execute();
    }
}

public function BRepository extends AbstractRepository
{
    public function save(int a, int b)
    {
        createQueryBuilder().insertInto(table, table.a, table.b).values(a, b).execute();
    }
}

=============================================== 解决方法 - 解决方案:

@Scheduled(...)
public class ScheduledTaskRunner
{
    // @Transactional
    public void run()
    {
        jooqService.createQueryBuilder().transaction(
            (configuration) ->
            {
                aService.parseXML();
                bService.parseCSV();
            }
        );
    }
}

标签: postgresqlspring-boottransactionsjooq

解决方案


我不确定这是否能解决你的问题,但你真的不应该在 astatic DSLContext中引用Service,尤其是因为你DSLContext引用了个人Connection。您的设计意味着任何JooqService实现都将使用相同的 JDBC 连接。

我也怀疑你是否也应该缓存你的 JDBC Connection。理想情况下,您直接DSLContext包装DataSource。这是将 jOOQ 插入您配置的事务管理的最佳方式,方法是Connection从数据源正确获取 a,并在使用后通过调用Connection.close()您再次释放它。


推荐阅读