Bean验证:尽管有一个约束来验证实体,但接收EntityNotFoundException [英] Bean Validation: Receive EntityNotFoundException though have a constraint to validate entity

查看:88
本文介绍了Bean验证:尽管有一个约束来验证实体,但接收EntityNotFoundException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

技术:Spring,Hibernate,JSR-303,JQuery

我试图实现@IdMustExist JSR-303约束。约束的目的是检查输入的id值是否存在于关联表中。请参阅此链接对于IdMustExist.java和IdMustExistValidator.java代码片段。

场景1 - 输入有效的Id值:在这种情况下,当执行hibernate的EntityManager.merge操作时,I看到@IdMustExist约束被执行。它成功验证输入的Id值是否存在于另一个关联/链接表中。 Hibernate成功完成保存操作。我注意到在调用@IdMustExist的验证器之前,hibernate会激发为实体选择SQL。


$ b 场景2 - 输入无效的Id值:在这种情况下,当hibernate的EntityManager。合并操作被执行时,它会抛出EntityNotFoundException(下面给出的堆栈跟踪),因为它无法找到输入的无效标识的实体。我希望约束@IdMustExist在更新前的阶段被触发,我们可以优雅地向用户显示错误消息。但是在hibernate进入pre-update阶段之前它看起来有些失败。我看到hibernate激发为实体选择SQL,然后抛出EntityNotFoundException。它没有机会调用验证@IdMustExist。

这是否意味着,我无法通过JSR-303验证输入的Id是否存在于关联/链接表中?任何替代品?



感谢您的帮助提前。
JP

  javax.persistence.EntityNotFoundException:无法找到com.mycompany.myapp.domain.package1.Class1与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)
在org.hibernate.type.TypeFactory.replace(TypeFactory.java:532)
a t 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)
在org.hibernate.impl.SessionImpl.merge(SessionImpl.java:843)
在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();
尝试{
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(); (ConstraintViolation≠violation:constraintViolations){
Iterator< Node> if(constraintViolations.size()> 0){
itr = violation.getPropertyPath()。iterator();
String propertyPath = itr.next()。getName();
Class <?扩展有效载荷> payload = violation.getConstraintDescriptor()。getPayload()。iterator()。next();
String payloadName = payload.getCanonicalName();
response.addMessage(violation.getMessage(),violation.getLeafBean()。getClass()。getName(),$ b $ 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)抛出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);
返回响应;
}
class2.setId(Long.parseLong(jqGridId));
class2.setCode(jqGridId);
GenericRequest请求=新的GenericRequest(UserUtil.getUser(),class2);
this.class2Service.update(request,response);
返回响应;
}


解决方案

显示了DAO的代码,但我假设你使用Session中的 load()方法。查看javadoc:假设实例存在,返回给定实体类的持久化实例。



请注意假设实例存在的部分。意思是说,你知道某个实体存在,你要求Hibernate加载它。如果它不存在,则这个假设被打破,并抛出异常。

您可能需要的是使用 get()方法。查看javadoc所说的内容:
$ b


返回给定实体类的持久化实例,如果没有这种持久性实例。

因此,解决方案是从 load()更改为 get()



Javadoc: http://docs.jboss.org/hibernate/core/3.5/api/org/hibernate/Session.html

Technologies: Spring, Hibernate, JSR-303, JQuery
Platform: Windows
I am trying to implement @IdMustExist JSR-303 constraint. The purpose of the constraint is to check whether the entered id value exists in associated table. Please see this link for the IdMustExist.java and IdMustExistValidator.java code snippets.

Scenario 1 - Valid Id value is entered: In this case, when hibernate's EntityManager.merge operation is executed, I see that the @IdMustExist constraint is executed. It successfully validates that the entered Id value exists in another associated/linked table. Hibernate completes the save operation successfully. I noticed that hibernate fires select SQL for the entity before calling the validator for @IdMustExist.

Scenario 2 - Invalid Id value is entered: In this case, when hibernate's EntityManager.merge operation is executed, it throws EntityNotFoundException (stack trace given below) as it could not find the entity for the entered invalid Id. I was hoping that the constraint @IdMustExist gets fired in the pre-update stage and we can gracefully show error message to the user. But it looks like something fails before hibernate can enter pre-update stage. I see that hibernate fires select SQLs for the entity and then throws the EntityNotFoundException. It does not get a chance to call validate @IdMustExist.

Does it mean, I cannot validate whether the entered Id exists in associated/linked table through JSR-303? Any alternatives?

Thanks for your help in advance. JP

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

解决方案

Your referenced link doesn't shows the code for the DAO, but I assume you are using the load() method from the Session. See the javadoc:

Return the persistent instance of the given entity class with the given identifier, assuming that the instance exists.

Note the part that it says "assuming that the instance exists.". Means, you know that some entity exists, and you are asking Hibernate to load it. If it doesn't exists, this assumption is broken, and an exception is thrown.

What you may want is to use the get() method instead. See what the javadoc says:

Return the persistent instance of the given entity class with the given identifier, or null if there is no such persistent instance.

So, the solution is to change from load() to get().

Javadoc: http://docs.jboss.org/hibernate/core/3.5/api/org/hibernate/Session.html

这篇关于Bean验证:尽管有一个约束来验证实体,但接收EntityNotFoundException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆