Вставка по уникальному ключу

224
03 ноября 2017, 09:06

Есть сущность с id и каким-то другим уникальным ключом (extId). Множество потоков (приложений) вставляют в БД сущности с незаполненным id, но известным extId по следующей логике:

  • Если extId уже найден в БД, то обновить сущность новыми данными.
  • Если не найден, то вставить новую запись.
@Transactional(propagation = REQUIRED_NEW)
public A createOrUpdate(A a) {
    A b = findByExtId(a.extId, LockModeType.PESSIMISTIC_WRITE);
    if (b != null) {
        a.id = b.id
    }
    return save(a); // hibernate merge
}

Update:

@Transactional(propagation = Propagation.SUPPORTS)
public A findByExtId(final Long extId,
                     final LockModeType lockMode) {
    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
    CriteriaQuery<A> cq = cb.createQuery(A.class);
    Root<A> root = cq.from(A.class);
    cq.where(cb.equal(root.get("extId"), cb.parameter(Long.class, "extId")));
    TypedQuery<A> query = entityManager.createQuery(cq);
    query.setParameter("extId", extId);
    query.setLockMode(lockMode);
    List<A> list = query.getResultList();
    if (!list.isEmpty()) {
        return list.get(0);
    }
    return null;
}
@Transactional(propagation = Propagation.SUPPORTS)
public A save(A t) {
    return entityManager.merge(t);
}

Проблема в том, что данный код в редких случаях все равно вставляет сущность с одинаковым extId несколько раз. В чем может быть причина?

База данных PostgreSQL.

Answer 1

Если два потока (с одним и тем же extID) примерно одновременно выполнят A b = findByExtId(a.extId, LockModeType.PESSIMISTIC_WRITE); и в БД еще нет строки с таким extID, то они оба вставят новую строчку

Answer 2

Потому что для обновления используется другая команда сессии. session.update(a); или session.merge(a);

READ ALSO
Список папок и файлов в Assets

Список папок и файлов в Assets

Каким образом я могу получить названия папок в assets, а также список файлов в каждой из этих папок?

234
Как задать иконку для Cluster Markers

Как задать иконку для Cluster Markers

Есть много маркеровДобавляются через класстер

287
Clean Architecture android

Clean Architecture android

Начал в своем MVP юзать интерактор) При этом Rx я не использовал) В Interactor`е я инжектил ретрофит и отправлял запрос)

234
Не отрабатывает корректно push

Не отрабатывает корректно push

ПриветТакая проблема

290