session.refresh(instance) doesn't update given instance if it was loaded in a batch

Description

Session.refresh doesn't return an instance, it updates the given instance in place. It does this by passing the optionalObject parameter to EntityPersister.load, identifying the object to be populated from the DB read. If the loader is a LegacyBatchingEntityLoader it disregards the optionalObject as it is going to load a batch of objects and optionalObject isn't supported in batch loads.

This means that the refresh operation in fact loads into a new instance, and the original instance is untouched. It isn't refreshed. And the session now contains the original instance and the new refreshed instance, but returns the new refreshed instance for subsequent calls to Session.get.

The problem this manifests, and how we detected this, is that any PersistentCollections in the instance are evicted (session set to null), and when we then try to access them an IllegalStateException is thrown because the session is null.

Environment

Hibernate 4.3.0, PostgreSQL 9.2 / 9.3

Assignee

Steve Ebersole

Reporter

Karl von Randow

Fix versions

None

backPortable

None

Suitable for new contributors

None

Requires Release Note

None

Pull Request

None

backportDecision

None

Components

Affects versions

Priority

Major
Configure