2012-02-09 4 views
0

私のユーザーがcsvやxlsなどをアップロードしていて、各行が私が保存するドメインオブジェクトのインスタンスになります。いずれかの行が失敗した場合は、すべてを元に戻したいが、後で失敗する行についてもエラーを戻したい。のは、例を作ってみましょう:Grails:トランザクションが既に失敗した後でも検証を続行したいときにトランザクションを構造化する方法

ドメインクラス:

MyDomainClass{ 
    String fieldOne 
    BigDecimal fieldTwo 
} 

入力:

ThisLineWorks,4.4 
ThisLineFails,BecauseOfThis 
How would I also get an error, for this line as well considering the last one would have rolled back the transaction already? 

ファンタジー出力:

1:ここ

OK|ThisLineWorks,4.4 
field 2 isn't a number|ThisLineFails,BecauseOfThis 
field 2 isn't a number|How would I also get an error, for this line as well considering the last one would have rolled back the transaction already? 

答えて

2

オブジェクトを保存せずに検証することができます(http://grails.org/doc/2.0.x/guide/validation.html#validatingConstraints)。そのため、サービスではすべてのオブジェクトを作成し、すべてのオブジェクトを検証してからすべてのオブジェクトを保存することができます。次のようなもの:

def serviceMethod(data) { 
    def listOfObjects = createObjectsFromData(data) 
    listOfObjects*.validate() 
    def anErrorOccurred = listOfObjects.find {it.hasErrors()} != null 
    if(anErrorOccurred) { 
     return listOfObjects 
    } 
    listOfObjects*.save(validate: false) //you could use the validate:false or leave it out. I figure since we've already validated that you could do without re-validating. 
} 

このようにして、すべてのエラーを収集し、トランザクションのロールバックを心配する必要はありません。この設定の問題は、N個のオブジェクトを作成してそれらのすべてを保持することです。あなたのファイルが100k行よりも長い場合(苦労し始める場所を少し推測します)、これはパフォーマンス上の問題を引き起こす可能性があります。 (http://grails.org/doc/2.0.x/ref/Domain%20Classes/withTransaction.html

def serviceMethod(data) { 
    MyDomainClass.withTransaction { status -> 
     def listOfObjects = [] 
     data.each { 
      def domainObject = createObjectFromData(it) 
      lisOfObjects << domainObject.save() 
     } 
     def anErrorOccurred = lisOfObjects.find {it.hasErrors()} != null 
     if(anErrorOccurred) { 
      status.setRollbackOnly() //will roll back all of the transactions surrounded by the .withTransaction {} 
     } 
    } 
} 

(あなたが発生したすべてのエラーを取得したいので)あなたがまだここにオブジェクトのすべてを握っている:あなたが手動でトランザクションを処理することができ、上記の方法が気に入らない場合。私が考えることのできる方法の1つは、オブジェクトを一度に1つずつ作成し、該当する場合にエラーをリストに追加して検証することですが、すべてのオブジェクトを再作成する必要があります彼らはすべて非常に効率的ではないように見える検証をパスします。

+0

http://naleid.com/blog/2009/10/01/batch-import-performance-with-grails-and-mysql/ 100kで本当に苦しんでいると思われ、約10kの闘いを見始めるようです。それは私がこのソリューションが私のためにうまく動作すると思うと言われています:) – Mikey

+0

また、おそらく、おそらくgrailsがその問題を先取りしています...今まで私のソースの日付を見ていませんでした。 – Mikey

2

は私が考えているものです。 ALL CLEARに通知するフラグを設定し、すべてがクリアであれば最後に手動でトランザクションをコミットします。

または

2です。失敗した行のエラーをキャプチャし、失敗をスキップする別のトランザクションで各行をコミットします。

関連する問題