Передовой опыт распространения уникальных исключений нарушений в пользовательском интерфейсе

Мы работаем над веб-проектом Java на основе JPA 2, Hibernate, Spring 3 и JSF 2, работающих в Tomcat 7. Мы используем Oracle 11g в качестве базы данных.

В настоящее время мы обсуждаем подходы к заполнению нарушений ограничений базы данных в виде удобных для пользователя сообщений в пользовательском интерфейсе. Более или менее мы видим два пути, оба не совсем удовлетворительные. Может кто-нибудь дать совет?

Подход 1. Проверка программно и создание определенного исключения.

В CountryService.java проверяется каждое уникальное ограничение и выдается соответствующее исключение. Исключения обрабатываются индивидуально в bean-компоненте поддержки.

Преимущество: Простота понимания и обслуживания. Возможны специальные сообщения пользователя.

Недостаток: Много кода только для того, чтобы иметь красивые сообщения. В основном все ограничения БД заново прописываются в приложении. Много запросов - ненужная нагрузка на БД.

@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);
    }
}

В 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 – позволить базе данных обнаруживать нарушения ограничений

Преимущество: Нет стандартного кода. Никаких лишних запросов к БД. Отсутствие дублирования логики ограничения данных.

Недостаток: Зависимости от имен ограничений в БД, поэтому генерация схемы через гибернацию невозможна. Механизм, необходимый для привязки сообщений к компонентам ввода (например, для выделения).

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;
    }
}
17
задан Cœur 13 December 2017 в 05:07
поделиться