You say that
"While Hibernate does have the option of generating UUIDs for you, we're back to the same old problem: your objects will not receive an ID at the time of creation, and will have to wait until they're saved."
No need to use a separate UUID to keep track of identity when persistence seals identity, so long as you reserve one value for id as meaning that the object is not persisted. An unpersisted object (one for which hibernate has not yet set the generated id) does not share identity with any other objects and is not equal to any other object besides itself.
The "unsaved id" (-1 for example) is the important point. The object's id is initialized to the unsaved id at object creation time. The value has to be one that will never be generated by your id generation algorithm. When the object is persisted, Hibernate sets the id to the generated id. Then, .equals starts by checking if the id has the unsaved value. If the object's id has the unsaved value, then equality is based on object1 == object2. If object1 and object2 are not the same object, then the two objects when persisted will not represent the same row in the database (hibernate will give them different ids at persistence time), and they are not equal.