2016-12-02 11 views
0

プロパティpを持つドメインAがあるとします。値がリストから順番に割り当てられる一括更新を効率的に行う方法はありますか?

class A{ 
Integer p 
} 

私はすなわち

def lis = A.list() 

のリストを持っているし、私はそれぞれのGrailsで一括更新を行うための最も効率的な方法は何か数字

def num = [4, 1, 22, ......] 

のリストを持っていますAのオブジェクトにはnumから順番に番号が割り当てられます。

一つの方法は、

for(int i=0; i<lis.size(); i++){ 
    lis[i].p = num[i] 
    lis[i].save(flush: true) 
} 

ことができるが、私は仮定し、このソリューションは、効率的ではありません。これはHQLまたは他の効率的な方法を使用して達成できますか?私は助けていただきありがとうございます!ありがとう!

答えて

0

あなたのソリューションは非効率的である可能性があると私は同意しますが、ほとんどの場合、保存ごとにフラッシュしていることが原因です。したがって、transactionを使用してパフォーマンスを向上させることができます。コミット時にこれは自動的にフラッシュが発生します。もちろん

A.withTransaction { status -> 
    ... 

    for(int i=0; i<lis.size(); i++) { 
     lis[i].p = num[i] 
     lis[i].save() 
    } 
} 

、あなたは@Transactionalアノテーションを使用することができた場合、それが良いだろう。

はい、あなたはHQLを使うことができますが、ここでの基本的な問題は数字のリストが任意であるため、複数のHQLクエリが必要になることです。各更新ごとに1つ。

トランザクションアプローチを最初に試してください。これはセットアップが最も簡単な方法です。

1

Aと番号のリストは、(lis.sizeは10 000に等しい例えばある場合)を処置するためのデータの非常に大きな量であれば、あなたはこれを行う必要があります。

A.withNewTransaction { status -> // begin a new hibernate session 

    int stepForFlush = 100 
    int totalLisSize = A.count() 
    def lis 

    for(int k=0; k < totalLisSize; k+=stepForFlush) { 

     lis = A.list(max: stepForFlush, offset: k) // load only 100 elements in the current hibernate session 
     ... 

     for(int i=0; i<lis.size(); i++) { 
     lis[i].p = num[k+i] 
     lis[i].save() 
     } 
     A.withSession { session -> 
     session.flush() // flush changes to database 
     session.clear() // clear the hibernate session, the 100 elements are no more attached to the hibernate session 
         // Then they are now eligible to garbage collection 
         // you ensure not maintaining in memory all the elements you are treating 
     } 
    } // next iteration, k+=100 


    } // Transaction is closed then transaction is commited = a commit is executed to database, 
    // and then all changes that has been flush previously are committed. 

注:

メモリ内のすべてのA要素を読み込まず、A.list()。size()が非常に大きいときに役立ちます。

関連する問題