проверяет нарушение ограничения перед сохранением сущности - PullRequest
15 голосов
/ 30 января 2010

Каков наилучший механизм предотвращения проверок нарушения ограничений перед созданием | модификация объекта?

Предположим, если объект «Пользователь» имеет «логин» в качестве уникального ограничения, было бы целесообразно проверить, существует ли уже запись пользователя с этим логином перед созданием или изменением.

OR

Вы бы позволили базе данных выдать исключение ConstraintViolationException и соответствующим образом обработать это сообщение на уровне пользовательского интерфейса. Где такие проверки должны выполняться в структуре шва jboss.

Примечание. В настоящее время такие проверки не применяются в коде seam-gen.

В настоящее время мы используем Seam 2.2, Richfaces с Hibernate.

Ответы [ 3 ]

7 голосов
/ 30 января 2010

Даже если вы проверяете условие в своем коде перед сохранением объекта пользователя, всегда существует вероятность того, что кто-то создаст дубликат имени входа в систему между временем проверки и сохранением нового пользователя.

Однако будет проще отобразить соответствующее сообщение об ошибке в пользовательском интерфейсе, если вы сделаете явную проверку. Если у вас есть несколько ограничений в таблице, перехват ConstraintViolationException не позволит вам легко определить, какое ограничение было нарушено.

Так что я бы сделал оба. Предполагая, что вы выходите из EntamHome в Seam:

  1. В методе persist () выполните запрос, чтобы убедиться, что loginid уникален. Если это не так, добавьте сообщение об ошибке в соответствующий элемент управления и верните ноль.
  2. Оберните вызов super.persist () и перехватите ConstraintViolationException, отображая общее повторяющееся сообщение об ошибке

EDIT

Как упоминал Шервин, создание JSF Validator - отличная идея (замена) # 1 выше, но вы все равно должны ожидать худшего и ловить ConstraintViolationException.

6 голосов
/ 10 февраля 2010

Я не согласен с обработкой ConstraintException. Я написал валидатор, который проверяет дубликаты перед сохранением, и он прекрасно работает.

Вот пример проверки дубликатов электронных писем.

@Name("emailValidator")
@Validator
@BypassInterceptors
@Transactional
public class UniqueEmailValidator implements javax.faces.validator.Validator, Serializable {

private static final long serialVersionUID = 6086372792387091314L;

@SuppressWarnings("unchecked")
public void validate(FacesContext facesContext, UIComponent component, Object value) throws ValidatorException {
    EntityManager entityManager = (EntityManager) Component.getInstance("entityManager");
    String newEmail = (String) value;
    String oldEmail = String.valueOf(component.getAttributes().get("oldEmail"));
    if (oldEmail != null && !oldEmail.equalsIgnoreCase(newEmail)) {
        List<User> users = entityManager.createQuery(
                "SELECT DISTINCT u FROM " + User.class.getName() + " p where lower(p.fromEmail) = :email").setParameter("email",
                newEmail.toLowerCase()).getResultList();
        if (!users.isEmpty()) {
            Map<String, String> messages = Messages.instance();
            throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, messages.get("admin.emailexists"), messages
                    .get("admin.emailexists")));
        }
    }
}
}

А в своей форме (xhtml) вы пишете:

<s:decorate template="/layout/definition.xhtml">
        <ui:define name="label">#{messages['processdata.email']}</ui:define>
        <h:inputText id="fromEmail" size="30" required="true" value="#  {userAdmin.existingUser.fromEmail}">
            <f:validator validatorId="emailValidator"/>
            <f:attribute name="oldEmail" value="#{userAdmin.existingUser.fromEmail}" />
            <s:validate />
        </h:inputText>
    </s:decorate>

Таким образом, оно всегда проверяет поле перед сохранением. Вы даже можете добавить тег a: support для проверки при изменении фокуса.

2 голосов
/ 30 января 2010

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

Как правило, вы выполняете эту проверку в своей бизнес-логике, прежде чем запрашивать добавление сущности в базу данных.

...