Hibernate PersistentMap 返回错误的值
Hibernate PersistentMap returning wrong values
我正在开发一个应用程序 运行 Grails 2.4.5 和 Hibernate 3.6.10。
有一个具有子 PersistentMap 的域对象。此地图存储 4
值始终为字符串的键值对。
在我们的开发和测试环境中,一切正常,然后偶尔
持久映射开始为键或值返回“1”。
父域对象中的其他值都可以。问题是
通过直接更新地图的记录之一解决问题
在数据库中。这让我觉得这是某种缓存问题,
但我无法在本地环境中重新创建它。
下面的数据库是MySQL。
以下不是实际代码,但代表结构。
class MyDomain {
static belongsTo = [owner: Owner]
static hasMany = [relatedDomains: RelatedDomain]
Set relatedDomains = []
Map flags = [:]
String simpleItem
String anotherItem
static constraints = {
owner(nullable: true)
relatedDomains(nullable: true)
flags(nullable: true)
simpleItem(nullable: true)
anotherItem(nullable: true)
}
}
这会生成几个表(忽略 RelatedDomain 和 Owner):
mydomain table
| id | version |owner_id|simple_item|another_item |
|-------|-----------|--------|-----------|-------------|
| 1 | 1 | 1 | A value |Another value|
mydomain_flags table
|flags| flags_ids | flags_elt |
|-----|-----------|-------------|
| 1 | KEY_ONE | VALUE_ONE |
| 1 | KEY_TWO | VALUE_TWO |
| 1 | KEY_THREE | VALUE_THREE |
当检索到 MyDomain 实例时,标志映射将具有:
[ "KEY_ONE": "VALUE_ONE", "KEY_TWO": "VALUE_TWO", "KEY_THREE" :"VALUE_THREE"]
偶尔地图包含:
[ "KEY_ONE": "1", "KEY_TWO": "1", "KEY_THREE" :"1"]<br/>
或
[ "1": "VALUE_ONE", "1": "VALUE_TWO", "1" :"VALUE_THREE"]
MyDomain 实例中的其余数据是正确的。似乎只有标志图有问题。该应用程序只读取 mydomain 和标志的信息,它从不更新数据。它基本上是应用程序的配置数据。
有没有其他人见过这样的行为?我不知道它是否与休眠(版本 3.6.10)或 Grails/Gorm 或两者有关。我无法在本地重现它,但它发生在两个不同的环境中。
我追踪到它是休眠的问题。为持久映射生成的别名导致键和元素的别名相同。这是因为别名基于 org.hibernate.mapping.Table class 中的静态计数器(在 3.6.10 中)。它是零星的原因是因为 Grails 将所有域 classes 加载到一个 HashSet 中,然后迭代绑定每个域的集合。由于 Set 是无序的,有时具有持久映射的域 class 将是第三个 class 映射,导致键别名与元素别名相同。
此问题已在 Hibernate 4.1.7 版中修复
https://hibernate.atlassian.net/browse/HHH-7545
为了解决 Grails 中的问题,我子class编辑了 GrailsAnnotationConfiguration class 并在构造函数中创建并丢弃了 10 个 Hibernate Table 实例。这会在加载 Grails 域 classes.
之前将静态计数器增加到更安全的种子值
我正在开发一个应用程序 运行 Grails 2.4.5 和 Hibernate 3.6.10。 有一个具有子 PersistentMap 的域对象。此地图存储 4 值始终为字符串的键值对。
在我们的开发和测试环境中,一切正常,然后偶尔 持久映射开始为键或值返回“1”。 父域对象中的其他值都可以。问题是 通过直接更新地图的记录之一解决问题 在数据库中。这让我觉得这是某种缓存问题, 但我无法在本地环境中重新创建它。
下面的数据库是MySQL。
以下不是实际代码,但代表结构。
class MyDomain {
static belongsTo = [owner: Owner]
static hasMany = [relatedDomains: RelatedDomain]
Set relatedDomains = []
Map flags = [:]
String simpleItem
String anotherItem
static constraints = {
owner(nullable: true)
relatedDomains(nullable: true)
flags(nullable: true)
simpleItem(nullable: true)
anotherItem(nullable: true)
}
}
这会生成几个表(忽略 RelatedDomain 和 Owner):
mydomain table
| id | version |owner_id|simple_item|another_item |
|-------|-----------|--------|-----------|-------------|
| 1 | 1 | 1 | A value |Another value|
mydomain_flags table
|flags| flags_ids | flags_elt |
|-----|-----------|-------------|
| 1 | KEY_ONE | VALUE_ONE |
| 1 | KEY_TWO | VALUE_TWO |
| 1 | KEY_THREE | VALUE_THREE |
当检索到 MyDomain 实例时,标志映射将具有:
[ "KEY_ONE": "VALUE_ONE", "KEY_TWO": "VALUE_TWO", "KEY_THREE" :"VALUE_THREE"]
偶尔地图包含:
[ "KEY_ONE": "1", "KEY_TWO": "1", "KEY_THREE" :"1"]<br/>
或
[ "1": "VALUE_ONE", "1": "VALUE_TWO", "1" :"VALUE_THREE"]
MyDomain 实例中的其余数据是正确的。似乎只有标志图有问题。该应用程序只读取 mydomain 和标志的信息,它从不更新数据。它基本上是应用程序的配置数据。
有没有其他人见过这样的行为?我不知道它是否与休眠(版本 3.6.10)或 Grails/Gorm 或两者有关。我无法在本地重现它,但它发生在两个不同的环境中。
我追踪到它是休眠的问题。为持久映射生成的别名导致键和元素的别名相同。这是因为别名基于 org.hibernate.mapping.Table class 中的静态计数器(在 3.6.10 中)。它是零星的原因是因为 Grails 将所有域 classes 加载到一个 HashSet 中,然后迭代绑定每个域的集合。由于 Set 是无序的,有时具有持久映射的域 class 将是第三个 class 映射,导致键别名与元素别名相同。
此问题已在 Hibernate 4.1.7 版中修复 https://hibernate.atlassian.net/browse/HHH-7545
为了解决 Grails 中的问题,我子class编辑了 GrailsAnnotationConfiguration class 并在构造函数中创建并丢弃了 10 个 Hibernate Table 实例。这会在加载 Grails 域 classes.
之前将静态计数器增加到更安全的种子值