Fix for Issue 72 - Bug - models.Role cannot be cast to java.util.Map [error] at com.avaje.ebeaninternal.server.persist.DefaultPersister.saveAssocManyDetails(DefaultPersister.java:877)

This commit is contained in:
Rob Bygrave
2014-01-23 00:50:09 +13:00
parent 87a948223c
commit ee96c4afa6
12 changed files with 169 additions and 22 deletions
@@ -145,14 +145,19 @@ public interface BeanCollection<E> extends Serializable {
public boolean isEmpty();
/**
* Returns the underlying details as an iterator.
* <p>
* Note that for maps this returns the entrySet as we need the keys of the
* map.
* </p>
* Returns the underlying collection of beans from the Set, Map or List.
*/
public Collection<E> getActualDetails();
/**
* Returns the underlying entries so for Maps this is a collection of
* Map.Entry.
* <p>
* For maps this returns the entrySet as we need the keys of the map.
* </p>
*/
public Collection<?> getActualEntries();
/**
* Set to true if maxRows was hit and there are actually more rows available.
* <p>
@@ -106,6 +106,11 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
public Collection<E> getActualDetails() {
return list;
}
@Override
public Collection<?> getActualEntries() {
return list;
}
/**
* Returns the underlying list.
@@ -104,14 +104,23 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
}
/**
* Returns the map entrySet iterator.
* Returns the collection of beans (map values).
*/
public Collection<E> getActualDetails() {
return map.values();
}
/**
* Returns the map entrySet.
* <p>
* This is because the key values may need to be set against the details (so
* they don't need to be set twice).
* </p>
*/
public Collection<E> getActualDetails() {
return map.values();
public Collection<?> getActualEntries() {
return map.entrySet();
}
/**
@@ -12,8 +12,7 @@ import com.avaje.ebean.bean.BeanCollectionLoader;
/**
* Set capable of lazy loading.
*/
public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E>,
BeanCollectionAdd {
public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E>, BeanCollectionAdd {
/**
* The underlying Set implementation.
@@ -113,6 +112,11 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
return set;
}
@Override
public Collection<?> getActualEntries() {
return set;
}
/**
* Returns the underlying set.
*/
@@ -970,11 +970,14 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
public void cachePutMany(BeanPropertyAssocMany<?> many, BeanCollection<?> bc, Object parentId) {
BeanDescriptor<?> targetDescriptor = many.getTargetDescriptor();
Collection<?> actualDetails = bc.getActualDetails();
ArrayList<Object> idList = new ArrayList<Object>();
// get the underlying collection of beans (in the List, Set or Map)
Collection<?> actualDetails = bc.getActualDetails();
for (Object bean : actualDetails) {
Object id = targetDescriptor.getId(bean);
idList.add(id);
// Collect the id values
idList.add(targetDescriptor.getId(bean));
}
CachedManyIds ids = new CachedManyIds(idList);
cachePutCachedManyIds(parentId, many.getName(), ids);
@@ -38,6 +38,10 @@ public class ManyType {
}
}
public boolean isMap() {
return Underlying.MAP.equals(underlying);
}
/**
* Return the matching Query type.
*/
@@ -788,7 +788,8 @@ public final class DefaultPersister implements Persister {
// check that the list is not null and if it is a BeanCollection
// check that is has been populated (don't trigger lazy loading)
Collection<?> collection = getDetailsIterator(details);
// For a Map this is a collection of Map.Entry objects and not beans
Collection<?> collection = getActualEntries(details);
if (collection == null) {
// nothing to do here
@@ -1262,7 +1263,7 @@ public final class DefaultPersister implements Persister {
* Return the details of the collection or map taking care to avoid
* unnecessary fetching of the data.
*/
private Collection<?> getDetailsIterator(Object o) {
private Collection<?> getActualEntries(Object o) {
if (o == null) {
return null;
}
@@ -1271,7 +1272,9 @@ public final class DefaultPersister implements Persister {
if (!bc.isPopulated()) {
return null;
}
return bc.getActualDetails();
// For maps this is a collection of Map.Entry, otherwise it
// returns a collection of beans
return bc.getActualEntries();
}
if (o instanceof Map<?, ?>) {
@@ -1281,8 +1284,7 @@ public final class DefaultPersister implements Persister {
} else if (o instanceof Collection<?>) {
return ((Collection<?>) o);
}
String m = "expecting a Map or Collection but got [" + o.getClass().getName() + "]";
throw new PersistenceException(m);
throw new PersistenceException("expecting a Map or Collection but got [" + o.getClass().getName() + "]");
}
/**
@@ -83,7 +83,7 @@ public class DefaultOrmQueryEngine implements OrmQueryEngine {
Collection<T> c = result.getActualDetails();
for (T bean : c) {
descriptor.cachePutBeanData(bean);
}
}
}
if (!result.isEmpty() && query.isUseQueryCache()){