如何处理由hibernate管理的Java对象的对象相等性?他们在《hibernate的行动》一书中说,人们应该更青睐商务钥匙而不是代理钥匙。
大多数时候,我没有业务密钥。想想映射到一个人的地址。地址保存在Set中,并显示在Wicket
RefreshingView中(使用ReuseIfEquals策略)。
我可以使用代理ID或使用equals()和hashCode()函数中的所有字段。
问题在于这些字段在对象的生存期内会发生变化。由于用户输入了一些数据,或者由于在OSIV(在视图中打开会话)过滤器内调用了JPA
merge()而导致ID更改。
我对equals()和hashCode()协定的理解是,这些协定在对象的生存期内不应更改。
到目前为止我尝试过的是:
我需要的是一个我认为在对象创建期间分配的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() ); } html" target="_blank">public int hashCode() { return username.hashCode(); } }
也许我错过了一些东西,但是对于地址,业务密钥通常由街道号,街道,城市,邮政编码,国家/地区组成。我认为没有任何问题。
以防万一,Equals And
HashCode是另一个有趣的读物。
问题内容: 如何处理由hibernate管理的Java对象的对象相等性?他们在《冬眠的行动》一书中说,人们应该更青睐商务钥匙而不是代理钥匙。 大多数时候,我没有业务密钥。想想映射到一个人的地址。地址保存在Set中并显示在Wicket RefreshingView中(使用ReuseIfEquals策略)。 我可以使用代理ID或使用equals()和hashCode()函数中的所有字段。 问题在于这些
如果我有多个线程,每个线程使用injector获取EntityManager对象,每个线程使用em对象选择其他类对象的列表。准备好在for循环中使用。 如果一个线程首先完成并调用clear(),这会影响其他线程吗?比如for循环会有异常? 谢谢你。
问题内容: 我有一个对象,其内部可变状态正在由一个或多个线程不断更新。对象已同步,目标是从另一个线程定期保存其状态(通过序列化): 问题: 在这种情况下,序列化安全吗? 它是如何工作的?也就是说,执行序列化是否会阻塞直到不再有线程运行? 如果同步不使用固有锁,而是使用其他锁怎么办? 问题答案: 在这种情况下,序列化安全吗? 否。正如@Tom Hawtin所说,您将需要执行自己的锁定,以确保在序列化
当试图使用webapp(使用Elixir/Ecto作为后端语言)、postgres数据库、elasticsearch和kibana创建一个项目时,使用以下docker-compose.yaml文件: ,
hibernate中的一级缓存维护在会话对象上,并且在同一JVM的边界内。它是hibernate使用的强制缓存。我担心的是如何在集群环境中管理it。多个节点将拥有自己的一级缓存(等于会话数)。在单个JVM中,一个实体可以是不同会话的一部分,但事务管理器、乐观锁定可以处理这种情况。。。。但是,我们将如何在集群环境中管理it 1)一个实体可以在两个不同节点的一级缓存中被修改,导致数据过时、数据丢失等问
3.13 环境抽象 {#toc_11} 在应用环境中,集成在容器的抽象环境模型有两个方面:profiles和properties。只有给出的profile被激活,一组逻辑命名的bean定义才会在容器中注册。无论是在XML中或者通过注解,bean都会被分配给一个profile。环境变量对象角色和profiles的关系来决定哪个profiles(如果有)处于当前激活状态,哪个profiles默认被激活