这些实体的equals和hashCode(Spring MVC + Hibernate)

有人可以建议我如何做这些实体的equals和hashCode方法?

这是Gara(竞赛)和Agenzia(代理商)之间的多对多关系:一个竞赛有很多代理商,一个代理商可以参加更多竞赛。

我尝试了一些实现但是我得到Stackoverflow错误,或者,当我更新Gara(竞赛)时,我无法更新Agenzie(代理商)的集合,因为我收到此错误:

org.springframework.dao.DuplicateKeyException:具有相同标识符值的另一个对象已与会话关联:[com.myApp.model.GaraAgenzia#com.mmyApp.model.GaraAgenziaId@49f]; 嵌套exception是org.hibernate.NonUniqueObjectException:具有相同标识符值的另一个对象已与会话关联:[com.myApp.model.GaraAgenzia#com.myApp.model.GaraAgenziaId@49f]

当我尝试做更新。

谢谢

Gare.java:

@Entity @Table(name = "gare") public class Gara extends BaseEntity implements Serializable { private static final long serialVersionUID = 6395640401966812691L; /* * inizializzo logger */ static Logger logger = LoggerFactory.getLogger(Gara.class); /* * molti a molti gara-agenzia * * EAGER altrimenti da errore: could not initialize proxy - no Session */ @OneToMany(fetch = FetchType.EAGER, mappedBy = "pk.gara", cascade=CascadeType.ALL, orphanRemoval=true) private Set garaAgenzie = new HashSet(0); /* * molti a molti gara-servizi * * EAGER altrimenti da errore: could not initialize proxy - no Session */ @OneToMany(fetch = FetchType.EAGER, mappedBy = "pk.gara", cascade=CascadeType.ALL, orphanRemoval=true) private Set garaServizi = new HashSet(0); /* * * colonna TITOLO * */ @NotNull(message = "Il campo TITOLO è obbligatorio") @NotEmpty(message = "Il campo TITOLO è obbligatorio") @Size(min = 0, max = 255, message = "Lunghezza massima campo TITOLO: 255 caratteri") @Column(name = "TITOLO", length = 255) private String titolo; /* * * colonna OBIETTIVO * */ @NotNull(message = "Il campo OBIETTIVO è obbligatorio") @Min(value = 1, message = "Il campo OBIETTIVO deve essere maggiore di ZERO") @Column(name = "OBIETTIVO") private int obiettivo = 0; /* * * colonna BONUS * */ @NotNull(message = "Il campo BONUS è obbligatorio") @Min(value = 1, message = "Il campo BONUS deve essere maggiore di UNO") @Column(name = "BONUS") private float bonus = 0f; @Column(name = "data_iniziale", nullable = false) private Date dataIniziale; @Column(name = "data_finale", nullable = false) private Date dataFinale; public Set getGaraAgenzie() { return garaAgenzie; } public void setGaraAgenzie(Set garaAgenzie) { this.garaAgenzie.clear(); this.garaAgenzie = garaAgenzie; } public Set getGaraServizi() { return garaServizi; } public void setGaraServizi(Set garaServizi) { this.garaServizi.clear(); this.garaServizi = garaServizi; } public void GaraServizio(GaraServizio gara_servizio) { garaServizi.add(gara_servizio); gara_servizio.setGara(this); } public void removeGaraServizio(GaraServizio gara_servizio) { garaServizi.remove(gara_servizio); gara_servizio.setGara(null); } public void GaraAgenzia(GaraAgenzia gara_agenzia) { garaAgenzie.add(gara_agenzia); gara_agenzia.setGara(this); } public void removeGaraAgenzia(GaraAgenzia gara_agenzia) { garaAgenzie.remove(gara_agenzia); gara_agenzia.setGara(null); } public String getTitolo() { return titolo; } public void setTitolo(String titolo) { this.titolo = titolo; } public int getObiettivo() { return obiettivo; } public void setObiettivo(int obiettivo) { this.obiettivo = obiettivo; } public float getBonus() { return bonus; } public void setBonus(float bonus) { this.bonus = bonus; } public Date getDataIniziale() { return dataIniziale; } public void setDataIniziale(Date dataIniziale) { this.dataIniziale = dataIniziale; } public Date getDataFinale() { return dataFinale; } public void setDataFinale(Date dataFinale) { this.dataFinale = dataFinale; } @Override public String toString() { return "Gara [garaAgenzie=" + garaAgenzie + ", garaServizi=" + garaServizi + ", titolo=" + titolo + ", obiettivo=" + obiettivo + ", bonus=" + bonus + ", dataIniziale=" + dataIniziale + ", dataFinale=" + dataFinale + "]"; } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + Float.floatToIntBits(bonus); result = prime * result + ((dataFinale == null) ? 0 : dataFinale.hashCode()); result = prime * result + ((dataIniziale == null) ? 0 : dataIniziale.hashCode()); result = prime * result + obiettivo; result = prime * result + ((titolo == null) ? 0 : titolo.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (getClass() != obj.getClass()) return false; Gara other = (Gara) obj; if (Float.floatToIntBits(bonus) != Float.floatToIntBits(other.bonus)) return false; if (dataFinale == null) { if (other.dataFinale != null) return false; } else if (!dataFinale.equals(other.dataFinale)) return false; if (dataIniziale == null) { if (other.dataIniziale != null) return false; } else if (!dataIniziale.equals(other.dataIniziale)) return false; if (obiettivo != other.obiettivo) return false; if (titolo == null) { if (other.titolo != null) return false; } else if (!titolo.equals(other.titolo)) return false; return true; } } 

GaraAgenzia.java:

 @Entity @Table(name = "gare_agenzie") @AssociationOverrides({ @AssociationOverride(name = "pk.gara", joinColumns = @JoinColumn(name = "gara_id")), @AssociationOverride(name = "pk.agenzia", joinColumns = @JoinColumn(name = "agenzia_id")) }) public class GaraAgenzia implements Serializable { private static final long serialVersionUID = 3865586469933888797L; /* * inizializzo logger */ static Logger logger = LoggerFactory.getLogger(GaraAgenzia.class); /* * * numero contratti: * * */ private int numeroContratti = 0; private GaraAgenziaId pk = new GaraAgenziaId(); @EmbeddedId public GaraAgenziaId getPk() { return pk; } public void setPk(GaraAgenziaId pk) { this.pk = pk; } @Transient public Gara getGara() { return getPk().getGara(); } public void setGara(Gara gara) { getPk().setGara(gara); } @Transient public Agenzia getAgenzia() { return getPk().getAgenzia(); } public void setAgenzia(Agenzia agenzia) { getPk().setAgenzia(agenzia); } @Column(name = "numero_contratti") public int getNumeroContratti() { return numeroContratti; } public void setNumeroContratti(int numeroContratti) { this.numeroContratti = numeroContratti; } public boolean equals(Object other) { if (this == other) return true; if ( !(other instanceof GaraAgenzia) ) return false; final GaraAgenzia gara_agenzia = (GaraAgenzia) other; if ( !gara_agenzia.getGara().equals( getGara() ) ) return false; if ( !gara_agenzia.getAgenzia().equals( getAgenzia() ) ) return false; return true; } public int hashCode() { int result; result = getGara().hashCode(); result = 29 * result + getAgenzia().hashCode(); return result; } } 

GaraAgenziaId.java:

 @Embeddable public class GaraAgenziaId implements Serializable { private static final long serialVersionUID = 4934033367128755763L; /* * inizializzo logger */ static Logger logger = LoggerFactory.getLogger(GaraAgenziaId.class); private Gara gara; private Agenzia agenzia; @ManyToOne public Gara getGara() { return gara; } public void setGara(Gara gara) { this.gara = gara; } @ManyToOne public Agenzia getAgenzia() { return agenzia; } public void setAgenzia(Agenzia agenzia) { this.agenzia = agenzia; } /* * override del metodo di uguaglianza */ @Override public boolean equals(Object o) { if (this == o) return true; if (o == null) return false; if (o instanceof GaraAgenzia) { final GaraAgenzia other = (GaraAgenzia) o; return (Objects.equal(getGara().getId(), other.getGara().getId())) && (Objects.equal(getAgenzia().getId(), other.getAgenzia().getId())); } return false; } /* * override del metodo creazione hashcode */ @Override public int hashCode() { return Objects.hashCode(getGara().getId(), getAgenzia().getId()); } /* public boolean equals(Object other) { if (this == other) return true; if ( !(other instanceof GaraAgenziaId) ) return false; final GaraAgenziaId gara_agenzia = (GaraAgenziaId) other; if ( !gara_agenzia.getGara().equals( getGara() ) ) return false; if ( !gara_agenzia.getAgenzia().equals( getAgenzia() ) ) return false; return true; } public int hashCode() { int result; result = getGara().hashCode(); result = 29 * result + getAgenzia().hashCode(); return result; } */ /* @Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (getClass() != obj.getClass()) return false; GaraAgenziaId other = (GaraAgenziaId) obj; if (gara == null) { if (other.gara != null) return false; } else if (!gara.equals(other.gara)) return false; if (agenzia == null) { if (other.agenzia != null) return false; } else if (!agenzia.equals(other.agenzia)) return false; return true; } */ } 

编辑1:如果我再次设置之前清除了一组代理商(和服务):

  garaToUpdate.getGaraAgenzie().clear(); garaToUpdate.getGaraServizi().clear(); getCurrentSession().flush(); garaToUpdate.setGaraAgenzie(gara.getGaraAgenzie()); garaToUpdate.setGaraServizi(gara.getGaraServizi()); getCurrentSession().update(garaToUpdate); 

我收到此错误:

拥有实体实例不再引用具有cascade =“all-delete-orphan”的集合:

编辑2:正如@JamesB所建议的,我将toString方法添加到GaraAgenzia和GaraAgenziaId。 这里的结果是在更新Gara记录之前:

这是在更新之前从db获取的记录

信息:com.machinet.model.GaraAgenziaId – garaToUpdate.GaraAgenzie(更新前):[GaraAgenzia [numeroContratti = 0,pk = GaraAgenziaId [Gara = Gara [titolo = gara title,obiettivo = 999,bonus = 100.00,dataIniziale = 2014- 07-31,dataFinale = 2014-07-31],agenzia = Agenzia(id = 1,nome =’Agency 1 ltd’,ragione sociale = Agency 1 ltd srl)]]

这是将在db中设置的已编辑记录:

信息:com.machinet.model.GaraAgenziaId – editedGara.GaraAgenzie(更新前):[GaraAgenzia [numeroContratti = 0,pk = GaraAgenziaId [Gara = Gara [titolo = gara title,obiettivo = 999,bonus = 100.00,dataIniziale = 2014- 07-31,dataFinale = 2014-07-31],agenzia = Agenzia(id = 1,nome =’Agency 1 ltd’,ragione sociale = Agency 1 ltd srl]]]

这些似乎运作良好。 我希望有人会发现它很有用:

GaraAgenzia课程:

 public boolean equals(Object o) { if (this== o) return true; if (o ==null|| getClass() != o.getClass()) return false; GaraAgenzia that = (GaraAgenzia) o; if (getPk() !=null?!getPk().equals(that.getPk()) : that.getPk() !=null) return false; return true; } public int hashCode() { return (getPk() !=null? getPk().hashCode() : 0); } 

GaraAgenziaIdclass:

 public boolean equals(Object o) { if (this== o) return true; if (o ==null|| getClass() != o.getClass()) return false; GaraAgenziaId that = (GaraAgenziaId) o; if (gara !=null?!gara.equals(that.gara) : that.gara !=null) return false; if (agenzia !=null?!agenzia.equals(that.agenzia) : that.agenzia !=null) return false; return true; } public int hashCode() { int result; result = (agenzia !=null? agenzia.hashCode() : 0); result =31* result + (gara !=null? gara.hashCode() : 0); return result; } 

这不是一个确切的答案,但可以帮助处理类似问题的人。 我创建了一个由所有实体扩展的抽象类。 这样我就不需要在所有实体中实现这些方法。

  public abstract class GenericEntity implements Serializable{ protected static final long serialVersionUID = 1L; abstract public Serializable getId(); @Override public int hashCode() { return (getId() == null) ? System.identityHashCode(this) : getId().hashCode(); } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (this.getClass() != obj.getClass()) return false; if (org.hibernate.Hibernate.getClass(this) != org.hibernate.Hibernate.getClass(obj)) return false; GenericEntity other = (GenericEntity) obj; if (getId() == null || other.getId() == null) return false; return getId().equals(other.getId()); } } 

我认为在你的情况下你可以把它放在你的BaseEntity中。