Надо брать данные из Jms и искать в таблице Address если такой есть тогда взять его ID если нет создать новый и достать его ID. Вот код:
try{
Query query = em.createQuery(
"SELECT s.id FROM Address s WHERE s.counrtyId=?1 and s.districtId=?2 and s.regionId=?3 and s.city=upper(?4)")
.setParameter(1, sa.getCounrtyId())
.setParameter(2, sa.getDistrictId())
.setParameter(3, sa.getRegionId())
.setParameter(4, sa.getCity());
Long result=(Long)query.getSingleResult();
return result;
} catch (NoResultException e){
em.persist(entity);
em.flush();
return sa.getId();
}
Так как jms обрабатывает сообщения параллельно он не находит в таблице такую строку создает новую в транзакций пока вся обработка не закончится только потом сохраняет. Если в параллельном потоке такая же строка он тоже в таблице ничего не находит и создает новую когда коммитит в базе появляются 2 таких строк.
Как можно предотвратить дублирование строк?
Ответ
Создать в базе уникальный ключ по countryId, districtId, regionId, city (если это все поля, кроме id), тогда вместо вставки в базу дублирующей записи будет возникать исключение. Если доставка сообщения jms осуществляется в транзакции, то она будет автоматически отменена и позже будет вторая попытка доставить это же сообщение. Со второй попытки id будет обнаружен. Если доставка jms не окружена транзакцией, то можно отловить исключение вставки внутри метода, принимающего сообщение. Ещё можно синхронизовать обработку сообщений, сделав её не параллельной, а поочерёдной, если такой вариант приемлем.
Комментариев нет:
Отправить комментарий