0

I have the following case where attachDirty saveOrUpdate() always tries to persist the entities when the transactional annotated method is called in burst.

Is there a way to avoid this primary key constraint violation exception? I thought that saveOrUpdate() would persist if the entity is not yet created and update it otherwise.

I used this ..orUpdate() instead of persist() as a way to handle these bursts.

There is no data corruption actually. Because the first saveOrUpdate() does save 1 record for each entity as desired. The other persists are rejected by the database because of the primary key constraint violation.

I researched about optimistic and pessimistic locking. I understood that these work after fetching an already existing record. Here the entities are new, not existing.

How to approach this in a better way?

Concurrent calls causing attachDirty saveOrUpdate() to always try to save

aboudirawas
  • 65
  • 15

1 Answers1

1

Why is the exception an issue, can't you just ignore it? If your database supports "upsert" you could theoretically make use of that by adding the following annotation on your entity:

@org.hibernate.annotations.SQLInsert (sql = "INSERT INTO message_user (user_id) VALUES (?) ON CONFLICT DO NOTHING")
Christian Beikov
  • 6,925
  • 1
  • 26
  • 48
  • I personally have no problem with this exception. The person who is reading the logs does :p This is exactly what I needed. It worked for postgresSQL. Now I have to find a way to make it work for Oracle as well. Thank you! – aboudirawas Nov 10 '20 at 08:15
  • There is a MERGE statement for Oracle which you can use, but can't you just catch the exception and ignore it to avoid the logging? – Christian Beikov Nov 10 '20 at 15:21
  • I tried to wrap the `.attachDirty(...)` with try catch. The exception seems to be fired at some other level ( I think at the end of the @Transactional annotated method ). I don't know how to catch that. Do you ? if yes kindly share some hints or resources please. – aboudirawas Nov 10 '20 at 15:29
  • 1
    The exception is thrown when flushing the changes. If you don't call `entityManager.flush` manually, Hibernate usually flushes right before doing the commit. So the try-catch has to go around a flush call. – Christian Beikov Nov 10 '20 at 19:56