From your message, I can say that you are using transactions, so you need to synchronize the threads somehow. The simplest, but not the most portable or effective solution is to lock tables in which you can use the @Transactional annotation, you must add isolation of your transaction to isolation. SERIALIZABLE
@Transactional(isolation = Isolation.SERIALIZABLE)
If your application is running on the same JVM, another easy way to make a method available for only one thread is to use a synchronized keyword.
public synchronized void method(){}
You can create a common data structure and save it in memory and either synchronize it as a method, or use a framework, for example, a halo or terracotta, this answer goes deeper in this approach .
The last method I can think of is the most reliable, efficient, and difficult. And it synchronizes your application through JMS messages or something like that.
The problem may also be that the record already exists, so you can request the last identifier with something like:
Entity findTop1ByOrderByIdDesc();
Then return the identifier and add it, this can leave holes if you remove your rights, and not the most effective ones, but complete the task.
See also the second diarmuid sentence. The primary key primary key in the definition of your JPA entity.
@Id @GeneratedValue(strategy = GenerationType.AUTO) //This one @Column(name = "id", nullable = false) public int getId() { return id; }
And double check that the id has auto-increment in the table definition. As a final recommendation, you can also check if your transaction does not have access to several entities, one of which may not have a GeneratedValue, and this may be the culprit of the message sent.