问题
Hello I am trying to implement a simple translation list, meaning I have a values and translations to this values.
[Edit:] As this is part of my user interface and values and translations shall be exportable via xml, using the i18n files seams quite inconvinient for this proposition. Thats why I decided to store them in a database.
I have one domain class for a value:
class Value {
String label
static hasMany = [ translations: Translation ]
}
and one for translations with a unique constraint to ensure that for one value there must'nt be more than one translation for a specific language:
class Translation {
String value
Language language
static belongsTo = [ value: Value ]
static constraints = {
language(unique: 'value')
}
}
My problem occures after interchanging two translation languages for the same value. Example:
value.translations.each() { translation ->
println "${value.label} in ${translation.language.label} is ${translation.value}"
}
// process updates...
value.translations.each() { translation ->
println "${value.label} in ${translation.language.label} is ${translation.value}"
}
// validate...
prints out
Comedy in german: Comedy
Comedy in english: Komödie
Comedy in english: Comedy
Comedy in german: Komödie
so the unique constraint is not violated before and after the update, but anyhow I get an unique constraint failure while saving. Another strange thing is, that I only get this error when I execute the each() loop on value. If I don't inspect the contents, the validation passes and the save(flush:true) method returns true, but the values will not be changed in the database.
[Edit:] I believe that the problem is on database level when only one value is altered and the other isn't, because exactly in that state the constraint is violated. If the changes would be executed as a transaction instead and the constraints would not be checked during this intermediate step this could be avoided. (this might be the thing, i am looking for)
Another way to avoid this would be to delete and recreate every edited bean but I was hoping that there might be a more convenient way to do this.
Thanks for any help
回答1:
The constraint is checked when an implicit or explicit flush()
happens. At that moment, GORM checks if there exists another such a value in a database. So, if one instance is already flush()
ed and another is not yet, you'll get a constraint violation.
Try not to flush()
till the end of transaction - remove flush: true
parameter or even set it to flush: false
. At the end of transaction both changes should apply.
There's a caveat in Grails, JFYTK: it does an implicit flush()
when executing a Criteria
, so don't be too surprised about Hibernate errors when you didn't intend to flush()
yet.
来源:https://stackoverflow.com/questions/6174374/grails-unique-test-fails-after-interchanging-attribute-values