5

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 つのトランザクションにカプセル化するにはどうすればよいですか?

ありがとうございました :)

4

1 に答える 1

1

単一の Validator を使用してコントローラーに注入することで、回避策を改善できます。やってみました:

@Autowired
private Validator validator;

このようにして、リクエストごとにバリデーターを作成するオーバーヘッドをスキップします。また、競合状態にも注意する必要があります。特定の電子メールが存在するかどうかをデータベースで確認しているときに、別のリクエストでこのレコードを作成できるため、データを挿入するときに例外が発生します。

于 2013-05-21T09:46:57.760 に答える