One hibernation transaction and Spring controller

I am trying to implement a registration controller for the Rest API. I read about where to post @Transactional quite a bit. (Not at the DAO level, but at services, possibly organized). In my use case, I want not only services, but also a sleep mode check to use the same transaction.

This is the controller code:

@Autowired private UserService userService; @RequestMapping(method = RequestMethod.GET) @ResponseBody @Transactional public DefaultResponse register(@Valid RegisterIO registerIO, BindingResult errors) { DefaultResponse result = new DefaultResponse(); if (errors.hasErrors()) { result.addErrors(errors); } else { userService.register(registerIO); } return result; } 

I wrote a custom contraint annotation that checks the registerIO parameter attribute. Both of these are validators and userService.register (registerIO); access to the database (check if the email address is used).

Therefore, I want both methods to use the same Hibernate session and transaction.

This approach leads to the following exception:

 org.hibernate.HibernateException: No Session found for current thread org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:97) org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:941) 

The problem is the @Transactional annotation. When I put this annotation in the methods that will call the database, everything works, but the two transactions begin. I suspect that when I put it in the register method, the validation of the sleep mode validation is done before @Transactional starts the transaction for this method.

I developed the following functional workaround, but I am not happy with it. These codes do not use the @Valid annotation, but invoke the validator themselves:

 @RequestMapping(method = RequestMethod.GET) @ResponseBody @Transactional public DefaultResponse register( RegisterIO registerIO, BindingResult errors) { DefaultResponse result = new DefaultResponse(); ValidatorFactory vf = Validation.buildDefaultValidatorFactory(); Validator validator = vf.getValidator(); Set<ConstraintViolation<RegisterIO>> valResult = validator.validate(registerIO); 

I am trying to summarize my question: Using Spring MVC and Hibernate-Validation together with @Valid and @Transactional, how can I encapsulate an entire request in a single transaction?

Thanks:)

+4
source share
1 answer

Your workaround can be improved by using a single validator and entering it into the controller. You tried:

 @Autowired private Validator validator; 

Thus, you will skip the overhead of creating a validator for each request. You must also be careful with the conditions of the race. While you are checking the database to see if a particular letter exists, another query may create this record so that you still get an exception during data entry.

+1
source

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


All Articles