OpenJPA
  1. OpenJPA
  2. OPENJPA-2405

EntityManager.merge does not work for entity that is managed by another EntityManager

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 2.2.3
    • Fix Version/s: 2.3.0
    • Component/s: kernel
    • Labels:
      None

      Description

      EntityManager.merge does not work for entity that is managed by another EntityManager. Instead of updating that entity OpenJPA tries to persist the entity a second time

        Activity

        Hide
        Arne Limburg added a comment -

        Added test that reproduces the problem

        Show
        Arne Limburg added a comment - Added test that reproduces the problem
        Hide
        Albert Lee added a comment - - edited

        Per Spec:
        ====================
        3.2.7.1 Merging Detached Entity State
        The merge operation allows for the propagation of state from detached entities onto persistent entities
        managed by the entity manager.
        The semantics of the merge operation applied to an entity X are as follows:
        ........
        • If X is a managed entity, it is ignored by the merge operation, however, the merge operation is
        cascaded to entities referenced by relationships from X if these relationships have been annotated
        with the cascade element value cascade=MERGE or cascade=ALL annotation.
        ====================

        merge() is for "detached" entity only. If it is "managed", it is IGNORED.....

        Show
        Albert Lee added a comment - - edited Per Spec: ==================== 3.2.7.1 Merging Detached Entity State The merge operation allows for the propagation of state from detached entities onto persistent entities managed by the entity manager. The semantics of the merge operation applied to an entity X are as follows: ........ • If X is a managed entity, it is ignored by the merge operation, however, the merge operation is cascaded to entities referenced by relationships from X if these relationships have been annotated with the cascade element value cascade=MERGE or cascade=ALL annotation. ==================== merge() is for "detached" entity only. If it is "managed", it is IGNORED.....
        Hide
        Arne Limburg added a comment -

        1. So you agree with me that it is a BUG that OpenJPA tries to INSERT the entity and throws an exception due to the duplicate key?

        2. Yes, I have read that chapter of the spec, too. And I come to the conclusion, that the only way to interpret it, is that managed entities of the SAME persistence context are meant.
        Your way of reading the spec simply does not work. Think of the following situation:
        a. Entity A is loaded by EntityManager X. Entity A has a Cascade.ALL relation to Entity B.
        b. Entity B is newly created and assigned to A
        c. Entity A is merged to EntityManager Y.
        Now Entity B would be managed by EntityManager Y due to the cascading behavior you cited. In addition Entity B would be managed by EntityManager X due to 3.2.4

        Spec 3.24
        =====================
        The semantics of the flush operation, applied to an entity X are as follows:

        • If X is a managed entity, it is synchronized to the database.
        • For all entities Y referenced by a relationship from X, if the relationship to Y has been annotated with the cascade element value cascade=PERSIST or cascade=ALL, the persist operation is applied to Y.
          =====================
          How do you think OpenJPA should behave in such situation? Should Entity B be managed by two persistence contexts?

        Btw. Any other persistence provider returns a managed copy of Entity A in such situation, no matter if A is managed by another persistence context or detached. And this is the expected behavior, I guess.

        Show
        Arne Limburg added a comment - 1. So you agree with me that it is a BUG that OpenJPA tries to INSERT the entity and throws an exception due to the duplicate key? 2. Yes, I have read that chapter of the spec, too. And I come to the conclusion, that the only way to interpret it, is that managed entities of the SAME persistence context are meant. Your way of reading the spec simply does not work. Think of the following situation: a. Entity A is loaded by EntityManager X. Entity A has a Cascade.ALL relation to Entity B. b. Entity B is newly created and assigned to A c. Entity A is merged to EntityManager Y. Now Entity B would be managed by EntityManager Y due to the cascading behavior you cited. In addition Entity B would be managed by EntityManager X due to 3.2.4 Spec 3.24 ===================== The semantics of the flush operation, applied to an entity X are as follows: If X is a managed entity, it is synchronized to the database. For all entities Y referenced by a relationship from X, if the relationship to Y has been annotated with the cascade element value cascade=PERSIST or cascade=ALL, the persist operation is applied to Y. ===================== How do you think OpenJPA should behave in such situation? Should Entity B be managed by two persistence contexts? Btw. Any other persistence provider returns a managed copy of Entity A in such situation, no matter if A is managed by another persistence context or detached. And this is the expected behavior, I guess.
        Hide
        Albert Lee added a comment -

        I am just pointing out that merge() is meant for merging DETACHED entity into a persistence context. If an entity is managed by the SAME persistence context, there is nothing to merge since the state of X is already maintained, hence the merge operation is ignored. However, the child relationship is still processed if proper cascade is specified.

        The spec also spelled out the following;
        =================================
        3.2.8 Managed Instances
        It is the responsibility of the application to insure that an instance is managed in only a single persistence
        context. The behavior is undefined if the same Java instance is made managed in more than one
        persistence context.
        =================================

        In the original test case, A (managed by em, not detached) is merged to em2 and there is no managed A in em2. Since A is marked managed and not managed in em2, OpenJPA creates a new managed instance in em2 and eventually "INSERT" to the database. I am not saying this is the right or wrong behavior but this use case is undefined.

        If you wants to merge changed content in A to a different persistence context, you may have to do:

        • em.find(A);
        • detach A from em2
        • make changes to A
        • em2.find(A);
        • em2.merge(A);
        • commit/flush em2
        Show
        Albert Lee added a comment - I am just pointing out that merge() is meant for merging DETACHED entity into a persistence context. If an entity is managed by the SAME persistence context, there is nothing to merge since the state of X is already maintained, hence the merge operation is ignored. However, the child relationship is still processed if proper cascade is specified. The spec also spelled out the following; ================================= 3.2.8 Managed Instances It is the responsibility of the application to insure that an instance is managed in only a single persistence context. The behavior is undefined if the same Java instance is made managed in more than one persistence context. ================================= In the original test case, A (managed by em, not detached) is merged to em2 and there is no managed A in em2. Since A is marked managed and not managed in em2, OpenJPA creates a new managed instance in em2 and eventually "INSERT" to the database. I am not saying this is the right or wrong behavior but this use case is undefined. If you wants to merge changed content in A to a different persistence context, you may have to do: em.find(A); detach A from em2 make changes to A em2.find(A); em2.merge(A); commit/flush em2
        Hide
        Arne Limburg added a comment -

        Yes, I know how I could make it work in the test case.
        Unfortunately this is not true for real life applications.
        The problem occured in a web-app with concurrent requests.
        I load the entity within one request and the EntityManager is closed after that request.
        In the second request I merge that entity to have an attached instance again.
        Unfortunately from time to time the second request comes in when the first is not completely finished and the first EntityManager is still open. Then the problem occures.

        So, until this behavior of OpenJPA is not fixed, I cannot have concurrent requests with JPA?

        Btw. I am willing to help fixing this issue.

        Is it common sense that the best behavior in the described case would be that OpenJPA simply copies the state of the entity?

        Show
        Arne Limburg added a comment - Yes, I know how I could make it work in the test case. Unfortunately this is not true for real life applications. The problem occured in a web-app with concurrent requests. I load the entity within one request and the EntityManager is closed after that request. In the second request I merge that entity to have an attached instance again. Unfortunately from time to time the second request comes in when the first is not completely finished and the first EntityManager is still open. Then the problem occures. So, until this behavior of OpenJPA is not fixed, I cannot have concurrent requests with JPA? Btw. I am willing to help fixing this issue. Is it common sense that the best behavior in the described case would be that OpenJPA simply copies the state of the entity?
        Hide
        Mark Struberg added a comment -

        Well, imo it's an OpenJPA bug in any case. If we simply ignore managed entities in em.merge() than we must not insert the children into the database twice neither.

        Regarding 3.2.8: In this paragraph 'instance' clearly does not mean 'entity identity' but 'java identity' as indicated by the sentence: "The behavior is undefined if the same Java instance is made managed in more than one persistence context."

        In any case I'm not sure if 'fixing' this would help you, Arne.

        I guess it's all about the entitymanager-per-request pattern and a premature redirect().
        In this case it might happen that finishing the first request (the one with the redirect) takes longer to end than the new request to hit the server (in a parallel thread now).
        In this case the flush() on the first request might change your records in the db and also update the @Version in those Entities. So even if you would get the entity merged into another EM in the 2nd request it would contain the old @Version and you will blow up at the end of the 2nd request with an OptimisticLockException. Doesn't sound good neither, right?

        There are now 2 ways to solve this issue in your application (even without changing OpenJPA)

        1.) Use a Servlet Filter to synchronize on your Session for those requests. Be careful as this might cause unnecessary locks ...

        2.) explicitly invoke em.flush() and em.close() before you do the redirect. And hope that your @Transactional Interceptor can deal with it For JSF apps we might be able to register a hook for the redirect in the FacesContext. Need to check...

        This might btw also work a bit different depending if you use synchronized or unsynchronized EM (see JTA-2.1 and em.joinTransaction()).

        Summary: multi-page 'wizard' style pages without DTOs suck at this time. We need this new pattern we've talked about last week where we use em.joinTransaction() to explicitly store the entity in the 'save' action on the last page - without having the em.merge() operations automagically prematurely store all changes into the database on the intermediate pages. Still thinking about how this can be done best with OpenJPA

        Show
        Mark Struberg added a comment - Well, imo it's an OpenJPA bug in any case. If we simply ignore managed entities in em.merge() than we must not insert the children into the database twice neither. Regarding 3.2.8: In this paragraph 'instance' clearly does not mean 'entity identity' but 'java identity' as indicated by the sentence: "The behavior is undefined if the same Java instance is made managed in more than one persistence context." In any case I'm not sure if 'fixing' this would help you, Arne. I guess it's all about the entitymanager-per-request pattern and a premature redirect(). In this case it might happen that finishing the first request (the one with the redirect) takes longer to end than the new request to hit the server (in a parallel thread now). In this case the flush() on the first request might change your records in the db and also update the @Version in those Entities. So even if you would get the entity merged into another EM in the 2nd request it would contain the old @Version and you will blow up at the end of the 2nd request with an OptimisticLockException. Doesn't sound good neither, right? There are now 2 ways to solve this issue in your application (even without changing OpenJPA) 1.) Use a Servlet Filter to synchronize on your Session for those requests. Be careful as this might cause unnecessary locks ... 2.) explicitly invoke em.flush() and em.close() before you do the redirect. And hope that your @Transactional Interceptor can deal with it For JSF apps we might be able to register a hook for the redirect in the FacesContext. Need to check... This might btw also work a bit different depending if you use synchronized or unsynchronized EM (see JTA-2.1 and em.joinTransaction()). Summary: multi-page 'wizard' style pages without DTOs suck at this time. We need this new pattern we've talked about last week where we use em.joinTransaction() to explicitly store the entity in the 'save' action on the last page - without having the em.merge() operations automagically prematurely store all changes into the database on the intermediate pages. Still thinking about how this can be done best with OpenJPA
        Hide
        Jody Grassel added a comment -

        Just reviewing this JIRA and wanted to post my own thoughts. First, some clips from the JPA Specification that I think are relevant:

        3.2 Entity Instance’s Life Cycle
        This section describes the EntityManager operations for managing an entity instance’s lifecycle. An entity instance can be characterized as being new, managed, detached, or removed.
        • • • •
        A new entity instance has no persistent identity, and is not yet associated with a persistence context.
        A managed entity instance is an instance with a persistent identity that is currently associated with a persistence context.
        A detached entity instance is an instance with a persistent identity that is not (or no longer) associated with a persistence context.
        A removed entity instance is an instance with a persistent identity, associated with a persistence context, that will be removed from the database upon transaction commit.

        – What I take from this is that an Entity Class that has been freshly created by its constructor (ie, not created by em.find() or a JPA query) and has never, ever been touched by an em.persist() or em.merge() operation is a "new entity". Such an object will not have any StateManager (DetachedStateManager or otherwise, it is simply null) associated with its internal state (internal state being the hidden variables added by enhancement.)

        – A "managed entity" is an Entity Class instance that has a link to a live StateManager in its internal state – and there's caveats to that. A StateManager is associated to one and only one Persistence Context (ie, EntityManager instance) - to those and only those Persistence Contexts is the entity a "managed entity". A new entity becomes a managed entity when em.persist() or em.merge() is called on it. (Managed entities are also provided by find/query operations (though it would return a detached entity if it's a CMTS entitymanager invocation outside of a transaction.))

        – To any other Persistence Context, because it is not "new" (because it has a StateManager object associated with it) and has a non DetachedStateManager that is associated with another Persistence Context, it should be interpreted as a "detached entity" (even if the StateManager associated with the Entity Object instance's internal state is not a DetachedStateManager.) So calling em.merge(entityWithSomeOtherPCsStateManager) should be treated as a detached entity, and return a new Entity Object instance. Which could create "interesting problems" if the original entity doesn't have a committed row on the database yet (because the two different PCs will have two different db connections, and a merge operation will trigger a fetch operation from the database/cache.) Remember the JPA spec requires Read-Committed to be the minimum isolation level.

        Show
        Jody Grassel added a comment - Just reviewing this JIRA and wanted to post my own thoughts. First, some clips from the JPA Specification that I think are relevant: 3.2 Entity Instance’s Life Cycle This section describes the EntityManager operations for managing an entity instance’s lifecycle. An entity instance can be characterized as being new, managed, detached, or removed. • • • • A new entity instance has no persistent identity, and is not yet associated with a persistence context. A managed entity instance is an instance with a persistent identity that is currently associated with a persistence context. A detached entity instance is an instance with a persistent identity that is not (or no longer) associated with a persistence context. A removed entity instance is an instance with a persistent identity, associated with a persistence context, that will be removed from the database upon transaction commit. – What I take from this is that an Entity Class that has been freshly created by its constructor (ie, not created by em.find() or a JPA query) and has never, ever been touched by an em.persist() or em.merge() operation is a "new entity". Such an object will not have any StateManager (DetachedStateManager or otherwise, it is simply null) associated with its internal state (internal state being the hidden variables added by enhancement.) – A "managed entity" is an Entity Class instance that has a link to a live StateManager in its internal state – and there's caveats to that. A StateManager is associated to one and only one Persistence Context (ie, EntityManager instance) - to those and only those Persistence Contexts is the entity a "managed entity". A new entity becomes a managed entity when em.persist() or em.merge() is called on it. (Managed entities are also provided by find/query operations (though it would return a detached entity if it's a CMTS entitymanager invocation outside of a transaction.)) – To any other Persistence Context, because it is not "new" (because it has a StateManager object associated with it) and has a non DetachedStateManager that is associated with another Persistence Context, it should be interpreted as a "detached entity" (even if the StateManager associated with the Entity Object instance's internal state is not a DetachedStateManager.) So calling em.merge(entityWithSomeOtherPCsStateManager) should be treated as a detached entity, and return a new Entity Object instance. Which could create "interesting problems" if the original entity doesn't have a committed row on the database yet (because the two different PCs will have two different db connections, and a merge operation will trigger a fetch operation from the database/cache.) Remember the JPA spec requires Read-Committed to be the minimum isolation level.
        Hide
        Jody Grassel added a comment -

        Further Thoughts, as I realize the statement "A managed entity instance is an instance with a persistent identity that is currently associated with a persistence context." could be read differently than how I read it (using the 2.1 spec, which should not be different from previous spec iterations.)

        3.2.8 Managed Instances
        It is the responsibility of the application to insure that an instance is managed in only a single persistence context. The behavior is undefined if the same Java instance is made managed in more than one persistence context.

        The contains() method can be used to determine whether an entity instance is managed in the current persistence context.

        – What I take from here is that from the perspective of a Persistence Context, an entity is managed if and only if it is actively associated with it. So an Entity Object instance with a StateManager associated with PCtx#1 is a "managed entity" only from the perspective of PCtx#1 (emPCTX1.contains(entity) returns true). Any other PCtxs, such as PCtx#2 would see that it has a StateManager that is not associated with it so it is neither "new" nor "managed" (by PCtx#2) and should consider it to be unmanaged (detached, since it cannot be a "new" entity for reasons previously stated) - in this case emPCTX2(entity) returns false.

        Show
        Jody Grassel added a comment - Further Thoughts, as I realize the statement "A managed entity instance is an instance with a persistent identity that is currently associated with a persistence context." could be read differently than how I read it (using the 2.1 spec, which should not be different from previous spec iterations.) 3.2.8 Managed Instances It is the responsibility of the application to insure that an instance is managed in only a single persistence context. The behavior is undefined if the same Java instance is made managed in more than one persistence context. The contains() method can be used to determine whether an entity instance is managed in the current persistence context. – What I take from here is that from the perspective of a Persistence Context, an entity is managed if and only if it is actively associated with it. So an Entity Object instance with a StateManager associated with PCtx#1 is a "managed entity" only from the perspective of PCtx#1 (emPCTX1.contains(entity) returns true). Any other PCtxs, such as PCtx#2 would see that it has a StateManager that is not associated with it so it is neither "new" nor "managed" (by PCtx#2) and should consider it to be unmanaged (detached, since it cannot be a "new" entity for reasons previously stated) - in this case emPCTX2(entity) returns false.
        Hide
        Mark Struberg added a comment -

        > Managed entities are also provided by find/query operations (though it would return a detached entity if it's a CMTS entitymanager invocation outside of a transaction.)

        Well, this is not quite what I do read from the JPA and JTA specs. The spec says that in such cases all query operations must succeed (thus also lacy loading shall work) but all write operations must get queued until the EntityManager joins a transaction.
        And this mechanism is lacking in OpenJPA I fear. At least I'm not aware that we can do this somehow.

        Show
        Mark Struberg added a comment - > Managed entities are also provided by find/query operations (though it would return a detached entity if it's a CMTS entitymanager invocation outside of a transaction.) Well, this is not quite what I do read from the JPA and JTA specs. The spec says that in such cases all query operations must succeed (thus also lacy loading shall work) but all write operations must get queued until the EntityManager joins a transaction. And this mechanism is lacking in OpenJPA I fear. At least I'm not aware that we can do this somehow.
        Hide
        Jody Grassel added a comment - - edited

        Outside of a tran, a CMTS EM find/query will work, the spec/javadoc just requires that the entities returned are detached. Anyways, that really isn't relevant to this JIRA.

        And I focused a bit too much on the first part and gave just a partial answer.

        As I interpret it, write operations are queued, and it's up to the persistence provider to decide when to flush them to the database (with em.flush() and tran commit being the "push everything to the database and do it Now" tools.) However, because of the Read Committed isolation policy, a new Entity that has been persisted and made managed by EM#1, even if flushed () (but not tran committed yet) will not be detectable to any other EM because EM#(not 1) doesn't share the same JDBC connection. So EM#1 could conceivably automatically sync every mutation as it comes in from the application to the database, but it's invisible until that critical tran.commit() takes place.

        Show
        Jody Grassel added a comment - - edited Outside of a tran, a CMTS EM find/query will work, the spec/javadoc just requires that the entities returned are detached. Anyways, that really isn't relevant to this JIRA. And I focused a bit too much on the first part and gave just a partial answer. As I interpret it, write operations are queued, and it's up to the persistence provider to decide when to flush them to the database (with em.flush() and tran commit being the "push everything to the database and do it Now" tools.) However, because of the Read Committed isolation policy, a new Entity that has been persisted and made managed by EM#1, even if flushed () (but not tran committed yet) will not be detectable to any other EM because EM#(not 1) doesn't share the same JDBC connection. So EM#1 could conceivably automatically sync every mutation as it comes in from the application to the database, but it's invisible until that critical tran.commit() takes place.
        Hide
        Mark Struberg added a comment -

        Jody, I'm not sure if the Entity of such a unsynchronized CMTS EM would be 'detached'. At least according to what I talked with Mike Keith (assuming that I didn't misunderstand him) lazy loading and graph traversal would work for such entitites.

        I agree with your 2nd part. Having the same db row managed in 2 different EMs will either not see each other properly or if they do (update case) most likely cause an OptimisticLockingException in one of them - at least if both write!

        Show
        Mark Struberg added a comment - Jody, I'm not sure if the Entity of such a unsynchronized CMTS EM would be 'detached'. At least according to what I talked with Mike Keith (assuming that I didn't misunderstand him) lazy loading and graph traversal would work for such entitites. I agree with your 2nd part. Having the same db row managed in 2 different EMs will either not see each other properly or if they do (update case) most likely cause an OptimisticLockingException in one of them - at least if both write!
        Hide
        Jody Grassel added a comment - - edited

        Looking at the attached test, my opinion is that the following should happen:

        1) The call to populate(), before the test begins, creates a new em, adds a row to the database, commits, and destroys the em.
        2) Enter testMergeManagedParent()
        3) Parent parent = em.find(Parent.class, pk); - returns an instance of Parent (id=K1) with an address of, say, @0000001.
        4) Parent mergedParent = em2.merge(parent); - sees parent is not "new" (because it has a StateManager), and that its associated StateManager belongs to em and not em2, should view parent as a detached entity - so it should perform a fetch from the database, create a new object, say, @0000002, and bring in any fields which have been mutated in @0000001 (which in this case, are none), and return @0000002 to the caller which is saved in the mergedParent field.

        It's a little different scenario than what I was initially led to believe (I thought the scenario would have been the em from step #3 was creating a new entity object instance, here, the row already exists on the db before the test logic runs.)

        Does anyone disagree with this?

        Show
        Jody Grassel added a comment - - edited Looking at the attached test, my opinion is that the following should happen: 1) The call to populate(), before the test begins, creates a new em, adds a row to the database, commits, and destroys the em. 2) Enter testMergeManagedParent() 3) Parent parent = em.find(Parent.class, pk); - returns an instance of Parent (id=K1) with an address of, say, @0000001. 4) Parent mergedParent = em2.merge(parent); - sees parent is not "new" (because it has a StateManager), and that its associated StateManager belongs to em and not em2, should view parent as a detached entity - so it should perform a fetch from the database, create a new object, say, @0000002, and bring in any fields which have been mutated in @0000001 (which in this case, are none), and return @0000002 to the caller which is saved in the mergedParent field. It's a little different scenario than what I was initially led to believe (I thought the scenario would have been the em from step #3 was creating a new entity object instance, here, the row already exists on the db before the test logic runs.) Does anyone disagree with this?
        Hide
        Jody Grassel added a comment - - edited

        I propose the attached fix for this issue, which allows the reporter's sample test to pass.

        Basically the idea is simple: check if the object to be merged (toAttach) has a StateManager associated with it. If it does and that StateManager is a StateManagerImpl (which DetachedStateManager is not a descendent of) then grab its broker reference.

        If this broker reference is different than the broker being used to perform the merge() operation, then set isManagedByAnotherPCtx=true.

        Then modify isNew to the following logic:

        boolean isNew = !broker.isDetached(pc) && !isManagedByAnotherPCtx;

        Basically, if toAttach is not detached and it is not managed by another persistence context, then it is to be considered a new object. If toAttach is not detached (because pc.isDetached() is not broker context aware) but if it is managed by some other broker,t hen it should NOT be considered a new object.

        (Disclaimer: have not run the full junit suite yet, will do so after posting this.)

        Show
        Jody Grassel added a comment - - edited I propose the attached fix for this issue, which allows the reporter's sample test to pass. Basically the idea is simple: check if the object to be merged (toAttach) has a StateManager associated with it. If it does and that StateManager is a StateManagerImpl (which DetachedStateManager is not a descendent of) then grab its broker reference. If this broker reference is different than the broker being used to perform the merge() operation, then set isManagedByAnotherPCtx=true. Then modify isNew to the following logic: boolean isNew = !broker.isDetached(pc) && !isManagedByAnotherPCtx; Basically, if toAttach is not detached and it is not managed by another persistence context, then it is to be considered a new object. If toAttach is not detached (because pc.isDetached() is not broker context aware) but if it is managed by some other broker,t hen it should NOT be considered a new object. (Disclaimer: have not run the full junit suite yet, will do so after posting this.)
        Hide
        Jody Grassel added a comment -

        I would also like to take the time to make the reminder that the 2.2.x is managed by IBM, any changes to this branch will need to go through the PMR process. Otherwise, if the general consensus decides that this is an appropriate fix it will have to go into trunk.

        Show
        Jody Grassel added a comment - I would also like to take the time to make the reminder that the 2.2.x is managed by IBM, any changes to this branch will need to go through the PMR process. Otherwise, if the general consensus decides that this is an appropriate fix it will have to go into trunk.
        Hide
        ASF subversion and git services added a comment -

        Commit 1498565 from Jody Grassel
        [ https://svn.apache.org/r1498565 ]

        OPENJPA-2405: EntityManager.merge does not work for entity that is managed by another EntityManager

        Show
        ASF subversion and git services added a comment - Commit 1498565 from Jody Grassel [ https://svn.apache.org/r1498565 ] OPENJPA-2405 : EntityManager.merge does not work for entity that is managed by another EntityManager
        Hide
        Jody Grassel added a comment -

        Fix has been checked into trunk.

        Show
        Jody Grassel added a comment - Fix has been checked into trunk.
        Hide
        Arne Limburg added a comment -

        Thanks for fixing this, Jody. Your suggested (and implemented) behavior matches my expectation

        Show
        Arne Limburg added a comment - Thanks for fixing this, Jody. Your suggested (and implemented) behavior matches my expectation

          People

          • Assignee:
            Jody Grassel
            Reporter:
            Arne Limburg
          • Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Time Tracking

              Estimated:
              Original Estimate - 2h
              2h
              Remaining:
              Remaining Estimate - 2h
              2h
              Logged:
              Time Spent - Not Specified
              Not Specified

                Development