我不同意處理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:支持標籤進行驗證。
如果獨立客戶端直接進行JPA調用,您如何防止出現這些問題。我們如何讓代碼在這些場景中重複使用? – Joe 2010-02-02 10:44:06
獨立客戶端是否總是直接進行JPA調用,或者您是否可以強制它通過某種類型的DAO? – mtpettyp 2010-02-08 16:54:39
我們使用Seam組件(EntityHome,EntityQuery接口),它們當前用作用戶界面和JPA持久層之間的粘合劑。 我不清楚,如果我可以強制獨立客戶端直接使用Seam抽象層進行持久化而不是JPA層。如果Seam層必須存在,那麼Seam庫需要作爲客戶端工具包的一部分發貨。 不知道這裏最好的辦法是什麼 – Joe 2010-02-11 03:59:08