多个存储库上的JOOQ @Transactional

问题描述 投票:0回答:1

情况:

我已经安排了长达15分钟的任务。它重新生成2个表。我想在一次交易中这样做,但是对于@Transational,回购电话有2个不同的交易,用于大量的回购电话。

这是一个带有postgres的春季靴子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();
            }
        );
    }
}
postgresql spring-boot transactions jooq
1个回答
1
投票

我不确定这是否会解决你的问题,但你真的不应该在static DSLContext中有Service参考,特别是因为你的DSLContext引用了一个单独的Connection。您的设计意味着任何JooqService实现都将使用相同的JDBC连接。

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

© www.soinside.com 2019 - 2024. All rights reserved.