I have a pretty weird error I have been sitting on for a few days. After learning about the importance of hashCode()
and equals()
and remembering I tried to implement these methods, for which I first used Intellij's generate feature and then, at least for the hashCode()
method, did some things myself. This all is for the following unit test:
@Test
@DisplayName("Should return correct Stundenplan Eintrag given Lehrer [deutschLehrer]")
void findByLehrer() {
List<StundenplanEintrag> stundenplanEintrag = stundenplanEintragRepository.findByLehrer(deutschLehrer);
assertEquals(stundenplanEintrag.get(0).hashCode(), stundenplanEintragExpected.hashCode());
}
StundenplanEintrag.java:
@Override
public int hashCode() {
int prime = 31;
int result = 1;
result = prime * result + Id;
result = prime * result + stunde;
result = prime * result + (klasse != null ? klasse.hashCode() : 0);
result = prime * result + (fach != null ? fach.hashCode() : 0);
result = prime * result + (lehrer != null ? lehrer.hashCode() : 0);
result = prime * result + (tag != null ? tag.hashCode() : 0);
return result;
}
Klasse.java:
@Override
public int hashCode() {
int prime = 31;
int result = 1;
result = prime * result + Id;
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + (schueler != null && !schueler.isEmpty() ? schueler.hashCode() : 0);
// result = prime * result + (stundenplanEintrag != null && !stundenplanEintrag.isEmpty() ? stundenplanEintrag.hashCode() : 0);
result = prime * result + (vertretungsplanEintrag != null && !vertretungsplanEintrag.isEmpty() ? vertretungsplanEintrag.hashCode() : 0);
return result;
}
Here the recursion occurs (this also is valid for the other classes Fach, Lehrer and Tag) because every class has a bidirectional relationship to StundenplanEintrag.java. So the recursion happens like this: StundenplanEintrag.java:hashCode -> Klasse.java:hashCode -> StundenplanEintrag.java:hashCode ...
. The only thing I found about this problem was this stackoverflow post: Always get infinite recursion when saving OneToMany relation (already used @JsonBackReference and @JsonManagedReference)
(And the other once are for infinite recursion in JSON responses, which is managable by annotations). Since I am implementing the methods on my own I can't use a annoation to do that for me. And simply excluding EVERYTHING that makes a recursion possible I also tried, which works and the test passes:
Still, my hashCode()
methods now look like this and I can't use any value that is in any relationship:
@Override
public int hashCode() {
int prime = 31;
int result = 1;
result = prime * result + Id;
result = prime * result + ((name == null) ? 0 : name.hashCode());
// result = prime * result + (schueler != null && !schueler.isEmpty() ? schueler.hashCode() : 0);
// result = prime * result + (stundenplanEintrag != null && !stundenplanEintrag.isEmpty() ? stundenplanEintrag.hashCode() : 0);
// result = prime * result + (vertretungsplanEintrag != null && !vertretungsplanEintrag.isEmpty() ? vertretungsplanEintrag.hashCode() : 0);
return result;
}
But I really want unique hashCodes for which I want to use every attribute and not exclude most of them. Also, this applies to the toString()
method, and if I want to print info I want to print info, I can't just exclude everything besides to integers, or atleast that wouldn't be very useful info. I know the Id basically is unique, but I just want to know if there maybe is a cleaner solution for this instead of avoiding the problem through just deleting the code?