You have to inflate your cache anew from DB in every transaction.
You don't have any data when you start.
Sure, that's unavoidable if you want to do optimistic locking.You don't have any data when you start.
doesn't have to come from the same transaction as your update.
That's the whole point of it.
However, there are records that have indirect dependencies. Stuff like updates to child records of which the parent record has gone away. Constraints that are not (portably or easily) expressible, such as rows covering contiguous ranges in their START_PERIOD and END_PERIOD fields. Configuration data that describes valid values, process A reduces the valid range, process B has the configuration in cache and validates against a stale configuration.
This kind of stuff can be handled by either reloading everything on every application transaction. That's Hibernate's standard mode of operation (if you don't use a second-level cache, which is the default). Or by explicit coding. Or by letting application programmers specify each and every data dependency, and having the ORM detect changes not just in the records being updated but also changes in all records that these updates might depend on.