在创建之前防止约束违规检查的最佳机制是什么?修改实体?
假设'User'实体的'loginid'作为唯一约束,在创建或修改之前检查是否已存在具有此loginid名称的用户条目是明智的。
OR
您是否允许数据库抛出ConstraintViolationException并在UI层中正确处理此消息。应该在jboss seam框架中强制执行此类检查。
注意:目前没有对seam-gen代码强制执行此类检查。
我们目前使用Seam 2.2,Richfaces和Hibernate。
答案 0 :(得分:7)
即使您在持久保存用户对象之前检查代码中的条件,也有可能有人在您检查的时间和持久保存新用户之间创建重复的loginid。
但是,如果进行显式检查,在UI中显示相应的错误消息会更容易。如果表上有多个约束,捕获ConstraintViolationException将不允许您轻松确定违反了哪个约束。
所以我会两个都做。假设您正在从Seam的EntityHome扩展:
修改强>
正如Shervin所说,创建一个JSF Validator是一个好主意(替换)#1,但你应该仍然期待最坏的并捕获ConstraintViolationException。
答案 1 :(得分:6)
我不同意处理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 :(得分:2)
我的建议是,如果你可以检查一个条件然后检查它,即在你的情况下是一个UserExists方法调用。抛出异常是昂贵的,并且用于通常与您的控制之外的事物有关的特殊情况,例如:光盘访问等
在调用实体添加到数据库之前,通常会在业务逻辑中执行此检查。