Deadlock not detected during MySQL Hibernate JPA transaction

What you have experienced is called a lost update and it's really not a JPA-level problem, you can easily reproduce this in MySQL shell. I'm assuming you did not do any changes in the database itself, so your default transaction isolation level is REPEATABLE READ.

In MySQL, REPEATABLE READ does not detect possible lost updates (even though that's the common understanding of this isolation level). You can check this answer on SO and the comments thread to learn more.

Basically with the use of MVCC, MySQL tries to avoid contention and deadlocks. In your case you will have to make a trade-off and choose to sacrifice some speed for the sake of consistency.

Your options are to use a SELECT ... FOR UPDATE statement or to set a more strict isolation level, which is SERIALIZABLE (you can do this for individual transaction). Both of these options will block the reads until the concurrent transaction commit/rollback. Thus you will see the consistent view of your data, just a bit later (or a lot later, depending on the application's requirements).

You can also read up on this here, here and here.

Concurrency is hard. :)

UPDATE: After thinking about comments below, there is actually another option that you have: implement Optimistic Locking for your data model. JPA has a support for this, please take look here and here. What you achieve is basically the same, but with a bit different approach (you will have to restart the transactions that failed to to mismatched versions) and less contention due to less locking.