JOOQ @Transactional在多个存储库上

时间:2018-09-06 10:08:52

标签: postgresql spring-boot transactions jooq

情况:

我已安排了15分钟的任务安排。它重新生成2个表。我想在一次交易中完成此操作,但是对于@reational来说,回购调用具有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();
            }
        );
    }
}

1 个答案:

答案 0 :(得分:1)

我不确定这是否可以解决您的问题,但是您确实不应该在static DSLContext中使用Service引用,尤其是因为您的DSLContext引用了一个单独的{{ 1}}。您的设计意味着任何Connection实现都将使用相同的JDBC连接。

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