gpt4 book ai didi

交换唯一属性值后,Grails 验证失败

转载 作者:行者123 更新时间:2023-12-02 13:58:56 25 4
gpt4 key购买 nike

交换唯一属性值后,Grails 验证失败

嗨,我正在尝试创建一个界面,用户可以在其中创建一些带有不同语言翻译的自定义枚举。例如,用户可以创建一个枚举“电影流派”。对于此枚举,可能存在一个枚举值“喜剧”,对于该枚举值,可能存在多种语言的一个或多个枚举值翻译。

由于特定语言只能有一个翻译,我向枚举值翻译域类添加了一个唯一约束。这些是我现在的域类:

class Enumeration {
String label
List<EnumerationValue> enumerationValues = new ArrayList<EnumerationValue>()

static hasMany = [ enumerationValues: EnumerationValue ]
static constraints = {
label(nullable: false, blank: false)
enumerationValues(nullable: true)
}
}


class EnumerationValue {
String label
List<EnumerationValueTranslation> enumerationValueTranslations = new ArrayList<EnumerationValueTranslation>()

static belongsTo = [ enumeration: Enumeration ]
static hasMany = [ enumerationValueTranslations: EnumerationValueTranslation ]

static constraints = {
label(nullable: false, blank: false, unique: 'enumeration')
enumeration(nullable: false)
enumerationValueTranslations(nullable: false)
}
}


class EnumerationValueTranslation {
String value
Language language

static belongsTo = [ enumerationValue: EnumerationValue ]

static constraints = {
value(nullable: false, blank: false)
language(nullable: true, unique: 'enumerationValue')
enumerationValue(nullable: false)

/* unique constraint as mentioned in description text */
language(unique: 'enumerationValue')
}
}

到目前为止,这工作得很好。当我以语言交换的方式更新相同枚举值的两个枚举值翻译时,我的问题就出现了。例如我有一个
  • 枚举值:“喜剧”

  • 和一些语言“不小心”混淆的翻译
  • “喜剧”的翻译
  • 语言:德语,值:“喜剧”
  • 语言:英语,重视“Komödie”

  • 如果用户发现他混淆了语言,他可能想要交换语言并再次保存枚举。这就是我发生错误的地方,因为在交换语言后,枚举值翻译唯一约束验证为 false。

    为了调试这个,我只是尝试在我处理参数之前和之后打印出导致翻译的错误,所以:
    Enumeration enumeration = Enumeration.get(params['id']);

    println "before:"
    enumeration.enumerationValues.each() { enumValue ->
    enumValue.enumerationValueTranslations.each() { enumValueTr ->
    println enumValueTr;
    if(!enumValueTr.validate()) {
    // print errors...
    }
    }
    }

    // swap languages:
    // (this are the lines of codes that are actually executed, and cause the
    // error. The actual processing of params looks different of course...)

    // sets the language of "Comedy" to English
    EnumerationValueTranslation.get(5).language = Language.get(1);
    // sets the language of "Komödie" to German
    EnumerationValueTranslation.get(6).language = Language.get(2);


    println "after:"
    enumeration.enumerationValues.each() { enumValue ->
    enumValue.enumerationValueTranslations.each() { enumValueTr ->
    println enumValueTr;
    if(!enumValueTr.validate()) {
    // print errors...
    }
    }
    }

    结果为:
    before:
    EnumerationValueTranslation(value: Fantasy, language: en_US, enumerationValue: Fantasy)
    EnumerationValueTranslation(value: Phantasie, language: de_DE, enumerationValue: Fantasy)

    EnumerationValueTranslation(value: Comedy, language: de_DE, enumerationValue: Comedy)
    EnumerationValueTranslation(value: Komödie, language: en_US, enumerationValue: Comedy)


    after:
    EnumerationValueTranslation(value: Fantasy, language: en_US, enumerationValue: Fantasy)
    EnumerationValueTranslation(value: Phantasie, language: de_DE, enumerationValue: Fantasy)

    EnumerationValueTranslation(value: Comedy, language: en_US, enumerationValue: Comedy)
    validation fails: Property [language] of class [Translation] with value [Language(code: en_US)] must be unique
    EnumerationValueTranslation(value: Komödie, language: de_DE, enumerationValue: Comedy)
    validation fails: Property [language] of class [Translation] with value [Language(code: de_DE)] must be unique

    在这种状态下,我没有删除或保存(或以任何方式刷新)任何内容 - 这只是更改对象后的结果。正如您所看到的,实际数据中确实没有不一致,验证不应该失败。

    我更改翻译的方式可能有错误吗?我只是通过 ID 获取它们并简单地更新了语言 - 我在一个简约的例子中尝试了它并且它在那里工作......
    如果我只是创建所有枚举值和枚举值翻译的深拷贝并存储它也可以工作(这意味着验证确实不应该失败),但我认为这真的不是它应该的方式完毕...

    另一个奇怪的事情是,只有在我遍历数据时验证才会失败。如果我根本不接触数据,则不会发生错误,但数据也不会保存,这意味着以下几行会导致对验证进行评估:
    enumeration.enumerationValues.each() { ev ->
    ev.enumerationValueTranslations.each() { evt ->

    }
    }

    这就是为什么我坚信一定有一些重要的问题......如果还有什么你需要知道的,请告诉我。

    谢谢你的帮助

    最佳答案

    让我再试一次:)

    我在看 UniqueConstraint.processValidate() ,并且可以假设其逻辑不考虑交换情况。

    特别是,代码

        boolean reject = false;
    if (id != null) {
    Object existing = results.get(0);
    Object existingId = null;
    try {
    existingId = InvokerHelper.invokeMethod(existing, "ident", null);
    }
    catch (Exception e) {
    // result is not a domain class
    }
    if (!id.equals(existingId)) {
    reject = true;
    }
    }
    else {
    reject = true;
    }

    应该迭代获得的 results并验证字段值 仍然 违反唯一性。在交换的情况下,另一个实例应该从缓存中选取并具有新的字段值。

    所以我建议你创建一个自己的后代 UniqueConstraint并使用它,除非有人要修补 Grails。

    关于交换唯一属性值后,Grails 验证失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6192786/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com