Hi,
I need the following result:
Code:
private Map<Long, List<FornecedorRecurso>> fornecedorRecursos;
But, Hibernate doesnt support a List value on a Map. I found out this link:
http://blog.xebia.com/2007/10/05/mappin ... hibernate/He create a class that implements the
UserCollectionType from Hibernate. These are the classes:
MultiMapType.javaCode:
package sigo.utils;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import org.apache.commons.collections.MultiHashMap;
import org.apache.commons.collections.MultiMap;
import org.hibernate.HibernateException;
import org.hibernate.collection.PersistentCollection;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.usertype.UserCollectionType;
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;
}
@Override
public Object instantiate(int arg0)
{
return new MultiHashMap();
}
}
PersistentMultiMap.javaCode:
package sigo.utils;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.Map.Entry;
import org.apache.commons.collections.DefaultMapEntry;
import org.apache.commons.collections.MultiHashMap;
import org.apache.commons.collections.MultiMap;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.collection.PersistentMap;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.type.Type;
@SuppressWarnings("deprecation")
public class PersistentMultiMap extends PersistentMap implements MultiMap
{
/**
*
*/
private static final long serialVersionUID = 1L;
public PersistentMultiMap(SessionImplementor session, MultiMap map)
{
super(session, map);
}
public PersistentMultiMap(SessionImplementor session)
{
super(session);
}
public Object remove(Object key, Object item)
{
Object old = isPutQueueEnabled() ? readElementByIndex(key) : UNKNOWN;
if (old == UNKNOWN)
{
write();
return ((MultiMap) map).remove(key, item);
}
else
{
queueOperation(new RemoveItem(key, item));
return old;
}
}
@Override
public Iterator entries(CollectionPersister persister)
{
return new KeyValueCollectionIterator(super.entries(persister));
}
@Override
public Serializable getSnapshot(CollectionPersister persister) throws HibernateException
{
EntityMode entityMode = getSession().getEntityMode();
MultiHashMap clonedMap = new MultiHashMap(map.size());
Iterator iter = map.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry e = (Map.Entry) iter.next();
Collection collection = (Collection) e.getValue();
for (Iterator i = collection.iterator(); i.hasNext();) {
final Object copy = persister.getElementType().deepCopy(i.next(), entityMode, persister.getFactory());
clonedMap.put(e.getKey(), copy);
}
}
return clonedMap;
}
@Override
public boolean equalsSnapshot(CollectionPersister persister) throws HibernateException {
Map sn = (Map) getSnapshot();
if (sn.size() != map.size())
return false;
Type elemType = persister.getElementType();
for (Iterator i = sn.entrySet().iterator(); i.hasNext();) {
Map.Entry entry = (Map.Entry) i.next();
Map oldState = getCollectionAsIdentityMap((Collection) entry.getValue());
Collection newState = (Collection) map.get(entry.getKey());
for (Iterator iter = newState.iterator(); iter.hasNext();) {
Object newValue = iter.next();
Object oldValue = oldState.get(newValue);
if (newValue != null && oldValue != null && elemType.isDirty(oldValue, newValue, getSession())) {
return false;
}
}
}
return true;
}
private Map getCollectionAsIdentityMap(Collection collection) {
Map map = new HashMap();
for (Iterator iter = collection.iterator(); iter.hasNext();) {
Object element = iter.next();
map.put(element, element);
}
return map;
}
@Override
public Iterator getDeletes(CollectionPersister persister, boolean indexIsFormula) throws HibernateException {
Set result = new HashSet();
Map sn = (Map) getSnapshot();
for (Iterator i = sn.entrySet().iterator(); i.hasNext();) {
Map.Entry entry = (Entry) i.next();
Collection oldState = (Collection) entry.getValue();
Collection newState = (Collection) map.get(entry.getKey());
for (Iterator j = oldState.iterator(); j.hasNext();) {
Object element = j.next();
if (!(newState.contains(element))) {
result.add(element);
}
}
}
return result.iterator();
}
@Override
public boolean needsInserting(Object entry, int i, Type elemType) throws HibernateException {
Map.Entry e = (Entry) entry;
Map sn = (Map) getSnapshot();
Collection oldState = (Collection) sn.get(e.getKey());
return oldState == null || !oldState.contains(e.getValue());
}
@Override
public boolean needsUpdating(Object entry, int i, Type elemType) throws HibernateException
{
Map.Entry e = (Entry) entry;
Map sn = (Map) getSnapshot();
Collection collection = (Collection) sn.get(e.getKey());
if (collection == null) {
return false;
}
for (Iterator iter = collection.iterator(); iter.hasNext();) {
Object oldValue = iter.next();
if (oldValue != null && oldValue.equals(e.getValue())) {
return e.getValue() != null && elemType.isDirty(oldValue, e.getValue(), getSession());
}
}
return false;
}
}
class RemoveItem
{
private final Object key;
private final Object item;
RemoveItem(Object key, Object item) {
this.key = key;
this.item = item;
}
public Object getAddedInstance() {
return null;
}
public Object getOrphan() {
return item;
}
public void operate() {
//((MultiMap) map).remove(key, item);
}
}
final class KeyValueCollectionIterator implements Iterator {
private final Iterator parent;
private Object key;
private Iterator current;
KeyValueCollectionIterator(Iterator parent) {
this.parent = parent;
move();
}
public boolean hasNext() {
return key != null;
}
public Object next() {
if (key == null) {
throw new NoSuchElementException();
} else {
DefaultMapEntry result = new DefaultMapEntry(key, current.next());
if (!current.hasNext()) {
move();
}
return result;
}
}
private void move() {
while (this.parent.hasNext()) {
Map.Entry entry = (Entry) this.parent.next();
key = entry.getKey();
current = ((Collection) entry.getValue()).iterator();
if (current.hasNext()) {
return;
}
}
key = null;
}
public void remove() {
throw new UnsupportedOperationException();
}
}
I'm not able to use them. This is the error:
Code:
Initial SessionFactory creation failed.org.hibernate.AnnotationException: Illegal attempt to map a non collection as a @OneToMany, @ManyToMany or @CollectionOfElements: sigo.model.Orcamento.fornecedorRecursos
Tried so:
Code:
@OneToMany(mappedBy="orcamento")
@MapKey(columns={@Column(name="fk_fornecedorId")})
public MultiMapType getFornecedorRecursos()
{
return fornecedorRecursos;
}
public void setFornecedorRecursos(
MultiMapType fornecedorRecursos)
{
this.fornecedorRecursos = fornecedorRecursos;
}
Somebody know what is happening?
cheers,
André Vendramini