Сбой запроса на слияние Oracle с уникальными ограничениями в транзакции гибернации при выполнении нескольких потоков - PullRequest
0 голосов
/ 20 мая 2019

У меня есть один метод, в котором есть запрос на слияние. Если запись уже отсутствует, этот метод вставляет новую строку, а если уже присутствует, обновляет существующую запись. Проблема в этом методе заключается в том, что 2 потока выполняют этот метод одновременно. Первый поток входит в метод и не фиксирует транзакцию, и в то же время второй поток входит. Теперь один из них вставляет строку, второй также пытается вставить вместо обновления и вызывает уникальную ошибку ограничения. Мне интересно, почему это происходит, второй поток должен обновить вместо вставки новой строки. Я новичок в спящем режиме. Так это проблема транзакции гибернации или что-то еще.

Пожалуйста, помогите мне понять это. Благодарю. Ниже приведен код mergeFunction (), добавленный для ясности. когда смоделированная строка журнала напечатана в следующей последовательности

  • обновление MY_TABLE ... thread-1

  • обновление MY_TABLE ... thread-2

  • обновлено MY_TABLE ... thread-1

  • Ошибка ограничения уникального ключа ... thread-2

Эта проблема моделируется только несколько раз. К счастью, 2 потока пытаются выполнить один и тот же метод.

    public void mergeFunction(long customerId, long assetId, String module, Status status, String errorMsg) {

    log.debug("Updating MY_TABLE for  asset {}  module {} status ={} customer ={}", assetId, module, status.name(),customerId);
    StatelessSession statelessSession = session.getSessionFactory().openStatelessSession();
    try {
        Transaction tx = statelessSession.beginTransaction();
        try {

            String sql = "merge into MY_TABLE x " +
                    "using (select " + customerId + " customer_id, '" + module + "' module, " + assetId + " asset_id from dual) y " +
                    "on (x.asset_id = y.asset_id and x.module = y.module) " +
                    "when matched then " +
                    "  update set x.status = :status, x.ERROR = :errMsg where x.asset_id = :aid and x.module = :module " +
                    "when not matched then " +
                    "  insert (id, uuid, customer_id, module, asset_id, status, activated_on) " +
                    "  values (id_MY_TABLE.nextval, portal_pck.get_uuid(), " + customerId + ", '" + module + "', " + assetId + ", '" + status + "', sysdate)";

            statelessSession.createSQLQuery(sql).setParameter("aid", assetId)
                    .setParameter("module", module)
                    .setParameter("status", status.name())
                    .setParameter("errMsg", StringUtils.isEmpty(errorMsg) ? " " : errorMsg)
                    .executeUpdate();
            tx.commit();
            log.debug("Updated MY_TABLE for {} asset for {} status ={} customer={}",assetId,module, status.name(),customerId);

        } catch (Exception exe) {
            log.debug("error while updating MY_TABLE table for asset {} module{} status {}  for customer {} exception ={}",
                    assetId, module, status.name(), customerId, exe);
            tx.rollback();
            throw exe;
        }

    } finally {
        statelessSession.close();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...