JPA EntityManager: merge () trying to create a new line in db - why?

I am using JPA through the Play Framework.

I check if the user object is cached, and if so, I get it and merge () so that I can update the fields and save the changes later:

user = (User) Cache.get("user-auth-" + sessionAuthToken); if (user != null) { user = user.merge(); // I believe this is the same as EntityManager.merge() } 

However, when I do this, I get the following error:

 PersistenceException occured : org.hibernate.exception.ConstraintViolationException: could not insert: [models.User] ... Caused by: com.mysql.jdbc.exceptions.jdbc4. MySQLIntegrityConstraintViolationException: Duplicate entry '1235411688335416533' for key 'authToken' 

It seems that he is trying to insert a new user, even if that user should be, and is already in the database. Why merge () this?

Or maybe I'm going to do it completely wrong - the advice will be appreciated.

+4
source share
5 answers

I believe your problem is how Play manages the JPA (and transactions).

After receiving the request, the structure immediately creates a JPA manager and transaction. From now on, all your model objects are automatically associated with the manager.

Play makes it easy to work with this model in two ways:

  • You need to explicitly indicate that you want to save changes to the object (via save ())
  • A transaction is executed automatically if there is no exception, or you specify it for rollback (JPA.setRollbackOnly ())

By running "merge", you are trying to add an entity to the Manager that already exists, which raises a unique key exception. If you just load the object from the cache, you can change and call save () after it is completed, and it will work.

+2
source

I think this could be a bit of a deal with hashCode() and equals() . If they were not executed correctly, a new my object will be inserted instead of updating the existing one.

+3
source

See What is the correct way to reattach individual objects in Hibernate? . Merge tries to write the stale state to db to overwrite possible other simultaneous updates. A related question mentions session.lock(entity, LockMode.NONE); as a possible solution, but I have not tried it.

+1
source

If authToken not the primary key, it is possible that the primary key of the User instance does not match the primary key of its copy in the database, so merge() considers this to be a new User and tries to insert it.

So, check the primary key of the User , maybe it was somehow damaged or lost.

+1
source

This is an entity definition problem. ; especially regarding primary / unsaved values .

The entity definition must be correct because Hibernate recognizes it as "already saved." For example, the presence of "null" in a field with a zero version may cause Hibernate to ignore any existing identifier and consider it unsaved.

This is a sleep issue, not just a JPA. JPA is an interface - you are having problems with a specific implementation.

+1
source

Source: https://habr.com/ru/post/1338297/


All Articles