You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@openjpa.apache.org by "M. Walter" <ma...@sbb.ch> on 2011/08/10 14:26:41 UTC
Best practice: Overriding equals() in entities?
We experienced some problems implementing our own equals() methods. So we
accidentally forgot to compare a relationship field in an entity and got
some nasty OpenJPA errors like that:
/org.apache.openjpa.persistence.ArgumentException: Encountered new object in
persistent field "MyEntity.myField" during attach. However, this field does
not allow cascade attach. Set the cascade attribute for this field to
CascadeType.MERGE or CascadeType.ALL (JPA annotations) or "merge" or "all"
(JPA orm.xml). You cannot attach a reference to a new object without
cascading./
We then deleted all equals() methods in our entities and DTOs and the error
was gone. Well, we could have fixed the method instead. ;-) But now we
wonder about the need of equals(). Apparently OpenJPA does not need equals()
to check for new or changed entities.
So does it have any advantages to override equals() in JPA entities? Would
you recommend overriding equals() or leave it up to OpenJPA's internal
checks? Are there any fundamental reasons to use equals()? What are your
experiences and best practices?
Thanks a lot for your input!
--
View this message in context: http://openjpa.208410.n2.nabble.com/Best-practice-Overriding-equals-in-entities-tp6672154p6672154.html
Sent from the OpenJPA Users mailing list archive at Nabble.com.
Re: Best practice: Overriding equals() in entities?
Posted by Matthew Adams <ma...@matthewadams.me>.
+1.
Since Java has no interface "Identifiable" with method "boolean
identifies(Object that)" to distinguish it from "boolean equals(Object
that)" (which I think should be on an interface called "Equatable"), and
none of the collections/maps that leverage equality can be told to use
identity instead of equality when testing for membership, you're kind of
stuck with forcing the semantics of equals(..) to mean "identifies", and
further, "persistently identifies", when dealing with persistent objects.**
I'd love for Java to fix that, but it's pretty fundamental, and many (who
don't use transparent persistence) would say that it's not broken.
-matthew
**: Further, I've gone so far as to define interfaces like the following
(off of the top of my head, since I'm pressed for time & can't dig to find
them):
// Interface for the notion of "natural identity",
// like some business value(s) that are unique & constant during a
transaction.
// For example, Person.taxId, etc.
public interface TransientlyIdentifiable<T> {
T getId(); // think transient identifier
boolean identifiesTransiently(TransientlyIdentifiable<? extends T> that);
int hashCodeTransient();
}
public interface PersistentlyIdentifiable<T>
extends TransientlyIdentifiable<U> {
T getPersistentId(); // returns key
boolean identifiesPersistently(PersistentlyIdentifiable<? extends U>
that); // uses key
boolean identifiesTransiently(PersistentlyIdentifiable<? extends U> that);
// uses "natural key"
int hashCodePersistent(); // uses key
}
// This would allow objects to be or not be able to be compared for
equality.
// Objects should get to choose whether or not they can be "equivalent" to
another object.
public interface Equatable {
boolean equals(Equatable that); // like Object#equals(Object)
int hashCodeEquatable(); // like Object#hashCode()
}
On Wed, Aug 10, 2011 at 12:18 PM, Pinaki Poddar <pp...@apache.org> wrote:
> > What are your experiences and best practices?
>
> semantics of equals(Object other) should stay close to equate the fields
> that constitute persistent identity of a type.
>
> // Two distinct contexts
> EntityManager em1 = ...;
> EntityManager em2 = ...;
>
> // One user-visible persistent identity
> Object pid = ...;
>
> // Access a persistent instance in two separate contexts
> X pc1 = em1.find(X.class, pid);
> X pc2 = em2.find(X.class, pid);
>
> // Access their persistent identity in distinct contexts
> Object id1 = em1.getObjectId(pc1);
> Object id2 = em2.getObjectId(pc2);
>
> // These assertions are true by design
> assertNotSame(pc1, pc2); // same persistent data gets realized as distinct
> objects in distinct context
> assertEquals(id1, id2); // their persistent identity equals by value
>
> // The user-written equals() *should* honor the following
> assertEquals(pc1, pc2);
>
>
>
>
>
>
> -----
> Pinaki Poddar
> Chair, Apache OpenJPA Project
> --
> View this message in context:
> http://openjpa.208410.n2.nabble.com/Best-practice-Overriding-equals-in-entities-tp6672154p6673341.html
> Sent from the OpenJPA Users mailing list archive at Nabble.com.
>
--
@matthewadams12
mailto:matthew@matthewadams.me
skype:matthewadams12
yahoo:matthewadams
aol:matthewadams12
google-talk:matthewadams12@gmail.com
msn:matthew@matthewadams.me
http://matthewadams.me
http://www.linkedin.com/in/matthewadams
Re: Best practice: Overriding equals() in entities?
Posted by Pinaki Poddar <pp...@apache.org>.
> What are your experiences and best practices?
semantics of equals(Object other) should stay close to equate the fields
that constitute persistent identity of a type.
// Two distinct contexts
EntityManager em1 = ...;
EntityManager em2 = ...;
// One user-visible persistent identity
Object pid = ...;
// Access a persistent instance in two separate contexts
X pc1 = em1.find(X.class, pid);
X pc2 = em2.find(X.class, pid);
// Access their persistent identity in distinct contexts
Object id1 = em1.getObjectId(pc1);
Object id2 = em2.getObjectId(pc2);
// These assertions are true by design
assertNotSame(pc1, pc2); // same persistent data gets realized as distinct
objects in distinct context
assertEquals(id1, id2); // their persistent identity equals by value
// The user-written equals() *should* honor the following
assertEquals(pc1, pc2);
-----
Pinaki Poddar
Chair, Apache OpenJPA Project
--
View this message in context: http://openjpa.208410.n2.nabble.com/Best-practice-Overriding-equals-in-entities-tp6672154p6673341.html
Sent from the OpenJPA Users mailing list archive at Nabble.com.