Bean Validation: getting an EntityNotFoundException, although there is a limitation for validating an object

Technologies: Spring, Hibernate, JSR-303, JQuery
Platform: Windows
I am trying to implement the @IdMustExist JSR-303 constraint. The purpose of the restriction is to check if the entered identifier value exists in the linked table. See Link for code snippets IdMustExist.java and IdMustExistValidator.java.

Scenario 1 - a valid identifier value is entered: in this case, when the hibernate EntityManager.merge operation is performed, I see that the @IdMustExist constraint is being met. It successfully confirms that the entered identifier value exists in another linked / linked table. Hibernate successfully completes the save operation. I noticed that hibernate fires selects SQL for the object before calling validator for @IdMustExist.

Scenario 2 - an invalid identifier value is entered: in this case, when the hibernate EntityManager.merge operation is performed, it throws an EntityNotFoundException (stack trace below), because it could not find the object for the entered invalid identifier. I was hoping that the @IdMustExist constraint would be triggered during the pre-upgrade phase and we could gracefully display the error message to the user. But something seems to fail until hibernation can enter the pre-update phase. I see that hibernation triggers SQL queries for an object and then throws an EntityNotFoundException. It has no way to call validate @IdMustExist.

Does this mean that I can’t check if the entered identifier exists in the linked / linked table via JSR-303? Any alternatives?

Thanks for your help in advance. In 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; } 
0
source share
2 answers

The link referenced by the link does not show the code for the DAO, but I assume that you are using the load() method from the session. See Javadoc:

Returns a persistent instance of this entity class with the given identifier, assuming that the instance exists.

Note the part that says: "Assuming an instance exists." So you know that some entity exists, and you ask Hibernate to download it. If this does not exist, this assumption is violated and an exception is thrown.

Instead, you can use the get() method. See what javadoc says:

Returns a constant instance of this entity class with the given identifier or null if there is no such constant 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

+1
source

A few things here. What session does your CommonDao use. In fact, it should be a new session open in the current connection. The entire issue of using a session (or entity manager in a constraint validator) is discussed in the Hibernate wiki database: http://community.jboss.org/wiki/AccessingtheHibernateSessionwithinaConstraintValidator

I do not recommend this approach. I would just call merge and deal with Hibernate Core (or JPA) exceptions.

0
source

Source: https://habr.com/ru/post/1338134/


All Articles