Repeatable read is a transaction isolation level for keeping a row's value stable across repeated reads within one transaction. It prevents an unrepeatable read: reading a value, then reading a different value after another transaction updates and commits it. It also prevents dirty reads and lost updates in the ANSI isolation-level comparison, but it does not prevent phantom reads. A repeated query can therefore return additional or fewer rows after another transaction inserts or deletes data. section 11.2.1
Table 11.1 ANSI isolation levels and the problems that they address (view table figure)
The isolation-level table compares which concurrency problems are prevented at each level: repeatable read rules out unrepeatable reads, while serializable also rules out phantom reads. section 11.2.1
Choose the level with the transaction's required guarantees in mind. Higher isolation has performance and scalability costs. A JPA pessimistic lock is a separate way to protect selected data: PESSIMISTIC_READ guarantees repeatable reads, while PESSIMISTIC_WRITE additionally requires serialized access without phantom reads. Hibernate's locking SQL depends on the database dialect, and the lock lasts only for the database transaction. section 11.2.1 section 11.2.3
Lock rows used in a calculation
A transaction totals item prices across categories by querying each category with setLockMode(LockModeType.PESSIMISTIC_READ) and a lock-timeout hint. Hibernate adds database-specific locking SQL: PostgreSQL can use FOR SHARE, whereas H2 uses FOR UPDATE for its pessimistic modes. If a required lock cannot be obtained, the operation throws an exception. section 11.2.3
Do not mistake a repeatable managed-entity result for transaction-level repeatable read. Without an active transaction, Hibernate can return an already-loaded entity from the persistence context, preserving its in-memory value, while a scalar query reads the database value in auto-commit mode. Database isolation also matters when refreshing entities: MySQL's stated default is REPEATABLE_READ, so an example that must see another transaction's committed changes configures the JDBC connection for READ_COMMITTED. section 11.3.1 section 13.1.3

