Я использую Hibernate и Spring Data, он будет выполнять оптимистическую блокировку при вставке или обновлении сущности, а если версия в базе данных не совпадает с версией, которая будет сохраняться, в Spring будет выдано исключение StaleObjectStateException
,вам нужно перехватить его с помощью ObjectOptimisticLockingFailureException
.
. Я хочу перехватить исключение и попросить пользователя обновить страницу, чтобы получить последние данные из базы данных, как показано ниже:
public void cancelRequest()
{
try
{
request.setStatus(StatusEnum.CANCELLED);
this.request = topUpRequestService.insertOrUpdate(request);
loadRequests();
//perform other tasks...
} catch (ObjectOptimisticLockingFailureException ex)
{
FacesUtils.showErrorMessage(null, "Action Failed.", FacesUtils.getMessage("message.pleaseReload"));
}
}
Я предполагаю, что это также будет работать с кодом ниже, но я еще не проверял его.
public void cancelRequest()
{
RequestModel latestModel = requestService.findOne(request.getId());
if(latestModel.getVersion() != request.getVersion())
{
FacesUtils.showErrorMessage(null, "Action Failed.", FacesUtils.getMessage("message.pleaseReload"));
}
else
{
request.setStatus(StatusEnum.CANCELLED);
this.request = requestService.insertOrUpdate(request);
loadRequests();
//perform other tasks...
}
}
Мне нужно применять эту проверку везде, где я звоню requestService.insertOrUpdate(request);
, и я не хочуприменять их по одному.Поэтому я решаю поместить проверочный код в саму функцию insertOrUpdate(entity)
.
@Transactional
public abstract class BaseServiceImpl<M extends Serializable, ID extends Serializable, R extends JpaRepository<M, ID>>
implements BaseService<M, ID, R>
{
protected R repository;
protected ID id;
@Override
public synchronized M insertOrUpdate(M entity)
{
try
{
return repository.save(entity);
} catch (ObjectOptimisticLockingFailureException ex)
{
FacesUtils.showErrorMessage(null, FacesUtils.getMessage("message.actionFailed"),
FacesUtils.getMessage("message.pleaseReload"));
return entity;
}
}
}
Мой главный вопрос заключается в том, что при таком подходе будет одна проблема.Сторона вызывающего абонента не будет знать, успешно ли объект сохранился успешно или нет, так как исключение будет перехвачено и обработано внутри функции, поэтому сторона вызывающего абонента всегда будет считать, что персистентность была успешной, и продолжит выполнение других задач, а это не так.хочу.Я хочу, чтобы он прекратил выполнение задач, если не удастся сохранить:
public void cancelRequest()
{
try
{
request.setStatus(StatusEnum.CANCELLED);
this.request = topUpRequestService.insertOrUpdate(request);
//I want it to stop here if fail to persist, don't load the requests and perform other tasks.
loadRequests();
//perform other tasks...
} catch (ObjectOptimisticLockingFailureException ex)
{
FacesUtils.showErrorMessage(null, "Action Failed.", FacesUtils.getMessage("message.pleaseReload"));
}
}
Я знаю, что при вызове insertOrUpdate
я могу перехватить возвращаемое значение entiry, объявив новую переменную модели, и сравнить ее версию с исходной., если версия такая же, означает, что сохранение не удалось.Но если я делаю это таким образом, я должен писать код проверки версии везде, где я звоню insertOrUpdate
.Есть ли лучший подход, чем этот?