是否有任何与此JPA“缓存的hashCode”模式? [英] Are there any gotchas with this JPA "cached hashCode" pattern?

查看:139
本文介绍了是否有任何与此JPA“缓存的hashCode”模式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 #hibernate IRC上,有人与我共享以下(部分)模式

  @Entity 
public MyEntity(){

...主键,对象属性,getters / setters在这里...

@Column(nullable = false)
private int hashCode;

public MyEntity(){
hashCode + = id;
}

private final Set< String> tags = Sets.newHashSet();
$ b $ public void addTag(String tag){
if(tags.add(tag)){
hashCode + = tag.hashCode();



public void removeTag(String tag){
if(tags.remove(tag){
hashCode - = tag.hashCode );
}
}

public void hashCode(){
return hashCode;
}

... http ://www.artima.com/lejava/articles/equality.html风格等于...
}

我们可以把它称为分段更新的缓存hashCode(这肯定是 NOT 是一些评论者似乎相信的商业密钥模式。需要一个具有唯一性约束的列,例如用于相等性测试的用户名)。



当在JPA / Hibernate中使用时,它表示 @Entity 可以与 JBoss Equals和HashCode文章,但却表现出开发人员期望的任何方式mal Javabean对象的行为(即而不必像数据库行那样考虑对象):在被保存到数据库之前;在 EAGER 取模模式中的交易之后;并随时在交易 EXTENDED LAZY 然而,确保 hashCode 始终正确更新可能是一个真正的挑战。

p>

这里有没有人有过这种模式的经验,您可以分享您的发现(包括正面和负面)吗?我对但是我对这样的评论完全没有兴趣,这些评论声称某些东西是坏的,没有关于它为什么坏的坚实论点。

请注意,我知道<一个href =https://stackoverflow.com/questions/5031614> JPA的hashCode()/等()困境,但我不认为这种模式实际上是在讨论中涵盖。



这个模式最初被认为是一种避免在 @中嵌套集合 s时出现问题的方法实体 s,例如遇到中的Hibernate LazyInitializationException。


$ b 更新:一些评论者对现有方法越来越热衷。为了避免疑问,我只是对这种新模式的优点感兴趣。为了您的参考,并且还要求您不要说您认为equals / hashCode应该如何实现,请注意,我对 @Entity s使用了以下模式现在年:

  @Id 
private UUID id = UUID.randomUUID();

@Override
public boolean equals(Object obj){
if(this == obj)
return true;
if(!(obj instanceof MY_CLASS)|| id == null)
return false;
MY_CLASS other =(MY_CLASS)obj;
return id.equals(other.id);
}

@Override
public int hashCode(){
Preconditions.checkNotNull(id,必须在调用@ Entity.hashCode之前设置id) ;
return id.hashCode();
}

我只是最近尝试了一些新东西,看看我是否真的需要一个单独的方法是这样的

  public boolean hasSameProperties(Note other){
Preconditions.checkNotNull(other);
if(this == other)
return true;
返回Objects.equal(source,other.source)
&& Objects.equal(title,other.title)
&& Objects.equal(tags,other.tags)
&& Objects.equal(contents,other.contents);
}


解决方案

独特的,所以它看起来像equals()的糟糕的选择。

商业密钥1002有标签500和标签-502添加到它,商业密钥995有标签3和标签2添加到它?这些对象是否真的意味着相同?



<32> 32位数的碰撞风险相对较低,对于您的特定实体所服务的任何目的而言都是可以容忍的,作为一种'模式',人们会希望它实际上是正确的,而不是对于给定的数据大小任意失败。


I was on #hibernate IRC and somebody shared the following (partial) pattern with me

@Entity
public MyEntity() {

  ... primary key, object properties, getters/setters go here ...    

  @Column(nullable=false)
  private int hashCode;

  public MyEntity() {
     hashCode += id;
  }

  private final Set<String> tags = Sets.newHashSet();

  public void addTag(String tag) {
     if(tags.add(tag)) {
         hashCode += tag.hashCode();
     }
  }

  public void removeTag(String tag) {
     if(tags.remove(tag) {
        hashCode -= tag.hashCode();
     }
  }

  public void hashCode() {
    return hashCode;
  }

  ... http://www.artima.com/lejava/articles/equality.html style equals ...
}

One could call this a "cached hashCode which is updated piecewise". (This is definitely NOT a "business key" pattern as some commenters seem to believe. The "business key" pattern requires a column with a uniqueness constraint on it, like a username, which is used for equality tests).

When used in JPA/Hibernate, it means that the @Entity can has similar advantages to "eq/hC with buisness [sic] key" from the JBoss Equals and HashCode article, yet behave the way a developer would expect any normal Javabean object to behave (i.e. without having to think about the object like a database row): before being persisted to the DB; after a Transaction in EAGER fetching modes; and at any time with LAZY fetch inside a Transaction or in EXTENDED mode.

However, ensuring that the hashCode is always updated correctly could be a real challenge.

Does anybody here have any experience with this pattern and could you share your discoveries (both positive and negative) about it? I'm extremely interested in Gotchas but I am not at all interested in comments which make claims that something is "bad" without solid arguments about why it is bad.

Note that I am aware of The JPA hashCode() / equals() dilemma, but I don't believe this pattern was actually covered in that discussion.

This pattern was originally suggested as a way to avoid a problem when loading nested Collections in @Entitys, such as encountered in Hibernate LazyInitializationException on find() with EAGER @ElementCollection.

UPDATE: some commenters are getting very passionate about the existing approaches. For the avoidance of doubt, I am just interested in the merits of this new pattern. For your reference, and to also ask you to stop saying how you believe equals/hashCode should be implemented, note that I have used the following pattern for my @Entitys for several years now:

@Id
private UUID id = UUID.randomUUID();

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (!(obj instanceof MY_CLASS) || id == null)
        return false;
    MY_CLASS other = (MY_CLASS) obj;
    return id.equals(other.id);
}

@Override
public int hashCode() {
    Preconditions.checkNotNull(id, "id must be set before @Entity.hashCode can be called");
    return id.hashCode();
}

and I only recently tried something new to see if I really needed to have a separate method like this

public boolean hasSameProperties(Note other) {
    Preconditions.checkNotNull(other);
    if (this == other)
        return true;
    return Objects.equal(source, other.source)
            && Objects.equal(title, other.title)
            && Objects.equal(tags, other.tags)
            && Objects.equal(contents, other.contents);
}

解决方案

This business key isn't unique, so it seems like a poor choice for equals().

Business key 1002 has tag 500 and tag -502 added to it, business key 995 has tag 3 and tag 2 added to it? Are those objects really meant to be equal?

The relatively low risk of collisions for 32 bit numbers may be tolerable for whatever purpose your particular entity serves, but to refer to something as a 'Pattern' one would like for it to actually be correct, not just arbitrarily unlikely to fail for a given data size.

这篇关于是否有任何与此JPA“缓存的hashCode”模式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆