将唯一违规异常传播到UI的最佳做法 [英] Best practice propagating Unique Violation Exceptions to UI
本文介绍了将唯一违规异常传播到UI的最佳做法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我们目前正在就如何将违反数据库约束作为用户友好的消息填充到UI进行辩论。我们或多或少看到了两种方式,都不是真正令人满意的。有人能给点建议吗?
方法1-以编程方式验证并引发特定异常
在CountryService.java中,将验证每个唯一约束并抛出相应的异常。在支持Bean中单独处理异常。
优点:易于理解和维护。可能的特定用户消息。
缺点:大量代码只是为了获得美好的消息。基本上,所有的DB约束都会在应用程序中重新编写。大量查询-不必要的数据库加载。
@Service("countryService")
public class CountryServiceImpl implements CountryService {
@Inject
private CountryRepository countryRepository;
@Override
public Country saveCountry(Country country) throws NameUniqueViolationException, IsoCodeUniqueViolationException, UrlUniqueViolationException {
if (!isUniqueNameInDatabase(country)) {
throw new NameUniqueViolationException();
}
if (!isUniqueUrl(country)) {
throw new UrlUniqueViolationException();
}
if (!isUniqueIsoCodeInDatabase(country)) {
throw new IsoCodeUniqueViolationException();
}
return countryRepository.save(country);
}
}
在视图的Backup Bean中处理异常:
@Component
@Scope(value = "view")
public class CountryBean {
private Country country;
@Inject
private CountryService countryService;
public void saveCountryAction() {
try {
countryService.saveCountry(country);
} catch (NameUniqueViolationException e) {
FacesContext.getCurrentInstance().addMessage("name", new FacesMessage("A country with the same name already exists."));
} catch (IsoCodeUniqueViolationException e) {
FacesContext.getCurrentInstance().addMessage("isocode", new FacesMessage("A country with the same isocode already exists."));
} catch (UrlUniqueViolationException e) {
FacesContext.getCurrentInstance().addMessage("url", new FacesMessage("A country with the same url already exists."));
} catch (DataIntegrityViolationException e) {
// update: in case of concurrent modfications. should not happen often
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("The country could not be saved."));
}
}
}
方法2-让数据库检测约束冲突
优点:没有样板代码。没有不必要的数据库查询。没有重复的数据约束逻辑。
缺点:依赖于DB中的约束名称,因此无法通过Hibernate生成Schema。将消息绑定到输入组件所需的机制(例如,用于突出显示)。
public class DataIntegrityViolationExceptionsAdvice {
public void afterThrowing(DataIntegrityViolationException ex) throws DataIntegrityViolationException {
// extract the affected database constraint name:
String constraintName = null;
if ((ex.getCause() != null) && (ex.getCause() instanceof ConstraintViolationException)) {
constraintName = ((ConstraintViolationException) ex.getCause()).getConstraintName();
}
// create a detailed message from the constraint name if possible
String message = ConstraintMsgKeyMappingResolver.map(constraintName);
if (message != null) {
throw new DetailedConstraintViolationException(message, ex);
}
throw ex;
}
}
推荐答案
方法1在并发方案中不起作用!--在您检查之后但在您添加数据库记录之前,总是会有其他人插入新数据库记录的更改。(除非您使用隔离级别可序列化,但这不太可能)
所以您必须处理违反DB约束的异常。但我建议捕获指示唯一违规的数据库异常,并像您在方法1中建议的那样抛出一个更有意义的完整异常。
这篇关于将唯一违规异常传播到UI的最佳做法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文