Browse files

Fix data corruption problem caused by proxy persistence.

Included test case which fails without fix and passes with it.
  • Loading branch information...
1 parent 46f4c3d commit 6726d6c38317f2ca7a197a38b0fe3f5e71c80bf7 @tomwidmer tomwidmer committed Mar 22, 2013
View
4 ...-core/src/main/groovy/org/grails/datastore/mapping/engine/NativeEntryEntityPersister.java
@@ -781,6 +781,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 +940,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) {
View
46 ...ls-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/UpdateWithProxyPresentSpec.groovy
@@ -12,6 +12,11 @@ import grails.gorm.DetachedCriteria
@ApplyDetachedCriteriaTransform
class UpdateWithProxyPresentSpec extends GormDatastoreSpec {
+ @Override
+ List getDomainClasses() {
+ [Parent, Child]
+ }
+
void "Test update entity with association proxies"() {
given:
session.mappingContext.setProxyFactory(new GroovyProxyFactory())
@@ -38,6 +43,32 @@ class UpdateWithProxyPresentSpec extends GormDatastoreSpec {
personPet.type.name == 'snake'
personPet.type.id == petType.id
}
+
+ 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"
+ }
}
@Entity
@@ -115,3 +146,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 6726d6c

Please sign in to comment.