mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
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:
@@ -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()){
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.avaje.tests.model.map;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
@Entity
|
||||
public class MpRole {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
private Long organizationId;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Long getOrganizationId() {
|
||||
return organizationId;
|
||||
}
|
||||
|
||||
public void setOrganizationId(Long organizationId) {
|
||||
this.organizationId = organizationId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.avaje.tests.model.map;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.*;
|
||||
|
||||
@Entity
|
||||
public class MpUser {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
@OneToMany(cascade = CascadeType.ALL)
|
||||
@MapKey(name = "id")
|
||||
public Map<Long, MpRole> roles = new HashMap<Long, MpRole>();
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Map<Long, MpRole> getRoles() {
|
||||
return roles;
|
||||
}
|
||||
|
||||
public void setRoles(Map<Long, MpRole> roles) {
|
||||
this.roles = roles;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.avaje.tests.query.other;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.avaje.ebean.BaseTestCase;
|
||||
import com.avaje.ebean.Ebean;
|
||||
import com.avaje.ebean.EbeanServer;
|
||||
import com.avaje.tests.model.map.MpRole;
|
||||
import com.avaje.tests.model.map.MpUser;
|
||||
|
||||
public class TestOneToManyAsMap extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
EbeanServer eServer = Ebean.getServer(null);
|
||||
|
||||
MpUser u = new MpUser();
|
||||
eServer.save(u);
|
||||
|
||||
MpUser u2 = eServer.find(MpUser.class, u.getId());
|
||||
Assert.assertNotNull(u2);
|
||||
|
||||
u2.setName("Charlie Brown");
|
||||
MpRole ourl = new MpRole();
|
||||
ourl.setOrganizationId(47L);
|
||||
u2.getRoles().put(ourl.getOrganizationId(), ourl);
|
||||
eServer.save(u2);
|
||||
|
||||
MpUser u3 = eServer.find(MpUser.class, u.getId());
|
||||
Assert.assertEquals("Charlie Brown", u3.getName());
|
||||
|
||||
Map<Long, MpRole> listMap = u3.getRoles();
|
||||
Assert.assertEquals(1, listMap.size());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,8 +24,8 @@ ebean.autofetch.profiling.base=10
|
||||
ebean.autofetch.traceUsageCollection=false
|
||||
|
||||
|
||||
#ebean.ddl.generate=true
|
||||
#ebean.ddl.run=true
|
||||
ebean.ddl.generate=true
|
||||
ebean.ddl.run=true
|
||||
|
||||
|
||||
ebean.debug.sql=true
|
||||
@@ -81,7 +81,7 @@ ebean.cacheWarmingDelay=-1
|
||||
## DataSources (If using default Ebean DataSourceFactory)
|
||||
## -------------------------------------------------------------
|
||||
|
||||
datasource.default=mysql
|
||||
datasource.default=h2
|
||||
|
||||
datasource.h2.username=sa
|
||||
datasource.h2.password=
|
||||
|
||||
Reference in New Issue
Block a user