SaganTheBest SaganTheBest - 4 months ago 9
Java Question

equals and hashCode of these entities (Spring MVC + Hibernate)

Someone can please suggest me how I can do equals and hashCode methods of these entities?

This is a many-to-many relationship between a Gara (Contest) and Agenzia (Agency):
One contest has many Agency, one Agency can be in more Contest.

I tried some implementations but or I get Stackoverflow error, or,
when I'm updating a Gara (Contest), I can't update the set of Agenzie (Agencies) because i get this error:


org.springframework.dao.DuplicateKeyException: a different object with
the same identifier value was already associated with the session:
[com.myApp.model.GaraAgenzia#com.mmyApp.model.GaraAgenziaId@49f];
nested exception is org.hibernate.NonUniqueObjectException: a
different object with the same identifier value was already associated
with the session:
[com.myApp.model.GaraAgenzia#com.myApp.model.GaraAgenziaId@49f]


when i try to do an update.

thanks

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<GaraAgenzia> garaAgenzie = new HashSet<GaraAgenzia>(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<GaraServizio> garaServizi = new HashSet<GaraServizio>(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<GaraAgenzia> getGaraAgenzie() {
return garaAgenzie;
}

public void setGaraAgenzie(Set<GaraAgenzia> garaAgenzie) {
this.garaAgenzie.clear();
this.garaAgenzie = garaAgenzie;
}

public Set<GaraServizio> getGaraServizi() {
return garaServizi;
}

public void setGaraServizi(Set<GaraServizio> 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;
}
*/
}


Edit 1:
If i clear the set of Agencies (and Services) before
set again it:

garaToUpdate.getGaraAgenzie().clear();
garaToUpdate.getGaraServizi().clear();

getCurrentSession().flush();

garaToUpdate.setGaraAgenzie(gara.getGaraAgenzie());
garaToUpdate.setGaraServizi(gara.getGaraServizi());

getCurrentSession().update(garaToUpdate);


i get this error:


A collection with cascade="all-delete-orphan" was no longer
referenced by the owning entity instance:


Edit 2:
As suggested by @JamesB, i added the toString method to GaraAgenzia and GaraAgenziaId. Here the result BEFORE update the Gara record:

this is the record taken from db just before update it


INFO : com.machinet.model.GaraAgenziaId - garaToUpdate.GaraAgenzie
(before update): [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)]]]


this is the edited record that will be set in db:


INFO : com.machinet.model.GaraAgenziaId - editedGara.GaraAgenzie
(before update): [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]]]

Answer

These seem to work well. I post hoping someone will find it useful:

GaraAgenzia class:

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);
    }   

GaraAgenziaId class:

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;
}