diff --git a/src/main/java/org/caosdb/datetime/FragmentDateTime.java b/src/main/java/org/caosdb/datetime/FragmentDateTime.java
index 52faf5f2040de56c05bb7ce4b5aee130fadf67c3..a14192fcf30697808c19df13700ab34b53b87a17 100644
--- a/src/main/java/org/caosdb/datetime/FragmentDateTime.java
+++ b/src/main/java/org/caosdb/datetime/FragmentDateTime.java
@@ -22,7 +22,9 @@
  */
 package org.caosdb.datetime;
 
+import java.util.Objects;
 import java.util.TimeZone;
+import org.caosdb.server.datatype.Value;
 
 public abstract class FragmentDateTime implements DateTimeInterface {
 
@@ -53,4 +55,13 @@ public abstract class FragmentDateTime implements DateTimeInterface {
     this.nanosecond = nanosecond;
     this.timeZone = tz;
   }
+
+  @Override
+  public boolean equals(Value val) {
+    if (val instanceof FragmentDateTime) {
+      FragmentDateTime that = (FragmentDateTime) val;
+      return Objects.equals(that.toDatabaseString(), this.toDatabaseString());
+    }
+    return false;
+  }
 }
diff --git a/src/main/java/org/caosdb/datetime/UTCDateTime.java b/src/main/java/org/caosdb/datetime/UTCDateTime.java
index 0ecb3ac60dfe796692c344e590f3935c36fceac3..765eb3f924b9d7d0bb26fd92b71c4513e6561f63 100644
--- a/src/main/java/org/caosdb/datetime/UTCDateTime.java
+++ b/src/main/java/org/caosdb/datetime/UTCDateTime.java
@@ -25,8 +25,10 @@ package org.caosdb.datetime;
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.GregorianCalendar;
+import java.util.Objects;
 import java.util.TimeZone;
 import org.caosdb.server.datatype.AbstractDatatype.Table;
+import org.caosdb.server.datatype.Value;
 import org.jdom2.Element;
 
 public class UTCDateTime implements Interval {
@@ -360,4 +362,13 @@ public class UTCDateTime implements Interval {
   public boolean hasNanoseconds() {
     return this.nanoseconds != null;
   }
+
+  @Override
+  public boolean equals(Value val) {
+    if (val instanceof UTCDateTime) {
+      UTCDateTime that = (UTCDateTime) val;
+      return Objects.equals(that.toDatabaseString(), this.toDatabaseString());
+    }
+    return false;
+  }
 }
diff --git a/src/main/java/org/caosdb/server/datatype/AbstractEnumValue.java b/src/main/java/org/caosdb/server/datatype/AbstractEnumValue.java
index 06216c822c705fa6fbaef949386966af15ff6b13..ac93629c5e8f3189975a8c1b93f9090fdc80edbe 100644
--- a/src/main/java/org/caosdb/server/datatype/AbstractEnumValue.java
+++ b/src/main/java/org/caosdb/server/datatype/AbstractEnumValue.java
@@ -52,7 +52,15 @@ public abstract class AbstractEnumValue implements SingleValue {
   @Override
   public boolean equals(final Object obj) {
     if (obj instanceof AbstractEnumValue) {
-      final AbstractEnumValue that = (AbstractEnumValue) obj;
+      return equals((AbstractEnumValue) obj);
+    }
+    return false;
+  }
+
+  @Override
+  public boolean equals(Value val) {
+    if (val instanceof AbstractEnumValue) {
+      final AbstractEnumValue that = (AbstractEnumValue) val;
       return Objects.equal(that.value, this.value);
     }
     return false;
diff --git a/src/main/java/org/caosdb/server/datatype/CollectionValue.java b/src/main/java/org/caosdb/server/datatype/CollectionValue.java
index 55cbf0489c3f965e19784c80439d291930d89841..2a55b47feab814ab5633c5e65ebb8b2c2afcfe1a 100644
--- a/src/main/java/org/caosdb/server/datatype/CollectionValue.java
+++ b/src/main/java/org/caosdb/server/datatype/CollectionValue.java
@@ -80,4 +80,23 @@ public class CollectionValue implements Value, Iterable<IndexedSingleValue> {
   public int size() {
     return list.size();
   }
+
+  @Override
+  public boolean equals(Value val) {
+    if (val instanceof CollectionValue) {
+      CollectionValue that = (CollectionValue) val;
+      sort();
+      that.sort();
+      return this.list.equals(that.list);
+    }
+    return false;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof Value) {
+      return this.equals((Value) obj);
+    }
+    return false;
+  }
 }
diff --git a/src/main/java/org/caosdb/server/datatype/GenericValue.java b/src/main/java/org/caosdb/server/datatype/GenericValue.java
index 02d735abcc36297e61b08f99455f077d832a3a4b..a4b1b0b1508b9debde1f34f1dd58786bdae840c8 100644
--- a/src/main/java/org/caosdb/server/datatype/GenericValue.java
+++ b/src/main/java/org/caosdb/server/datatype/GenericValue.java
@@ -89,8 +89,16 @@ public class GenericValue implements SingleValue {
 
   @Override
   public boolean equals(final Object obj) {
-    if (obj instanceof GenericValue) {
-      final GenericValue that = (GenericValue) obj;
+    if (obj instanceof Value) {
+      return equals((Value) obj);
+    }
+    return false;
+  }
+
+  @Override
+  public boolean equals(Value val) {
+    if (val instanceof GenericValue) {
+      final GenericValue that = (GenericValue) val;
       return Objects.equal(that.value, this.value);
     }
     return false;
diff --git a/src/main/java/org/caosdb/server/datatype/IndexedSingleValue.java b/src/main/java/org/caosdb/server/datatype/IndexedSingleValue.java
index a9ed584b3ee858e6de2bbb84ad4a43da820cedb0..ec9280c3ab0cbdf6e577feec4d40a01f6402dbfe 100644
--- a/src/main/java/org/caosdb/server/datatype/IndexedSingleValue.java
+++ b/src/main/java/org/caosdb/server/datatype/IndexedSingleValue.java
@@ -22,6 +22,7 @@
  */
 package org.caosdb.server.datatype;
 
+import java.util.Objects;
 import org.caosdb.server.datatype.AbstractDatatype.Table;
 import org.jdom2.Element;
 
@@ -78,4 +79,21 @@ public class IndexedSingleValue implements SingleValue, Comparable<IndexedSingle
   public SingleValue getWrapped() {
     return this.wrapped;
   }
+
+  @Override
+  public boolean equals(Value val) {
+    if (val instanceof IndexedSingleValue) {
+      IndexedSingleValue that = (IndexedSingleValue) val;
+      return Objects.equals(that.wrapped, this.wrapped);
+    }
+    return false;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof Value) {
+      return this.equals((Value) obj);
+    }
+    return false;
+  }
 }
diff --git a/src/main/java/org/caosdb/server/datatype/ReferenceValue.java b/src/main/java/org/caosdb/server/datatype/ReferenceValue.java
index 89601b50a46cbf838a995a222b0d4c43150f8a19..40b05e48d10db963268541ccc3efeec6e98e490c 100644
--- a/src/main/java/org/caosdb/server/datatype/ReferenceValue.java
+++ b/src/main/java/org/caosdb/server/datatype/ReferenceValue.java
@@ -199,13 +199,21 @@ public class ReferenceValue implements SingleValue {
 
   @Override
   public boolean equals(final Object obj) {
-    if (obj instanceof ReferenceValue) {
-      final ReferenceValue that = (ReferenceValue) obj;
+    if (obj instanceof Value) {
+      return equals((Value) obj);
+    }
+    return false;
+  }
+
+  @Override
+  public boolean equals(Value val) {
+    if (val instanceof ReferenceValue) {
+      final ReferenceValue that = (ReferenceValue) val;
       if (that.getId() != null && getId() != null) {
         return that.getId().equals(getId())
             && Objects.deepEquals(that.getVersion(), this.getVersion());
       } else if (that.getName() != null && getName() != null) {
-        return that.getName().equals(getName());
+        return Objects.equals(that.getName(), this.getName());
       }
     }
     return false;
diff --git a/src/main/java/org/caosdb/server/datatype/Value.java b/src/main/java/org/caosdb/server/datatype/Value.java
index 540e6bc52b72744c4d7c1c651c40924d1da57c6d..a2612fb37dae11953b6083f3be8132b2dd61f77f 100644
--- a/src/main/java/org/caosdb/server/datatype/Value.java
+++ b/src/main/java/org/caosdb/server/datatype/Value.java
@@ -26,4 +26,6 @@ import org.jdom2.Element;
 
 public interface Value {
   public void addToElement(Element e);
+
+  public abstract boolean equals(Value val);
 }
diff --git a/src/main/java/org/caosdb/server/transaction/WriteTransaction.java b/src/main/java/org/caosdb/server/transaction/WriteTransaction.java
index ee9aa81e49c99b15ac30a8164a4b9afc18b666f2..334e408a82ddc343ed634979dc76e0b11f33a94b 100644
--- a/src/main/java/org/caosdb/server/transaction/WriteTransaction.java
+++ b/src/main/java/org/caosdb/server/transaction/WriteTransaction.java
@@ -41,6 +41,7 @@ import org.caosdb.server.entity.DeleteEntity;
 import org.caosdb.server.entity.EntityInterface;
 import org.caosdb.server.entity.FileProperties;
 import org.caosdb.server.entity.InsertEntity;
+import org.caosdb.server.entity.Message;
 import org.caosdb.server.entity.RetrieveEntity;
 import org.caosdb.server.entity.UpdateEntity;
 import org.caosdb.server.entity.container.TransactionContainer;
@@ -400,7 +401,8 @@ public class WriteTransaction extends Transaction<WritableContainer>
     }
 
     // entity role
-    if (newEntity.hasRole()
+    if (!(newEntity instanceof Property && oldEntity instanceof Property)
+            && newEntity.hasRole()
             && oldEntity.hasRole()
             && !newEntity.getRole().equals(oldEntity.getRole())
         || newEntity.hasRole() ^ oldEntity.hasRole()) {
@@ -409,10 +411,18 @@ public class WriteTransaction extends Transaction<WritableContainer>
     }
 
     // entity value
-    if (newEntity.hasValue()
-            && oldEntity.hasValue()
-            && !newEntity.getValue().equals(oldEntity.getValue())
-        || newEntity.hasValue() ^ oldEntity.hasValue()) {
+    if (newEntity.hasValue() && oldEntity.hasValue()) {
+      try {
+        newEntity.parseValue();
+        oldEntity.parseValue();
+      } catch (Message m) {
+        // ignore, parsing is handled elsewhere
+      }
+      if (!newEntity.getValue().equals(oldEntity.getValue())) {
+        needPermissions.add(EntityPermission.UPDATE_VALUE);
+        updatetable = true;
+      }
+    } else if (newEntity.hasValue() ^ oldEntity.hasValue()) {
       needPermissions.add(EntityPermission.UPDATE_VALUE);
       updatetable = true;
     }
diff --git a/src/test/java/org/caosdb/server/transaction/UpdateTest.java b/src/test/java/org/caosdb/server/transaction/UpdateTest.java
index fb121c260a7706e806ddc73e9005ea4a440f1510..36cce88a8b4514f5ec95bac9263cb58da5857b65 100644
--- a/src/test/java/org/caosdb/server/transaction/UpdateTest.java
+++ b/src/test/java/org/caosdb/server/transaction/UpdateTest.java
@@ -25,16 +25,22 @@ package org.caosdb.server.transaction;
 import static org.caosdb.server.utils.EntityStatus.QUALIFIED;
 import static org.caosdb.server.utils.EntityStatus.VALID;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 import java.io.IOException;
 import java.security.NoSuchAlgorithmException;
+import java.util.HashSet;
 import org.caosdb.server.CaosDBException;
 import org.caosdb.server.CaosDBServer;
+import org.caosdb.server.datatype.CollectionValue;
 import org.caosdb.server.datatype.GenericValue;
+import org.caosdb.server.datatype.ReferenceValue;
 import org.caosdb.server.entity.Entity;
 import org.caosdb.server.entity.EntityInterface;
 import org.caosdb.server.entity.StatementStatus;
 import org.caosdb.server.entity.wrapper.Property;
+import org.caosdb.server.permissions.EntityPermission;
+import org.caosdb.server.permissions.Permission;
 import org.caosdb.server.utils.EntityStatus;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -176,4 +182,78 @@ public class UpdateTest {
     assertEquals(newEntity.getEntityStatus(), QUALIFIED);
     assertEquals(newProperty.getEntityStatus(), QUALIFIED);
   }
+
+  @Test
+  public void testDeriveUpdate_Collections()
+      throws NoSuchAlgorithmException, CaosDBException, IOException {
+
+    final Entity newEntity = new Entity();
+    final Property newProperty = new Property(1);
+    newProperty.setDatatype("List<Person>");
+    CollectionValue newValue = new CollectionValue();
+    newValue.add(new ReferenceValue(1234));
+    newValue.add(null);
+    newValue.add(new GenericValue(2345));
+    newValue.add(new GenericValue(3465));
+    newProperty.setValue(newValue);
+    newEntity.addProperty(newProperty);
+    newEntity.setEntityStatus(QUALIFIED);
+    newProperty.setEntityStatus(QUALIFIED);
+
+    // old entity represents the stored entity.
+    final Entity oldEntity = new Entity();
+    final Property oldProperty = new Property(1);
+    oldProperty.setDatatype("List<Person>");
+    CollectionValue oldValue = new CollectionValue();
+    // Values are shuffled but have the correct index
+    oldValue.add(1, null);
+    oldValue.add(3, new GenericValue(3465));
+    oldValue.add(2, new ReferenceValue(2345));
+    oldValue.add(0, new ReferenceValue(1234));
+    oldProperty.setValue(oldValue);
+    oldEntity.addProperty(oldProperty);
+
+    HashSet<Permission> permissions = new WriteTransaction(null).deriveUpdate(newEntity, oldEntity);
+    // Both have been identified as equals
+    assertTrue(permissions.isEmpty());
+    assertEquals(newEntity.getEntityStatus(), VALID);
+    assertEquals(newProperty.getEntityStatus(), VALID);
+
+    // NEW TEST CASE
+    newValue.add(null); // newValue has another null
+    newProperty.setValue(newValue);
+    oldEntity.addProperty(oldProperty); // Add again, because deriveUpdate throws it away
+    newEntity.setEntityStatus(QUALIFIED);
+    newProperty.setEntityStatus(QUALIFIED);
+
+    HashSet<Permission> permissions2 =
+        new WriteTransaction(null).deriveUpdate(newEntity, oldEntity);
+    HashSet<Permission> expected = new HashSet<Permission>();
+    expected.add(EntityPermission.UPDATE_ADD_PROPERTY);
+    expected.add(EntityPermission.UPDATE_REMOVE_PROPERTY);
+    assertEquals(expected, permissions2);
+    assertEquals(newEntity.getEntityStatus(), QUALIFIED);
+    assertEquals(newProperty.getEntityStatus(), QUALIFIED);
+
+    // NEW TEST CASE
+    // now change the order of oldValue
+    CollectionValue oldValue2 = new CollectionValue();
+    // Values are shuffled but have the correct index
+    oldValue2.add(0, null);
+    oldValue2.add(1, new GenericValue(3465));
+    oldValue2.add(2, new ReferenceValue(2345));
+    oldValue2.add(3, new ReferenceValue(1234));
+    oldValue2.add(4, null);
+    oldProperty.setValue(oldValue2);
+
+    oldEntity.addProperty(oldProperty); // Add again, because deriveUpdate throws it away
+    newEntity.setEntityStatus(QUALIFIED);
+    newProperty.setEntityStatus(QUALIFIED);
+
+    HashSet<Permission> permissions3 =
+        new WriteTransaction(null).deriveUpdate(newEntity, oldEntity);
+    assertEquals(expected, permissions3);
+    assertEquals(newEntity.getEntityStatus(), QUALIFIED);
+    assertEquals(newProperty.getEntityStatus(), QUALIFIED);
+  }
 }