Am I doing something wrong?
EntityManager#persist() will not trigger immediate insertion (unless you use the IDENTITY strategy). Therefore, if you want to actually write the changes in memory to the database and be able to catch the violation of the restriction, you need to flush() "manually" (although even this does not guarantee strict control, your database can be configured to use deferred constraints).
In other words, what you do is IMO, just the right way.
I have a service method with @Transactional on it (REQUIRED) called addNewObject (). Something happens in this method that may throw an exception (and thus roll back the transaction). One of these calls is a call to the addObject method of the DAO method. This may fail due to a unique constraint. Now, if I make a flash, the object will be saved if there is no unique violation. However, there might be something else inside the service that causes the method to throw an exception.
I think you are confusing flush and commit . If something goes addObject and throws a fatal exception (but inside the same transaction), the whole transaction will be rolled back, including INSERT corresponding to persist() calls. To summarize, flush ! = commit .
source share