その中でそれが可能かどうかを言うのに十分なほど、私はgrailsを知りません。クラスのプロパティを一覧表示して動的に構成することで SQL 挿入フィールドを生成しようとしましたが、順序が狂ってしまいます。
CSV 内のそのフィールドの位置を定義する注釈を作成できます。
import java.lang.annotation.*
@Retention(RetentionPolicy.RUNTIME) @interface CSV { int position() }
class Product {
@CSV(position=1) String description
@CSV(position=3) BigDecimal price
@CSV(position=4) Integer type
@CSV(position=2) boolean soldout
}
複数のマッピングが必要な場合 (たとえば、独自の古い CSV をサポートするため)、エンティティから切り離されるマップ構造または XML を検討する必要があります。
次に、フィールドを繰り返してクエリを作成する必要があります。
def csv = '''rice;10.0;3;false
beet;12.0;2;false
mango;22.0;2;true'''
def properties = Product.declaredFields
.findAll { it.declaredAnnotations }
.sort { it.declaredAnnotations[0].position() }
def templateQuery = "INSERT INTO product(#fields) VALUES (#values)"
csv.eachLine { line ->
def fields = line.split( /;/ )
def sqlFields = [:]
fields.eachWithIndex { field, i ->
sqlFields[properties[i].name] = field
}
println templateQuery
.replace('#fields', sqlFields.keySet().join(","))
.replace('#values', sqlFields.values().join(","))
}
どちらが印刷されますか:
INSERT INTO product(description,price,type,soldout) VALUES (rice,10.0,3,false)
INSERT INTO product(description,price,type,soldout) VALUES (beet,12.0,2,false)
INSERT INTO product(description,price,type,soldout) VALUES (mango,22.0,2,true)
それはかなり生で、引用符やSQLインジェクションに対するいくつかのものなど、いくつかの研磨が必要ですが、概念実証のように機能します。
私が働いていた古いシステムでは、jboss seam を使用し、jpa バッチで作業した大量のもの、つまりすべてpersist()
が完了したら手動でフラッシュしました。gorm で使用する grails にそのようなものはありませんか?
このリンクwithTransaction
は、定期的にセッション クリアを適用しながら、grails 内でバッチ更新を使用するブログ投稿を示しています。
List <Person> batch =[]
(0..50000).each{
Person person= new Person(....)
batch.add(person)
println "Created:::::"+it
if(batch.size()>1000){
Person.withTransaction{
for(Person p in batch){
p.save()
}
}
batch.clear()
}
session = sessionFactory.getCurrentSession()
session.clear()
}
うまくいかないよね?そうでない場合は、注釈が解決策になる可能性があります。
また、Java のキャメル ケースと db のアンダースコアの違いにより、列の命名にも問題があります。その翻訳の背後にある人物は、休止状態で、ImprovedNamingStrategyです。彼から何かを得ることができるかもしれません。@CSV
または、注釈に列名を追加します。JPAのリサイクルのように聞こえます:-)。
log4jdbcもありますが、問題は解決しないと思います。休止状態のSQL生成に忍び込む必要があります。