当前位置: 首页 > 面试题库 >

在Hibernate / WebApp上下文中的对象相等

江敏学
2023-03-14
问题内容

如何处理由hibernate管理的Java对象的对象相等性?他们在《冬眠的行动》一书中说,人们应该更青睐商务钥匙而不是代理钥匙。
大多数时候,我没有业务密钥。想想映射到一个人的地址。地址保存在Set中并显示在Wicket
RefreshingView中(使用ReuseIfEquals策略)。

我可以使用代理ID或使用equals()和hashCode()函数中的所有字段。
问题在于这些字段在对象的生存期内会发生变化。因为用户输入了一些数据,或者由于在OSIV(在视图中打开会话)过滤器内调用了JPA
merge(),所以id发生了更改。

我对equals()和hashCode()协定的理解是,这些协定在对象的生存期内不应更改。

到目前为止我尝试过的是:

  • 基于使用数据库ID(或id为null的super.hashCode())的hashCode()的equals()。问题:新地址以空ID开头,但在附加到某人后会获得一个ID,此人在osiv过滤器中被merged()(重新附加)。
  • 首次调用hashCode()时,延迟计算哈希码,并将该哈希码设为@Transitional。不起作用,因为merge()返回一个新对象,并且哈希码不会被复制过来。

我需要的是我认为在对象创建期间分配的ID。我在这里有什么选择?我不想引入一些其他的持久属性。有没有一种方法可以明确地告诉JPA为对象分配ID?

问候


问题答案:

使用id实体的并不是一个好主意,因为临时实体还没有ID(并且您仍然希望临时实体可能等于持久性ID)。

使用所有属性(除了数据库标识符)也不是一个好主意,因为所有属性都不是标识的一部分。

因此,实现平等的首选(正确)方法是使用 业务密钥 ,如 Java Persistence with Hibernate中所述

用业务密钥实现平等

要获得我们推荐的解决方案,您需要了解业务密钥的概念。业务密钥是属性或属性的某种组合,对于具有相同数据库标识的每个实例都是唯一的。本质上,如果您不使用代理主键,那么它就是您要使用的自然键。与自然主键不同,并非绝对要求业务键永不更改-
只要它很少更改,就足够了。

我们认为,基本上每个实体类都应该具有一些业务密钥,即使它包含了该类的所有属性(这对于某些不可变的类也是适当的)。业务密钥是用户认为唯一标识特定记录的东西,而代理密钥是应用程序和数据库使用的东西。

业务密钥相等性意味着equals()方法仅比较构成业务密钥的属性。这是避免前面描述的所有问题的理想解决方案。唯一的缺点是,首先需要额外的思想来识别正确的业务密钥。无论如何,都需要这种努力。如果您的数据库必须通过约束检查确保数据完整性,则标识任何唯一键非常重要。

对于User类,username是一个很好的候选业务密钥。它永远不会为null,它具有数据库约束是唯一的,并且很少更改(如果有的话):

    public class User {
        ...
        public boolean equals(Object other) {
            if (this==other) return true;
            if ( !(other instanceof User) ) return false;
            final User that = (User) other;
            return this.username.equals( that.getUsername() );
        }
        public int hashCode() {
            return username.hashCode();
        }
}

也许我错过了一些东西,但是对于地址,业务密钥通常由街道号,街道,城市,邮政编码,国家/地区组成。我认为没有任何问题。

以防万一,Equals And
HashCode是另一个有趣的读物。



 类似资料:
  • 问题内容: 如何处理由hibernate管理的Java对象的对象相等性?他们在《hibernate的行动》一书中说,人们应该更青睐商务钥匙而不是代理钥匙。 大多数时候,我没有业务密钥。想想映射到一个人的地址。地址保存在Set中,并显示在Wicket RefreshingView中(使用ReuseIfEquals策略)。 我可以使用代理ID或使用equals()和hashCode()函数中的所有字段

  • 上下文对象 上下文对象(Context)是一个类似于 Map<String, Object> 的结构,用户可以用字符串做 Key,放入任何类型的数据。因为该对象不需要在客户端和服务端进行传输,所以它当中存放的数据,不必是可序列化类型。 上下文对象具有判断某个 Key 是否存在的功能,但是在不同语言实现时,可以根据各自语言的特性在语法或方法命名上有所不同。 上下文对象还应具有一个 clone 方法,

  • 上下文对象 context 变量的可用属性一览: 属性字段 类型 可用 描述 app Vue 根实例 客户端 & 服务端 包含所有插件的 Vue 根实例。例如:在使用 axios 的时候,你想获取 $axios 可以直接通过 context.app.$axios 来获取 isClient Boolean 客户端 & 服务端 是否来自客户端渲染(废弃。请使用 process.client ) isS

  • 问题内容: 我正在尝试在Spring上下文文件中创建对象数组,以便可以将其注入声明为这样的构造函数中: 我正在尝试使用标签: 我尚未在文档中找到如何执行此操作的示例或其他内容。另外,对于如何实现我想做的更好的方法,您有任何建议,请告诉我:)。 问题答案: 那是因为没有,只有。 好消息是,Spring会根据需要在列表和数组之间进行自动转换,因此将数组定义为,Spring会为您强制将其转换为数组。 这

  • 在GraalVM CE上跑步。 案例一: 结果: 为什么? 据我所知,正确通过: 返回。 案例2: 例外情况 但是是公共的。。。发生了什么?

  • 本文向大家介绍JS中this上下文对象使用方式,包括了JS中this上下文对象使用方式的使用技巧和注意事项,需要的朋友参考一下 JavaScript 有一套完全不同于其它语言的对 this 的处理机制。 在五种不同的情况下 ,this 指向的各不相同。 有句话说得很在理 -- 谁调用它,this就指向谁 一、全局范围内 在全局范围内使用this ,它将指向全局对象(浏览器中为 window) 二、