技术:Spring、Hibernate、JSR-303、JQuery
平台:Windows
我正在尝试实现@IdMustExist JSR-303 约束。约束的目的是检查输入的 id 值是否存在于关联表中。请参阅此链接以获取 IdMustExist.java 和 IdMustExistValidator.java 代码片段。
场景 1 - 输入了有效的 Id 值:在这种情况下,当执行 hibernate 的 EntityManager.merge 操作时,我看到执行了 @IdMustExist 约束。它成功验证输入的 Id 值是否存在于另一个关联/链接表中。Hibernate 成功完成了保存操作。我注意到在调用@IdMustExist 的验证器之前,hibernate 会为实体触发选择 SQL。
场景 2 - 输入了无效的 Id 值:在这种情况下,当执行 hibernate 的 EntityManager.merge 操作时,它会抛出 EntityNotFoundException(下面给出的堆栈跟踪),因为它找不到输入的无效 Id 的实体。我希望约束 @IdMustExist 在更新前阶段被触发,我们可以优雅地向用户显示错误消息。但在休眠进入更新前阶段之前,似乎有些事情失败了。我看到休眠触发实体的选择 SQL,然后抛出 EntityNotFoundException。它没有机会调用 validate @IdMustExist。
这是否意味着,我无法通过 JSR-303 验证输入的 Id 是否存在于关联/链接表中?有什么选择吗?
提前感谢您的帮助。J.P
javax.persistence.EntityNotFoundException: Unable to find com.mycompany.myapp.domain.package1.Class1 with id 100
at org.hibernate.ejb.Ejb3Configuration$Ejb3EntityNotFoundDelegate.handleEntityNotFound(Ejb3Configuration.java:133)
at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:233)
at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:285)
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:152)
at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:1080)
at org.hibernate.impl.SessionImpl.internalLoad(SessionImpl.java:1028)
at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:623)
at org.hibernate.type.EntityType.resolve(EntityType.java:431)
at org.hibernate.type.EntityType.replace(EntityType.java:291)
at org.hibernate.type.TypeFactory.replace(TypeFactory.java:532)
at org.hibernate.event.def.DefaultMergeEventListener.copyValues(DefaultMergeEventListener.java:495)
at org.hibernate.event.def.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:423)
at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:234)
at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:84)
at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:859)
at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:843)
at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:847)
at org.hibernate.ejb.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:682)
at com.mycompany.myapp.dao.hibernate.package2.HibernateClass2Dao.save(HibernateClass2Dao.java:101)
at com.mycompany.myapp.service.package2.Class1ServiceImpl.update(Class1ServiceImpl.java:56)
...
...
at java.lang.Thread.run(Thread.java:619)
HibernateClass2Dao.java
public void save(GenericRequest request, GenericResponse response){
Class2 class2Request = (Class2) request.getObject(Class2.class.getName());
EntityManager em = PersistenceUtil.getEntityManagerFactory().createEntityManager();
Class2 class2Persisted = em.find(Class2.class, class2Request.getId());
EntityTransaction tx = em.getTransaction();
try {
tx.begin();
class2Persisted.setClass1(class2Request.getClass1());
em.merge(class2Request);
tx.commit();
} catch (RollbackException rbe) {
response.setSuccess(false);
rbe.getCause().printStackTrace();
ConstraintViolationException cve = (ConstraintViolationException) rbe.getCause();
Set<ConstraintViolation<?>> constraintViolations = cve.getConstraintViolations();
if (constraintViolations.size() > 0){
for (ConstraintViolation<?> violation : constraintViolations){
Iterator<Node> itr = violation.getPropertyPath().iterator();
String propertyPath = itr.next().getName();
Class<? extends Payload> payload = violation.getConstraintDescriptor().getPayload().iterator().next();
String payloadName = payload.getCanonicalName();
response.addMessage(violation.getMessage(), violation.getLeafBean().getClass().getName(),
propertyPath , payloadName);
}
}
} finally {
em.close();
}
}
Class2ServiceImpl.java
public void update(GenericRequest request, GenericResponse response){
class2Dao.save(request, response);
}
Class2Controller.java
@RequestMapping(value="/update")
public @ResponseBody GenericResponse update(String jqGridId, String oper
, Class2 class2
, BindingResult bindingResult) throws Exception {
GenericResponse response = new GenericResponse(true);
response.setMessageSource(messageSource);
Locale locale = new Locale(CommonConstants.DEFAULT_LOCALE);
if (bindingResult.hasErrors()){
response.setSuccess(false);
addBindingMessages(response, bindingResult, locale);
return response;
}
class2.setId(Long.parseLong(jqGridId));
class2.setCode(jqGridId);
GenericRequest request = new GenericRequest(UserUtil.getUser(), class2);
this.class2Service.update(request, response);
return response;
}