disclaimer: I am not an JPA expert, I simply had various experiences with it.
Usage of @Transactional
The reasons behind using a topmost @Transactional might be multiple, and I guess the developer who wrote this piece of code should be the one answering here.
Still, I can see two main reasons one would do so:
- a poor understanding of
@Transactional annotation (see rest of the answer),
- pure laziness: the developer did not want to annotate all underlying methods and was aware of the risks.
According to my experience, this is an extremely risky practice:
I once encountered an issue related to a @Transactional on application entrypoint.
The problem was at first not that visible, but showed off when someone added an HTTP call nested in the workflow of that entrypoint.
Indeed, we were opening database connection, doing an HTTP call, writing the response to a database and finally closing the connection.
I let you imagine what happened when the service behind the HTTP call got really slow to answer (for reasons only they know)...
Database connections were basically stacking up without being released on time, leading to saturation of database connection pool.
This would not have happened if we simply let the HTTP call being made out of a transaction, since database connections would have been opened only when we needed to actually access to the database.
Personal conclusion: always put the @Transactional on purely database relative piece of code. In your example, this would be at least on the EventInterface.groupUpdate method.
Using topmost @Transactional
Based on the previous answer, I would suggest you place your @Transactional on a method which guarantees by design that it only relies on your own system.
For your specific issue, I would simply annotate the method persisting the parentEvent with an @Transactional. With a correct entity relationship graph, your parentEvent should only be persisted if all its related entities were, otherwise the persisting event will throw a exception, marking the transaction for rollback (see javax.persistence.PersistenceException).
If you want to return a decent HTTP status to your client on such events, you might want to either:
- wrap your code in a try/catch to handle the thrown exception
- setup a
RestControllerAdvice extending ResponseEntityExceptionHandler (Spring)
TLDR;
Make sure your @Transactional method relies by design only on your system so that your database connection pool is not dependent of another system.