-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
Enhance direct access to protected, package-private, private and superclass entity fields in Hibernate ORM #32876
Conversation
Thanks for your pull request! The title of your pull request does not follow our editorial rules. Could you have a look?
|
Very interesting, thanks. There's one sentence in your description giving me pause:
Arguably if the user is overriding a get/set, they might mean it. What if they didn't want the parent method to be called? That's the contract when one doesn't call "super.get/set" - it's hard to say if the omission in a trivial method implementation is intentional or just because there is no need. |
So first, it might not have existed in the first place, since we generate getters/setters. Sometimes users apparently define the field in a superclass and the getter/setter in a subclass; don't ask me why. If the getter/setter in superclasses are generated then the call to super is safe. If the getter/setter in superclass is not generated... well, as you said, hard to say what the user meant. I suppose we could avoid calling super in that case, but that would require more pre-processing/metadata. And I'm pretty sure we'll get bug report from users who simply throught we'd replace field access anyway. Alternatively, maybe we should just stop generating/calling I wouldn't know what to do about MongoDB, though. I'm not sure why we replace public field access with getter/setter calls there anyway, since to the best of my knowledge it doesn't do change tracking or lazy initialization... |
To simply call the internal ORM accessors was my thought as well. Could you elaborate on the "problems" with transient? I'm not sure what the problem would be. |
Well if the field is marked as transient in XML mapping, I wouldn't expect the ORM accessor to work correctly (since, well, it's not a field ORM should care about). Maybe it does work though... EDIT: Though I suppose we could process XML mapping during the build to extract that information. |
ah, got it know. I misunderstood by "XML mapping" that the object was also being mapped with e.g. JAXB annotations. Yes right I wouldn't know if it creates any problem to mark a field as dirty even when the field is transient/ignored. (I don't think it hurts but I'm not sure); either way that's something we could do something about and I feel this is a more robust approach - that said I don't mean to say you should definitely do that now: up to you. |
This comment has been minimized.
This comment has been minimized.
I'll see what can be done and will investigate the test failures. Thanks for the feedback! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, when the tests will pass ;)
Yep I'm on it, that's what #33832 was about :) |
I think I'll have to fix superclass field access directly in Hibernate ORM in the end. I will get a closer look tomorrow. |
I rebased on #33844 because that's necessary for tests to pass. Converting to a draft PR until #33844 gets merged. I also changed the handling of field access in subclasses as per Sanne's suggestion. We now replace such access with a call to I suppose we could replace field access with |
This comment has been minimized.
This comment has been minimized.
Looks like the current approach causes problems when there are already getters, but with a slightly different return type (e.g. primitive vs. boxed):
That's arguably something we should solve independently from this PR (because it could affect applications that declare public field + getters/setters), but for the moment I chose to sidestep the problem: I updated the PR again to use I updated the PR description and force-pushed. |
c072f38
to
edf4cce
Compare
This comment has been minimized.
This comment has been minimized.
This does not change its behavior at all.
I addressed the bugs detected by the test suite. Let's see if everything is fine now. |
This comment has been minimized.
This comment has been minimized.
…te_{read/write}_* methods when enhancing for Hibernate ORM
…te_{read/write}_* methods when enhancing for Hibernate ORM Instead of leaving the field access in place.
I.e. direct access to superclass fields and non-public fields
…ters, listeners) 1. Because it's not necessary 2. Because it won't work since those fields don't get corresponding $_hibernate_{read,write}_*() methods generated by Hibernate ORM's enhancements.
✔️ The latest workflow run for the pull request has completed successfully. It should be safe to merge provided you have a look at the other checks in the summary. |
Fixes #32735
In essence, this changes two things, but for for Hibernate ORM entities only:
We now also replace access to protected, package-private and private fields with calls to
$$_hibernate_{read/write}_*
(though obviously not in the constructor, since that would fail, or the getter/setter, since Hibernate ORM itself will do that).We now replace such access with a call to
$$_hibernate_{read/write}_*
, so that we call Hibernate ORM's enhancements.I didn't apply these to Panache MongoDB, because there's simply no equivalent to
$$_hibernate_{read/write}_*
for MongoDB, and callingget*()
/set*()
(which was my initial approach) could cause other problems.I will need some serious review from someone familiar with bytecode enhancement and Hibernate ORM (@Sanne, pretty please!), because this is a rather fundamental change with potential for breaking stuff. I worry in particular about:
Such applications, until now, didn't even get most of the field access enhancement code executed, because they didn't need to.
But now that we enhance protected/private field access, we do need to scan those applications, be it just to conclude that they only access these fields in the corresponding getters and don't need any enhancement in the end. So we may discover performance issues or simply bugs in those applications (even if they don't need field access enhancement).
in particular if we don't correctly detect fields marked as transient using XML mapping: we will then replace field access with calls to
$$_hibernate_{read/write}_*
methods that may not exist.That could be considered a pre-existing bug though, since such applications would already behave badly if they have public fields marked as transient using XML mapping (we'd generate an unnecessary getter/setter pair).
Also, I suspect Hibernate ORM also doesn't detect those XML-mapped transient fields correctly, so it may generate those
$$_hibernate_{read/write}_*
methods anyway.For the reasons mentioned above, I really don't want to backport this patch.