-
Notifications
You must be signed in to change notification settings - Fork 75
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JPA: how to handle Id fields #225
Comments
I wouldn't check for a magic number, as that may actually vary per implementation, and some |
Some interesting insights from @vladmihalcea in this blog post: as far as I understand the best approach would be to use the business key, a unique, non-null and non-updatable column. In Hibernate (not JPA) it is possible to map such business key(s) using @NaturalId. |
|
You can also use the entity identifier for equals, but you need to make sure you use a constant hashCode, as explained in this article. |
I'm no expert on this, but I think the correct answer may be a 2 or 3 modal...
I'm not sure that asking if "surrogate or natural" is the right for all hibernate entities, because I think the answer is it depends. |
Perhaps a policy of "natural then surrogate" would be a less surprising behavior? In that regard, if a class contains both |
Having read your responses and also both @vladmihalcea's blog posts (they're very enlightening, thanks for sharing!), I feel that EqualsVerifier should indeed default to using a business/natural key. I don't mind supporting If no There would be a If I'm feeling particularly motivated, I could also add a check that if any field used in equals has a If all this works well, I could investigate whether What do you guys think? |
I would be pretty happy even without |
https://stackoverflow.com/q/5031614/206466 found this while trying to find whether the Another quandry I have, which is more of UGH!!! lol |
@dfa1 Well, I still have to actually build all of it of course, that might take a little while 😉. I take it you agree with the proposal? @xenoterracide I agree that Regarding your |
yes, I do! |
by default yes, but you can change what the fetch is on query. |
Yeah, but then EqualsVerifier fails. (Maybe it should only fail if the field is actually used in equals). |
let me rephrase, you can change fetches at runtime in you jpql/criteria queries. The definition on the annotation is simply the default for the class. |
Ohhh, that explains a lot. Yeah, that sucks. Can't do a lot about it, either. |
another consideration is for jpa entities should we force property access through accessors? that way when calling equals you're for sure interacting with the proxy? this is that optimization I found for id
so for example if one has a
without incurring a fetch... but if I called any other method on this class it will cause the collection to be fetched.
yeah just wanted to make sure we were on the same page |
might be an idea to have equalsverifier enforce... "simple properties only", in other words you can depend on |
Wait, I don't understand what you're saying here. You're asking whether EqualsVerifier should enforce that property access goes through an accessor method. That's a good question, I'm not sure if it should (and I'm also not sure if it can). I don't see how the optimization for Remember, I don't know the first thing about JPA, I've never used it. You have to take me by the hand here. |
Sorry, they're both different and the same. By default Hibernate (other providers do other things) creates proxies for your objects on load/save from the database, this is to support that lazy loading. In order to trigger a lazy load you have to call a method on the proxy (gotcha's here with detached proxies...). So if you don't put that "property access" on id, calling getId will always cause the proxy to fetch if it hasn't already. To test this, you'll have to create a proxy, and ensure that equals works on simple properties ( I think for an aggregate class like Bar, you have to hand equalsverifier an instance anyways?)
on bar can be lazy, and will trigger a lazyload on getName()
safe property access, and only checks ids
|
^ I think I'm done writing that for now... though I may update the classes there for sake of example |
basically I'm thinking that we should ensure that an objects equals matches a proxy of itself with lazy loaded objects uninstantiated, or maybe only instantiated via id (I'm not sure on that if we're going NATURAL by default though). |
Still not sure I understand 100% what you're asking.
|
sorry for the late reply
also, still kind of in favor of a modal system where you have to select the mode(s) before testing. |
@dfa1, what do you think? |
I see all the points raised by @xenoterracide: they are real problems but usually I address them in other tests specific to Hibernate/JPA (i.e. to enforce certain custom policies about caching, cascading, etc). I would be very happy even with a simple, explicit support for annotations:
|
So if I understand you correctly, these points are all nice-to-haves? I'll just start with implementing my initial proposal and see if I can pick up any of these points along the way. If not, they could always be added later. Personally, I'm not really in favour of a modal approach, or a system where the support for annotations is made explicit. EqualsVerifier has always been very opinionated. For instance, if it sees a Thanks to both of your input, I have now been able to form that opinion about Hibernate id's for EqualsVerifier. And of course it will always be possible to disagree and make EqualsVerifier behave differently, by adding a flag here or suppressing a warning there. |
Not really, I see them as general problem with hibernate/JPA but I don't expect to detect this kind of issues by using this library.
Wonderful, this is even better :-) |
I think that's fine, I've just been trying to make sure I cover as many parts of the problem with jpa/hibernate as possible since you're starting from 0 ;) just so you have as complete of a context as we can give. |
Thanks to you both! |
I've just released a first version of this with EqualsVerifier 3.1. It supports the The other things we discussed, such as attempting to check for I've also not changed anything about the behaviour of Please let me know what you think of this! Merry christmas! |
This is a question that comes up from time to time in the issue tracker and the mailinglist (for example #89 and #221). Since I don't have much experience with JPA / Hibernate, I'd like this issue to be a place where people more knowledgeable than me can help me find the right behaviour for EqualsVerifier.
JPA has the
@Id
annotation that signals that the field is a primary key in the database. It feels like a missed opportunity that EqualsVerifier doesn't do anything with that. But what should it do?@Id
annotation is present, should EqualsVerifier then check that only this id field is used inequals
, enforcing a primary-key basedequals
implementation?equals
implementation?null
, and check that the content is used when the entity is new, basically combining the two previous options? Currently, there's Warning.IDENTICAL_COPY_FOR_VERSIONED_ENTITY that does more or less the same thing, but it might be a bit confusing the way it's implemented now.Do id fields always have the
@Id
annotation in the first place? I don't know.Are there other relevant annotations that EqualsVerifier should take into account?
If you see this issue and have an opinion on the matter, please write it down in a comment below! If you know a link to a good blog post on the subject, please also share that below.
The text was updated successfully, but these errors were encountered: