to trigger the association management, at some point there has to be a change in the *ToMany field, even if it's with the same collection. The collection itself is not tracked for changes.
So, instead of:
It's required a call to the setter:
UPDATE: Nevermind. This actually works well, the problem I faced was due to a lack of session flush. It would be cool if the session flush isn't needed here, but it is a good alternative.
This is either same or similar/related to the issue documented at:
What appears to be happening is that the bytecode enhancement will only update the inverse side if that inverse side is already loaded - i.e. it will not lazily load it OR somehow store the action to be done when loaded/updated. This, sort of, invalidates the main advantage of using the bi-directional association management - not having to be concerned with whether there even is another side, what it might be and writing that update code in a way that avoids infinite call loops. It also hides the issue. At this point I can see the following possibilities (not all mutually exclusive - i.e. possibly configurable):
Automatically (implicitly) lazily load the inverse side if it isn't already loaded.
Store the update in alternate structures (dirty tracking) so that it can be applied automatically in the transaction and/or if/when the inverse association is actually accessed.
Fail fast with an exception, do not hide the issue of not being able to do what is, essentially, expected - that the inverse side is updated. This will help discover these issues earlier in the development process.
Give an option / hook to handle this situation.
Not desirable in the long term but a must in the short term - document the issue in "bi-directional association management" bytecode enhancement documentation.
I realize that the issue here has an accepted stackoverflow answer related to the (lack of) unit test bytecode enhancement, but in here I found nothing closer... and this is still "OPEN". What I am reporting may be a separate issue and should be moved out.
Additionally, considerations may need to be made as to what to do when mixing transient and persistent state entities, such as setting an association of a (new) transient entity to point to a (loaded) persistent one and expecting that the persistent's inverse association is updated, when should this happen (when save()/saveOrUpdate()/persist() is called and on which entity - ideally only the one being explicitly modified), etc.