2016-11-24 9 views
0

最初のリクエストでオブジェクトが作成されても、2番目のリクエストでオブジェクトが返されるという奇妙な問題が発生しています。 のは、我々は2つのドメインクラスがあると仮定してみましょう:プットがPUT /as/<id>を経由してAのインスタンスに送信されafterUpdateイベントフック、トランザクション、および連続したリクエストの古い状態

Class A { 
    static hasMany = [bs: B] 

    def afterUpdate() { 
     this.addToBs(new B(a: this)) 
     this.save() 
    } 
} 

Class B { 
    static belongsTo = [a: A] 
} 

update()@TransactionalでアノテートされRestfulControllerに呼び出されます。

私たちが見ることができるのは、最初の要求の応答が返された後、フォローアップ要求がAPIコンシューマによって送信されるたびに、GET /bsは、作成されたはずのBの新しいインスタンスを返しません最初の要求では、さらに要求で返されます。

Grailsは、トランザクションがコミットされた後にのみAPIコンシューマに応答を送信することを期待していました。これは、次のリクエストでそのトランザクションからのすべての変更が表示されるはずです。

その動作の理由は何ですか? grailsアプリが既にAPIコンシューマーに応答を送った後にトランザクションがコミットされますか?もしそうなら、デフォルトでオンになっているupdate()の周りの@Transactionalの理由はありますか?

私はこの例ではafterUpdateのコードをbeforeUpdateに入れることもできますが、できる限りこの例を簡略化しようとしました。

答えて

0

私の経験上、afterUpdate()のコードなどはトランザクションに含まれていません。トランザクションを明示的に作成する必要があります(またセッションも可能です)。 http://docs.grails.org/latest/ref/Domain%20Classes/withTransaction.html

afterUpdate()や友人の中でGORMのアップデートを行うことをお勧めします。このような奇妙な問題が発生し、ドメインモデルの単体テストが難しくなるためです。代わりにトランザクションサービスに保存を委任した場合、機能するだけでなく、統合テストで確認することもできます。私のGrailsのアプリで

、私は本当にばかな私のコントローラを保つ:

  1. コールサービス
  2. 戻り、サービスの出力(おそらくそれをフォーマット)。

コントローラーは、テストするのに苦労しているので、すべてのビジネスロジックを維持しています。ここでは例です:

@grails.transaction.Transactional 
class SomeService { 
    def saveA(A a) { 
     // This method will run in a transaction. 
     a.addToBs(new B(a: this)) 
     a.save() 
    } 
} 

とコントローラで...

class SomeController { 
    def update() { 
     ... 
     someService.save(a) 
    } 
} 
+0

はそのアドバイスエマニュエルいただきありがとうございます。これらのフックを適切に使用することはまだ可能かもしれないと思っていましたが、その操作をサービスに入れてチェックアウトします。 – alexanderfranke

+0

これらのフックを使うことはできますが、 'DomainClass.withSession()'や 'DomainClass.withTransaction()'を使ってGORMの使用法を新しいセッションやトランザクションのいずれかでラップする必要があります。それぞれ、問題はフックが@transactionの外で実行されることです。 –

関連する問題