Rest API の登録コントローラーを実装しようとしています。@Transactional を配置する場所についてはかなり読みました。(DAO レベルではなく、サービスでオーケストレーションされる可能性があります)。私のユースケースでは、サービスだけでなく、休止状態の検証でも同じトランザクションを使用したいと考えています。
これはコントローラーのコードです:
@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;
}
パラメータ registerIO の属性を検証するカスタム制約アノテーションを作成しました。このバリデーターと userService.register(registerIO); の両方。データベースにアクセスします (メールアドレスが既に使用されているかどうかを確認してください)。
したがって、両方のメソッドで同じ Hibernate セッションとトランザクションを使用する必要があります。
このアプローチでは、次の例外が発生します。
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)
問題は @Transactional アノテーションです。この注釈をメソッドに配置すると、データベースを呼び出してすべてが機能しますが、2 つのトランザクションが開始されます。register メソッドに配置すると、@Transactional がこのメソッドのトランザクションを開始する前に休止状態の検証が実行されると思われます。
次の機能的な回避策を開発しましたが、満足できません。このコードは @Valid アノテーションを使用しませんが、バリデータ自体を呼び出します。
@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);
私の質問を要約しようとします: Spring MVC と Hibernate-Validation を @Valid と @Transactional と共に使用すると、リクエスト全体を 1 つのトランザクションにカプセル化するにはどうすればよいですか?
ありがとうございました :)