HibernateCollectionConverter.javacom.thoughtworks.xstream.converters.Converter to intercept every PersistentCollection instance before XStream serializes it. Forces initialization of lazy-loaded collections, extracts the underlying java.util collection (dealing with Hibernate's peculiar internal representation of sets as maps), and delegates the actual XML writing to the appropriate standard XStream converter. This is the value-level converter — the HibernateCollectionsMapper handles name-level mapping, and this converter handles the actual collection data.XStream converters form a chain. When XStream encounters an object to serialize, it iterates registered converters calling canConvert(Class). HibernateCollectionConverter claims any class assignable to org.hibernate.collection.spi.PersistentCollection — this covers PersistentBag, PersistentList, PersistentSet, PersistentSortedSet, PersistentMap, and PersistentSortedMap. Because XStream checks converters in registration order, this converter must be registered before default converters. This is done by HibernateMapper when configuring XStream instances.
The constructor accepts a ConverterLookup and immediately resolves and caches five converter references:
| Field | Converted Type | Purpose |
|---|---|---|
listSetConverter | ArrayList.class | Handles List and Set output |
mapConverter | HashMap.class | Handles Map output |
treeMapConverter | TreeMap.class | Handles sorted map output |
treeSetConverter | TreeSet.class | Handles sorted set output |
defaultConverter | Object.class | Fallback for unrecognized types |
source instanceof PersistentCollection. If so, calls forceInitialization() to trigger lazy loading, then retrieves getStoredSnapshot() — the underlying JDK collection that Hibernate uses internally. (Note: a TODO comment references getCollectionSnapshot() as a potential alternative.)HashMap where keys are the set elements. The converter extracts .values() and wraps them in a new TreeSet to restore proper set semantics.HashMap internally. Extracts .values() and wraps in a new HashSet.listSetConverter (for ArrayList/HashSet/TreeSet), mapConverter, treeMapConverter, treeSetConverter. Falls back to defaultConverter.unmarshal() returns null. This converter is unidirectional — it only handles serialization (Java→XML). Deserialization (XML→Java) produces standard JDK collections, which are then assigned to entity fields. Hibernate replaces them with persistent wrappers when the entity is later attached to a session.xstream.registerConverter() calls.JOIN FETCH queries.PersistentSet and PersistentSortedSet using HashMap structures. The converter must explicitly unwrap these. If this logic were removed, XStream would serialize sets as XML maps (with key elements), producing unparseable output.getCollectionSnapshot().getSnapshot() instead of getStoredSnapshot(). The current approach works because forceInitialization() guarantees the stored snapshot exists, but this is fragile across Hibernate versions.868d6abb7 2025 -> 2026 63081666f Source file headers: 2024-> 2025. c1d14ecdb Migration stuff in progress... b6092df09 Copyright 2023 -> 2024 ab45d51fa Copyright 2001-2022 -> 2001-2023. 5f7ef41b8 Copyright 2021 -> 2022 ceb63e8a1 Source code header: (C) 2001-2021. 7c79f1922 Copyright of source header -> 2020. 32f634b88 Optimize imports dd5ca38ac CopyRight of all java file-header updated or created. 9ebb88522 Initial commit