0

Grails サービスで、外部リストに基づいてドメイン エンティティを作成/更新します。更新はループで行われます。入力ファイルの行が有効な場合、エンティティが更新されます。それ以外の場合は、障害のある行番号を保存して、次の行を処理します。

問題:エンティティで validate() を呼び出すと、結果が の場合false、サービスで行われたすべての作業がロールバックされます。たとえそれが検証に関連していなくても、例外は表示されません。例えば:

assert contact.firstName = 'Bruce'
contact.firstName = 'John'
assert contact.save()
...
company.vat = 'bogus'
if (!company.validate()) {
    log.error "bogus"
    company.discard()
} else {
    assert company.save()
}
log.debug "done"

会社が検証しない場合、私のログには「偽物」と「完了」と表示されます。連絡先の名は'Bruce'データベースにあり、 ではありません'John'

代替バージョン: に電話しないとcompany.validate()、連絡先の名が更新されます。

この段階で、Grails が validate() 呼び出しで会社のインスタンスをアタッチし、discard() の努力にもかかわらず、検証が通らなかったことに気付いたときにトランザクションを破滅させているのではないかと思います。

validate() セマンティックとその javadoc (「インスタンスを検証する」) から、検証が失敗するかどうか、または validate() を呼び出すかどうかに関係なく、副作用は期待できませんでした。

どう思いますか?これは「通常の」動作ですか、それともバグですか? どうすればこれを回避できますか?

必要に応じて、2 つのエンティティを使用した単純な再現ケースがあります。

4

2 に答える 2

0

ここで何かが欠けているかもしれませんが、変更を適用しないという「破棄」メソッドの全体的な目標ではなく、ここで表示されているもの (検証エラーの場合に変更を適用しない) は論理的でしょうか?

于 2013-01-14T13:59:04.627 に答える
0

この設定でテストすることはできませんが、サービスで transactional = false を設定し、すべてのオブジェクトを処理して (正しく検証されたオブジェクトを 1 つのリストに追加し、失敗したオブジェクトを別の場所に保存/ログに記録して)、最後に「良い」オブジェクトを保存できますか? " withTransaction を使用したオブジェクトのリスト? 何かのようなもの:

static transactional = false
def sessionFactory
List<Company> validCompanies = []
for(Company company: listOfCompaniesToValidate) {
    if (!company.validate()) {
        log.error "bogus"
    } else {
        validCompanies.add(company)
    }
}
Company.withTransaction {
    for (Company validCompany: validCompanies)
        validCompany.save()
    }
    validCompanies.clear()
}
sessionFactory.getCurrentSession().clear();

ただのアイデア!

于 2013-01-14T18:23:54.343 に答える