I have had a chat with Gail on $subject and promised to give my feedback. First of, I would argue that the user is doing something relatively wrong on my weirdo scale. I am not massively bothered with whatever solution we end up choosing.
When the same state is present in both instances, you guys agreed to consider it a no-op which Ia gree offers the best user experience. About warn vs exception, I would prefer warn or even nothing (see below) but I can see the benefit of a pluggable strategy. Now the big questions are: 1. Should we take into account the first version of the entity and ignore / warn / throw an exception on the followings OR should we always override the state with the last version of the entity encountered (and warn or throw and exception optionally) 2. Should this rule be the same when we are discussing cascading from a single call / cascade tree to em.merge(x) And when it comes from two subsequent calls to merge em.merge(y1); em.merge(y2); Unsurprisingly the spec does not mention this case explicitly but the merge semantic indicates that the state of the entity provided is merged into the state of the persistence context. So my preference would be to last version wins which makes all situations similar. I understand that cascading of merge could lead to the merge of entities no longer associated with the entity that ends up in the database but I prefer the simplicity of the rule leading to odd behavior is corner cases than something complex to explain. If we end up supporting the following behavior y = em.merge(y1); //state if y1 copied in y y = em.merge(y2); //state of y2 ignored and y keeps y1 state I would be concerned it leads to a lot of misunderstanding and complains from the users. And to me it would be against the spec as I read it. Fundamentally merge is broken-ish and I tend to prefer the saveOrUpdate moder which clearly throw an exception in case of conflicts like this. But that's not the model that was chosen in JPA. Emmanuel On Tue 2014-04-08 2:50, Gail Badner wrote: > After fixing HHH-6848, Hibernate throws IllegalStateException when merging > entity 'x' if it has references to 2 detached entities 'y1' and 'y2' obtained > from different sessions, and y1 and y2 represent the same persistent entity. > In other words, y1 != y2. > > I've pushed some FailureExpected test cases to > org.hibernate.test.ops.MergeTest that illustrate this. [1] > > Before fixing HHH-6848, one of the representations would be merged and the > other would be ignored (probably overwritten). > > I'm looking into a fix that will restore this functionality as well as > provide logging for this situation. I'll discuss logging in a separate email. > > Merging multiple representations that have equivalent state would be > straightforward. Things are more complicated when the representations do not > have equivalent state. I'd like to discuss and get feedback before fixing > this. > > I am a little leery about allowing multiple representations that are not > equivalent to be merged because data could be lost. I would prefer to throw > an exception by default, and then provide a flag to override this behavior as > suggested in HHH-8570. I discussed briefly with Steve E., and he preferred to > address this concern by logging a warning. Opinions? > > In any case, here are 2 possible strategies: > > 1) The last one copied will "win". First, the state from one will be copied > onto a pre-existing managed entity or a new managed copy, then later when the > merge operation is cascaded to the other representation, a copy of its state > will overwrite the managed entity state. > > 2) The first representation detected will "win". The idea here is that y1 and > y2 are both representations of the same entity; only 1 can be merged. When > the first is detected, the merge operation is cascaded to its associations > with cascade=MERGE or cascade=AL, then its state will be copied onto a > pre-existing managed entity or a new managed copy. When a later > representation is detected, it's state is not copied and the merge operation > is not cascaded to its associations with cascade=MERGE or cascade=ALL. > > I think 2) fits in better With the way merge currently works. > > A problem with 1) is that we won't know when we are processing the last > representation until all cascade-merges are finished. By then, the session > may contain entities from cascading the merge operation from the earlier > representations. This could result in persisting transient entities or > updating entites that are only associated with earlier representations. > > With 2) we always know when we are processing the first representation and > can more easily skip cascading the merge operation for representations > detected later. > > Comments? > > Thanks, > Gail > > [1] > https://github.com/hibernate/hibernate-orm/blob/0118376f8efd9b35d8be815c892f3ac7f9b6048f/hibernate-core/src/test/java/org/hibernate/test/ops/MergeTest.java#L829 > _______________________________________________ > hibernate-dev mailing list > hibernate-dev@lists.jboss.org > https://lists.jboss.org/mailman/listinfo/hibernate-dev _______________________________________________ hibernate-dev mailing list hibernate-dev@lists.jboss.org https://lists.jboss.org/mailman/listinfo/hibernate-dev