Czy powinienem pisać metody equals () w encjach JPA?
Chcę sprawdzić, czy encja jest członkiem kolekcji (@OneToMany
lub @ManyToMany
) innej encji:
if (entity2.getEntities1().contains(entity1)) { }
6 answers
Niekoniecznie. Istnieją trzy opcje:
-
Nie nadpisuj-w ten sposób będziesz pracować z instancjami. Jest to w porządku w przypadkach, gdy pracujesz z kolekcjami z tylko encjami, które są dołączone do sesji (a tym samym gwarantowane, że będą tą samą instancją). Jest to (dla mnie) preferowany sposób w wielu przypadkach, ponieważ wymaga mniej kodu i mniej uwagi przy nadpisywaniu
Zastąp
hashCode()
iequals()
kluczem biznesowym. To może być podzbiór właściwości identyfikujących podmiot. Na przykład dlaUser
dobrym kluczem biznesowym może byćusername
lubemail
. Jest to uważane za dobrą praktykę.-
Nadpisuje
hashCode()
iequals()
używając tylko pola ID. W niektórych przypadkach jest to w porządku, szczególnie jeśli masz ręcznie przypisany identyfikator (np. UUID). Jest również w porządku, jeśli Twoja jednostka nigdy nie wejdzie do kolekcji. Ale w przypadku encji przejściowych (bez identyfikatora), które trafiają do kolekcji, powoduje to problemy, więc ostrożnie z tą opcją. Jak zauważył seanizer-należy tego unikać. Ogólnie rzecz biorąc, zawsze, chyba że jesteś naprawdę świadomy tego, co robisz (i być może dokumentujesz to)
Więcej szczegółów można znaleźć w tym artykule. Zauważ również, że equals()
i hashCode()
są powiązane i powinny być zaimplementowane z dokładnie tymi samymi polami.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-06 15:58:13
Tak, powinieneś zdefiniować odpowiednie metody equals()
i hashcode()
, ale nigdy nie pozwól, aby id było częścią żadnej z nich. (Zobacz moją ostatnią odpowiedź w podobnym pytaniu)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:33:26
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-12 18:10:27
Zazwyczaj pozwalamy IDE generować hashCode()
i equals()
dla nas. Bądź ostrożny. Podczas generowania tych metod dla encji JPA. Niektóre wersje equals()
sprawdzania tożsamości klasy
// ... inside equals() - wrong approach for Entities (cause of generate proxies)
if (o == null || this.getClass() != o.getClass()) {
return false;
}
// ...
Spowoduje to złamanie Twoich kolekcji z niektórymi bibliotekami JPA, ponieważ biblioteki te tworzą proxy do Twoich encji( podklas), jak na przykład MyGreatEntity_$$_javassist_7
w Hibernate.
In encje zawsze zezwalają na podklasy w equals()
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-25 07:34:49
Tak, powinieneś!
Jeśli nie nadpisujesz domyślnego Java.lang.Object
equals
i hashCode
realizacja:
@Entity(name = "Book")
public class Book implements Identifiable<Long> {
@Id
@GeneratedValue
private Long id;
private String title;
//Getters and setters omitted for brevity
}
Operacja merge
zwróci inną instancję obiektu i umowa równości zostanie zerwana Jak wyjaśniono w tym poście .
Najlepszym sposobem jest użycie klucza biznesowego, takiego jak:
@Entity
public class Book implements Identifiable<Long> {
@Id
@GeneratedValue
private Long id;
private String title;
@NaturalId
private String isbn;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Book)) return false;
Book book = (Book) o;
return Objects.equals(getIsbn(), book.getIsbn());
}
@Override
public int hashCode() {
return Objects.hash(getIsbn());
}
//Getters and setters omitted for brevity
}
Możesz również użyć identyfikatora dla równości, ale pamiętaj, że implementacja hashCode powinna zawsze zwracać tę samą wartość, co wyjaśniono w tym samym post, o którym już wspomniałem:
@Entity
public class Book implements Identifiable<Long> {
@Id
@GeneratedValue
private Long id;
private String title;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Book)) return false;
Book book = (Book) o;
return Objects.equals(getId(), book.getId());
}
@Override
public int hashCode() {
return 31;
}
//Getters and setters omitted for brevity
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-06 10:31:50
To jedyny sposób. Możesz spróbować Pojomatic library, która wykonuje ciężką pracę za Ciebie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-08 14:11:13