gpt4 book ai didi

spring - 将唯一违规异常传播到 UI 的最佳实践

转载 作者:IT老高 更新时间:2023-10-28 13:52:05 24 4
gpt4 key购买 nike

我们正在开发基于 JPA 2、Hibernate、Spring 3 和 JSF 2 在 Tomcat 7 中运行的 Java Web 项目。我们使用 Oracle 11g 作为数据库。

我们目前正在就将违反数据库约束的方法填充为 UI 的用户友好消息进行辩论。我们或多或少看到了两种方式,两者都不是很令人满意。有人能给点建议吗?

方法 1 - 以编程方式验证并抛出特定异常

在 CountryService.java 中,每个 Unique 约束都将被验证并引发相应的异常。异常在支持 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);
}
}

在 View 的 Backing 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 没有不必要的查询。数据约束逻辑不重复。

缺点:依赖于 DB 中的约束名称,因此无法通过 hibernate 生成 Schema。将消息绑定(bind)到输入组件(例如用于突出显示)所需的机制。

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 中建议的那样抛出更完整的含义。

关于spring - 将唯一违规异常传播到 UI 的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9842672/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com