This is a problem I keep on running into:
I would like to have hibernate manage a single table that represents a collection of collections. For example:
Example, I would like to be able to represent this:
class OwningClass { Long entityId; Map<String, List<Element>> mapOfLists; } class Element { String data_1; boolean data_2; }
as a single table:
OWNER (Foreign key to the owner of this element) MAP_KEY (varchar(30) ) LIST_INDEX (int) ELEMENT_DATA_1 (varchar(1020) ELEMENT_DATA_2 (bit)
It doesn't seem possible without a custom hibernate code, which I don't mind. But I was hoping someone had some guidance on what that custom code should look like.
Its possible to manage if multiple tables are o.k. but obviously that is lame from the db perspective.
" The persistent collections injected by Hibernate behave like HashMap , HashSet , TreeMap , TreeSet or ArrayList , depending on the interface type."
A Bag is a java collection that stores elements without caring about the sequencing, but allow duplicate elements in the list. A bag is a random grouping of the objects in the list. A Collection is mapped with a <bag> element in the mapping table and initialized with java. util. ArrayList.
JPA allows three kinds of objects to store in mapping collections - Basic Types, Entities and Embeddables.
Found the answer on https://xebia.com/blog/mapping-multimaps-with-hibernate/
This is a long blog post from 11 years ago. The key code is:
public class MultiMapType implements UserCollectionType {
public boolean contains(Object collection, Object entity) {
return ((MultiMap) collection).containsValue(entity);
}
public Iterator getElementsIterator(Object collection) {
return ((MultiMap) collection).values().iterator();
}
public Object indexOf(Object collection, Object entity) {
for (Iterator i = ((MultiMap) collection).entrySet().iterator(); i.hasNext();) {
Map.Entry entry = (Map.Entry) i.next();
Collection value = (Collection) entry.getValue();
if (value.contains(entity)) {
return entry.getKey();
}
}
return null;
}
public Object instantiate() {
return new MultiHashMap();
}
public PersistentCollection instantiate(SessionImplementor session, CollectionPersister persister) throws HibernateException {
return new PersistentMultiMap(session);
}
public PersistentCollection wrap(SessionImplementor session, Object collection) {
return new PersistentMultiMap(session, (MultiMap) collection);
}
public Object replaceElements(Object original, Object target, CollectionPersister persister, Object owner, Map copyCache, SessionImplementor session) throws HibernateException {
MultiMap result = (MultiMap) target;
result.clear();
Iterator iter = ( (java.util.Map) original ).entrySet().iterator();
while ( iter.hasNext() ) {
java.util.Map.Entry me = (java.util.Map.Entry) iter.next();
Object key = persister.getIndexType().replace( me.getKey(), null, session, owner, copyCache );
Collection collection = (Collection) me.getValue();
for (Iterator iterator = collection.iterator(); iterator.hasNext();) {
Object value = persister.getElementType().replace( iterator.next(), null, session, owner, copyCache );
result.put(key, value);
}
}
return result;
}
}
There was also some talk over here: Multimap in Hibernate
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With