Permalink
Browse files

Merge branch '1.x'

Conflicts:
	grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/UpdateWithProxyPresentSpec.groovy
  • Loading branch information...
2 parents 23b3f5a + bc369c0 commit 21b151a0bead0d33caad6db5cdaabec61460cf43 @tomwidmer tomwidmer committed Mar 22, 2013
@@ -56,6 +56,13 @@ public Object getAttribute(Object entity, String attributeName) {
return attrs.get(attributeName);
}
+ protected void removeAttributesForEntity(Object entity) {
+ if (entity == null) {
+ return;
+ }
+ attributes.remove(System.identityHashCode(entity));
+ }
+
/**
* Performs clear up. Subclasses should always call into this super
* implementation.
@@ -86,8 +86,6 @@ public void onEviction(PersistentEntity key, Collection<PendingUpdate> value) {
protected TPCacheAdapterRepository cacheAdapterRepository;
- protected Map<Object, Serializable> objectToKey = new ConcurrentHashMap<Object, Serializable>();
-
private Map<PersistentEntity, Collection<PendingInsert>> pendingInserts =
new Builder<PersistentEntity, Collection<PendingInsert>>()
.listener(EXCEPTION_THROWING_INSERT_LISTENER)
@@ -351,7 +349,6 @@ public void clear() {
pendingUpdates.clear();
pendingDeletes.clear();
attributes.clear();
- objectToKey.clear();
exceptionOccurred = false;
}
@@ -406,7 +403,6 @@ public void cacheInstance(Class type, Serializable key, Object instance) {
if (type == null || key == null || instance == null) {
return;
}
- objectToKey.put(instance, key);
getInstanceCache(type).put(key, instance);
}
@@ -425,14 +421,13 @@ public void clear(Object o) {
final Map<Serializable, Object> cache = firstLevelCache.get(o.getClass());
if (cache != null) {
- Serializable key = objectToKey.get(o);
+ Persister persister = getPersister(o);
+ Serializable key = persister.getObjectIdentifier(o);
if (key != null) {
cache.remove(key);
- objectToKey.remove(o);
}
}
-
- attributes.remove(o);
+ removeAttributesForEntity(o);
}
public void attach(Object o) {
@@ -521,7 +516,13 @@ public Object proxy(Class type, Serializable key) {
"]. The class [" + type.getName() + "] is not a known persistent type.");
}
- return persister.proxy(key);
+ // only return proxy if real instance is not available.
+ Object o = getInstanceCache(type).get(key);
+ if (o == null) {
+ o = persister.proxy(key);
+ }
+
+ return o;
}
public void lock(Object o) {
@@ -483,13 +483,10 @@ else if (tmp != null && !prop.getType().isInstance(tmp)) {
boolean isLazy = isLazyAssociation(associationPropertyMapping);
final Class propType = prop.getType();
- if (isLazy) {
- Object proxy = getProxyFactory().createProxy(session, propType, associationKey);
- ea.setProperty(prop.getName(), proxy);
- }
- else {
- ea.setProperty(prop.getName(), session.retrieve(propType, associationKey));
- }
+ Object value = isLazy ?
+ session.proxy(propType, associationKey) :
+ session.retrieve(propType, associationKey);
+ ea.setProperty(prop.getName(), value);
}
}
}
@@ -781,6 +778,9 @@ private boolean isLazyAssociation(PropertyMapping<Property> associationPropertyM
@Override
protected final Serializable persistEntity(final PersistentEntity persistentEntity, Object obj) {
T tmp = null;
+ ProxyFactory proxyFactory = getProxyFactory();
+ // if called internally, obj can potentially be a proxy, which won't work.
+ obj = proxyFactory.unwrap(obj);
final NativeEntryModifyingEntityAccess entityAccess = (NativeEntryModifyingEntityAccess) createEntityAccess(persistentEntity, obj, tmp);
K k = readObjectIdentifier(entityAccess, persistentEntity.getMapping());
@@ -937,7 +937,6 @@ else if (association.doesCascade(CascadeType.PERSIST) && association.getAssociat
if (associatedObject != null) {
Serializable associationId;
NativeEntryEntityPersister associationPersister = (NativeEntryEntityPersister) session.getPersister(associatedObject);
- ProxyFactory proxyFactory = getProxyFactory();
if (proxyFactory.isInitialized(associatedObject) && !session.contains(associatedObject)) {
Serializable tempId = associationPersister.getObjectIdentifier(associatedObject);
if (tempId == null) {
@@ -110,4 +110,11 @@
* @return The objects id
*/
Serializable refresh(Object o);
+
+ /**
+ * Get the identifier for the given object, if it has one.
+ * @param o The object.
+ * @return The object's id.
+ */
+ Serializable getObjectIdentifier(Object o);
}
@@ -10,6 +10,11 @@ import org.grails.datastore.gorm.query.transform.ApplyDetachedCriteriaTransform
*/
class UpdateWithProxyPresentSpec extends GormDatastoreSpec {
+ @Override
+ List getDomainClasses() {
+ [Pet, Person, PetType, Parent, Child]
+ }
+
void "Test update entity with association proxies"() {
given:
session.mappingContext.setProxyFactory(new GroovyProxyFactory())
@@ -37,9 +42,30 @@ class UpdateWithProxyPresentSpec extends GormDatastoreSpec {
personPet.type.id == petType.id
}
- @Override
- List getDomainClasses() {
- [Pet, Person, PetType]
+ void "Test update unidirectional oneToMany with proxy"() {
+ given:
+ session.mappingContext.setProxyFactory(new GroovyProxyFactory())
+ def parent = new Parent(name: "Bob").save(flush: true)
+ def child = new Child(name: "Bill").save(flush: true)
+ session.clear()
+
+ when:
+ parent = Parent.get(parent.id)
+ child = Child.load(child.id) // make sure we've got a proxy.
+ parent.addToChildren(child)
+ parent.save(flush: true)
+ session.clear()
+ parent = Parent.get(parent.id)
+
+ then:
+ parent.name == 'Bob'
+ parent.children.size() == 1
+
+ when:
+ child = parent.children.first()
+
+ then:
+ child.name == "Bill"
}
}
@@ -118,3 +144,18 @@ class PetType implements Serializable {
static belongsTo = Pet
}
+
+@Entity
+class Parent {
+ Long id
+ String name
+ Set<Child> children = []
+ static hasMany = [children: Child]
+}
+
+@Entity
+class Child {
+ Long id
+ String name
+}
+

0 comments on commit 21b151a

Please sign in to comment.