Monday 17 September 2012

A bug in EclipseLink

I recently found a bug in EclipseLink JPA provider.

I posted the question and answer at Stackoverflow.

Let me summarize the problem here.

First, retrieve an entity from the database, call entityManager.merge() on this entity, change the entity's Id, call entityManager.merge() on this entity again. An exception will be thrown.

Note the above operations are not executed in the same transaction context. Rather, each merge() is executed within its own transaction.

Here is the pseudocode to illustrate the idea.


User user = userManager.find(1); 
userManager.merge(user); 
System.out.println("User is managed? "+userManager.contains(user);
user.setId(2);
userManager.merge(user);


The console outputs:

User is managed? false

Exception [EclipseLink-7251] (Eclipse Persistence Services - 2.1.3.v20110304-r9073): org.eclipse.persistence.exceptions.ValidationException
Exception Description: The attribute [id] of class [demo.model.User] is mapped to a primary key column in the database. Updates are not allowed.


userManager.contains() methods invokes the entityManager.contains() method, the fact that it returns false indicates the entity is not being managed. When switching the JPA provider from EclipseLink to Hibernate, it works fine. And according to the JPA specification, it shouldn't throw any exception in this scenario. I believe this bug has manifested itself in other forms. I have found several articles discussing this exception. If you want to reproduce this error, this blog presents one of the simplest approaches.