2

我有一个包含 2 个主要列的表:名称和不带重音的名称。当第一个更改时,我希望休眠更新第二个:

@Column(name = "name")
public String getName() {
    return this.name;
}

public void setName(String s) {
    this.name = s;
    this.noAccentName = RemoveDiacritics(name);  //remove diacritics from name
}

@Column(name = "noaccent_name")
public String getNoAccentName() {
    return this.noAccentName;
}

public void setNoAccentName(String s) {
    this.noAccentName = s;
}

这是有效的,但它有一个开销:名称的设置器将对象设置为脏,并且休眠想要一直更新它...... :(

当“名称”以干净的方式更改时,我如何要求休眠更新“noAccentName”?

非常感谢。

4

5 回答 5

3

您找到了拦截​​器,但从 Hibernate 4 开始,推荐的执行此类操作的方法是使用回调方法。事实上,我在 Hibernate 4 中根本找不到拦截器,所以如果你这样做,你可能没有升级路径。

我相信你想要做的是:

@Column(name = "name")
public String getName() {
    return this.name;
}

public void setName(String s) {
    this.name = s;
}

@PrePersist
private void updateNoAccentName() {
    this.noAccentName = RemoveDiacritics(this.name);
}

@Column(name = "noaccent_name")
public String getNoAccentName() {
    return this.noAccentName;
}

private void setNoAccentName(String s) {
    this.noAccentName = s;
}

然后 Hibernate 将负责在保存对象之前更新 noAccentName。请注意,我还将 setNoAccentName 方法设置为私有,因为无法从 noAccentName 转换为 name 并获得正确的重音。

于 2012-04-20T14:00:44.157 回答
1

我找到了解决方案。:) 它的名字是休眠拦截器。

http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/events.html

在一个简单的拦截器的帮助下,我可以根据另一个来更新 noAccent 字段。

感谢您的时间和精力,

于 2012-04-20T12:19:35.730 回答
0

给定 name 的值,你总能得出 noAccentName 吗?如果是这样,您应该标记它以及 getter 和 setter @Transient,以便它们不再受 hibernate 的影响。只需在设置 name 时设置 noAccentName 的值,除非 name 的值更改,否则 hibernate 不会更新该特定实例。

编辑: 或者,您可以尝试检查名称与分配的新名称的相等性,因此除非绝对必要(这会导致休眠将其标记为脏),否则您不会分配任何字段。如果它仍然更新,要么是因为 hibernate 被配置为更新,要么是因为另一个字段也在更新。

于 2012-04-19T12:44:56.490 回答
0

一种简单的方法是使用字段访问而不是属性访问,甚至可能仅针对这两个属性(请参阅访问类型,不推荐)。

于 2012-04-19T21:08:15.943 回答
0

我认为这是一个域命名问题。此时调用 setName 时,您不仅仅是在设置名称。另一种像 changeName 这样改变两者值的方法似乎更合适。尽管我同意 Neil 的观点,如果该值始终是派生的,那么保留名称和更改后的名称就没有什么价值了。如果您的应用程序是唯一使用该信息的应用程序,为什么不删除该列并仅提供一个单独的访问器来删除变音符号。

于 2012-04-19T21:22:05.370 回答