JOOQ @Transactional для нескольких хранилищ - PullRequest
0 голосов
/ 06 сентября 2018

Положение:

У меня запланированное задание с длительностью 15 минут. Восстанавливает 2 стола. Я хотел бы сделать это в ОДНОЙ транзакции, но в @Transational вызовы репо имеют 2 разные транзакции для партии репо.

Это проект с весенней загрузкой 2 с postgres.

Возможно ли, что репозитории имеют разные связи?

(Я удалил и упростил некоторые 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 голосов
/ 06 сентября 2018

Я не уверен, что это решит вашу проблему, но вы действительно не должны иметь ссылку static DSLContext в Service, тем более что ваши DSLContext ссылаются на отдельного пользователя Connection. Ваш дизайн означает, что любая реализация JooqService будет использовать одно и то же соединение JDBC.

Я также сомневаюсь, что вы также должны кэшировать свой JDBC Connection. В идеале ваш DSLContext оборачивает DataSource напрямую. Это лучший способ подключить jOOQ к вашему сконфигурированному управлению транзакциями, правильно получив Connection из источника данных и выпуская его снова после использования, позвонив вам Connection.close().

...