diff --git a/src/main/java/org/caosdb/server/database/BackendTransaction.java b/src/main/java/org/caosdb/server/database/BackendTransaction.java
index 5addf3f3f3e34a8e3e6a9152b9511046fe4b6a23..05ea26c255ae5b2bd1e75df7f3fdc4d94fca5e5a 100644
--- a/src/main/java/org/caosdb/server/database/BackendTransaction.java
+++ b/src/main/java/org/caosdb/server/database/BackendTransaction.java
@@ -47,7 +47,6 @@ import org.caosdb.server.database.backend.implementation.MySQL.MySQLIsSubType;
 import org.caosdb.server.database.backend.implementation.MySQL.MySQLListRoles;
 import org.caosdb.server.database.backend.implementation.MySQL.MySQLListUsers;
 import org.caosdb.server.database.backend.implementation.MySQL.MySQLLogUserVisit;
-import org.caosdb.server.database.backend.implementation.MySQL.MySQLRegisterSubDomain;
 import org.caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveAll;
 import org.caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveAllUncheckedFiles;
 import org.caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveDatatypes;
@@ -106,7 +105,6 @@ import org.caosdb.server.database.backend.interfaces.IsSubTypeImpl;
 import org.caosdb.server.database.backend.interfaces.ListRolesImpl;
 import org.caosdb.server.database.backend.interfaces.ListUsersImpl;
 import org.caosdb.server.database.backend.interfaces.LogUserVisitImpl;
-import org.caosdb.server.database.backend.interfaces.RegisterSubDomainImpl;
 import org.caosdb.server.database.backend.interfaces.RetrieveAllImpl;
 import org.caosdb.server.database.backend.interfaces.RetrieveAllUncheckedFilesImpl;
 import org.caosdb.server.database.backend.interfaces.RetrieveDatatypesImpl;
@@ -177,7 +175,6 @@ public abstract class BackendTransaction implements Undoable {
       setImpl(IsSubTypeImpl.class, MySQLIsSubType.class);
       setImpl(UpdateSparseEntityImpl.class, MySQLUpdateSparseEntity.class);
       setImpl(RetrieveAllImpl.class, MySQLRetrieveAll.class);
-      setImpl(RegisterSubDomainImpl.class, MySQLRegisterSubDomain.class);
       setImpl(RetrieveDatatypesImpl.class, MySQLRetrieveDatatypes.class);
       setImpl(RetrieveUserImpl.class, MySQLRetrieveUser.class);
       setImpl(RetrieveParentsImpl.class, MySQLRetrieveParents.class);
diff --git a/src/main/java/org/caosdb/server/database/DatabaseUtils.java b/src/main/java/org/caosdb/server/database/DatabaseUtils.java
index 5799d23faf3435e9bb939666770aedd7a0a6c00b..6d72d96546b0df7f98d46ab9cce2c32fe0d0c15d 100644
--- a/src/main/java/org/caosdb/server/database/DatabaseUtils.java
+++ b/src/main/java/org/caosdb/server/database/DatabaseUtils.java
@@ -27,6 +27,7 @@ import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.util.AbstractMap.SimpleEntry;
 import java.util.ArrayList;
+import java.util.Deque;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedList;
@@ -44,9 +45,7 @@ import org.caosdb.server.entity.EntityID;
 import org.caosdb.server.entity.EntityInterface;
 import org.caosdb.server.entity.Message;
 import org.caosdb.server.entity.RetrieveEntity;
-import org.caosdb.server.entity.Role;
 import org.caosdb.server.entity.StatementStatus;
-import org.caosdb.server.entity.wrapper.Domain;
 import org.caosdb.server.entity.wrapper.Parent;
 import org.caosdb.server.entity.wrapper.Property;
 
@@ -63,39 +62,33 @@ public class DatabaseUtils {
     }
   }
 
-  private static Domain makeReplacement(final EntityInterface p) {
-    // add a new helper domain.
-    final Domain d =
-        new Domain(p.getProperties(), p.getDatatype(), p.getValue(), p.getStatementStatus());
-    d.setDescOverride(p.isDescOverride());
-    d.setNameOverride(p.isNameOverride());
-    d.setDatatypeOverride(p.isDatatypeOverride());
-    d.setName(p.getName());
-    d.setDescription(p.getDescription());
-    p.setReplacement(d);
-    return d;
-  }
-
-  public static void deriveStage1Inserts(
-      final List<EntityInterface> stage1Inserts, final EntityInterface e) {
+  public static int deriveStage1Inserts(
+      final List<Property> stage1Inserts, final EntityInterface e) {
     // entity value
     if (e.hasValue()) {
       final Property p = new Property(e);
       p.setStatementStatus(StatementStatus.FIX);
-      p.setPIdx(0);
       p.setDatatype(e.getDatatype());
       p.setValue(e.getValue());
+      p.setPIdx(0);
       processPropertiesStage1(stage1Inserts, p, e);
     }
 
-    for (final EntityInterface p : e.getProperties()) {
+    for (final Property p : e.getProperties()) {
       processPropertiesStage1(stage1Inserts, p, e);
     }
+    int replacementCount = 0;
+    for (EntityInterface pp : stage1Inserts) {
+      if (pp instanceof Replacement) {
+        replacementCount++;
+      }
+    }
+    return replacementCount;
   }
 
   private static void processPropertiesStage1(
-      final List<EntityInterface> stage1Inserts, final EntityInterface p, final EntityInterface e) {
-    stage1Inserts.add(p);
+      final List<Property> stage1Inserts, final Property p, final EntityInterface e) {
+
     if (!p.isDescOverride()
         && !p.isNameOverride()
         && !p.isDatatypeOverride()
@@ -105,25 +98,40 @@ public class DatabaseUtils {
       // setReplacement(null) because there is a corner case (related to the inheritance of
       // properties) where there is a replacement present which belongs to the parent entity, see
       // https://gitlab.com/caosdb/caosdb-server/-/issues/216.
-      p.setReplacement(null);
+      stage1Inserts.add(p);
     } else {
-      stage1Inserts.add(makeReplacement(p));
+      Replacement r = new Replacement(p);
+      stage1Inserts.add(r);
+      stage1Inserts.add(r.replacement);
     }
     processSubPropertiesStage1(stage1Inserts, p);
   }
 
-  public static int deriveStage2Inserts(
-      final List<EntityInterface> stage2Inserts, final List<EntityInterface> stage1Inserts) {
-    int domainCount = 0;
-    for (final EntityInterface p : stage1Inserts) {
-      if (p.hasRole() && p.getRole() == Role.Domain) {
-        domainCount++;
-      }
-      if (!p.hasReplacement() && p.hasProperties()) {
-        stage2Inserts.addAll(p.getProperties());
+  public static void deriveStage2Inserts(
+      final List<Property> stage2Inserts,
+      final List<Property> stage1Inserts,
+      Deque<EntityID> replacementIds,
+      EntityInterface entity) {
+    for (final Property p : stage1Inserts) {
+      if (p instanceof Replacement) {
+
+        EntityID replacementId = replacementIds.pop();
+        ((Replacement) p).setReplacementId(replacementId);
+
+        if (p.hasProperties()) {
+          for (Property subP : p.getProperties()) {
+            subP.setDomain(p);
+            stage2Inserts.add(subP);
+          }
+        }
+      } else {
+        if (p.hasProperties()) {
+          for (Property subP : p.getProperties()) {
+            stage2Inserts.add(subP);
+          }
+        }
       }
     }
-    return domainCount;
   }
 
   private static boolean hasUniquePropertyId(final EntityInterface p, final EntityInterface e) {
@@ -137,10 +145,10 @@ public class DatabaseUtils {
   }
 
   private static void processSubPropertiesStage1(
-      final List<EntityInterface> stage1Inserts, final EntityInterface p) {
-    for (final EntityInterface subP : p.getProperties()) {
+      final List<Property> stage1Inserts, final EntityInterface p) {
+    for (final Property subP : p.getProperties()) {
       if (subP.hasProperties()) {
-        stage1Inserts.add(makeReplacement(subP));
+        stage1Inserts.add(new Replacement(subP));
         processSubPropertiesStage1(stage1Inserts, subP);
       }
     }
diff --git a/src/main/java/org/caosdb/server/database/Replacement.java b/src/main/java/org/caosdb/server/database/Replacement.java
new file mode 100644
index 0000000000000000000000000000000000000000..8606d51bcf903eccea77132aaed9e6a7541da71e
--- /dev/null
+++ b/src/main/java/org/caosdb/server/database/Replacement.java
@@ -0,0 +1,41 @@
+package org.caosdb.server.database;
+
+import org.caosdb.server.datatype.ReferenceValue;
+import org.caosdb.server.entity.EntityID;
+import org.caosdb.server.entity.RetrieveEntity;
+import org.caosdb.server.entity.StatementStatus;
+import org.caosdb.server.entity.wrapper.Property;
+
+public class Replacement extends Property {
+
+  public Property replacement;
+  public EntityID replacementId;
+
+  @Override
+  public EntityID getId() {
+    return replacementId;
+  }
+
+  public void setReplacementId(EntityID id) {
+    replacementId.link(id);
+  }
+
+  public Replacement(Property p) {
+    super(p);
+    replacementId = new EntityID();
+    replacement = new Property(new RetrieveEntity());
+
+    replacement.setDomain(p.getDomainEntity());
+    //    replacement.setDatatypeOverride(p.isDatatypeOverride());
+    //    replacement.setDatatype(p.getDatatype());
+    //    replacement.setNameOverride(p.isNameOverride());
+    //    replacement.setName(p.getName());
+    //    replacement.setDescOverride(p.isDescOverride());
+    //    replacement.setDescription(p.getDescription());
+
+    replacement.setId(replacementId);
+    replacement.setStatementStatus(StatementStatus.REPLACEMENT);
+    replacement.setValue(new ReferenceValue(p.getId()));
+    replacement.setPIdx(0);
+  }
+}
diff --git a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLInsertEntityProperties.java b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLInsertEntityProperties.java
index 7c3c5a33e160f3da6a8c2b89fe0487e0317c99da..5c9ca6f9bbda94f63e93054c9b5a508de0b5d4e7 100644
--- a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLInsertEntityProperties.java
+++ b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLInsertEntityProperties.java
@@ -25,15 +25,30 @@ package org.caosdb.server.database.backend.implementation.MySQL;
 import static java.sql.Types.BIGINT;
 
 import java.sql.PreparedStatement;
+import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.SQLIntegrityConstraintViolationException;
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import org.caosdb.server.database.DatabaseUtils;
 import org.caosdb.server.database.access.Access;
 import org.caosdb.server.database.backend.interfaces.InsertEntityPropertiesImpl;
 import org.caosdb.server.database.exceptions.IntegrityException;
 import org.caosdb.server.database.exceptions.TransactionException;
 import org.caosdb.server.database.proto.FlatProperty;
+import org.caosdb.server.datatype.AbstractCollectionDatatype;
 import org.caosdb.server.datatype.AbstractDatatype.Table;
+import org.caosdb.server.datatype.CollectionValue;
+import org.caosdb.server.datatype.IndexedSingleValue;
+import org.caosdb.server.datatype.ReferenceValue;
+import org.caosdb.server.datatype.SingleValue;
 import org.caosdb.server.entity.EntityID;
+import org.caosdb.server.entity.EntityInterface;
+import org.caosdb.server.entity.StatementStatus;
+import org.caosdb.server.entity.wrapper.Property;
 
 public class MySQLInsertEntityProperties extends MySQLTransaction
     implements InsertEntityPropertiesImpl {
@@ -46,7 +61,27 @@ public class MySQLInsertEntityProperties extends MySQLTransaction
   }
 
   @Override
-  public void execute(
+  public void execute(EntityInterface entity) {
+    final List<Property> stage1Inserts = new LinkedList<>();
+    final List<Property> stage2Inserts = new LinkedList<>();
+
+    final int domainCount = DatabaseUtils.deriveStage1Inserts(stage1Inserts, entity);
+
+    try {
+      final Deque<EntityID> replacementIds = registerReplacementId(domainCount);
+
+      DatabaseUtils.deriveStage2Inserts(stage2Inserts, stage1Inserts, replacementIds, entity);
+
+      insertStages(stage1Inserts, entity.getDomain(), entity.getId());
+      insertStages(stage2Inserts, entity.getId(), null);
+    } catch (final SQLIntegrityConstraintViolationException exc) {
+      throw new IntegrityException(exc);
+    } catch (SQLException | ConnectionException e) {
+      throw new TransactionException(e);
+    }
+  }
+
+  private void insertFlatProperty(
       final EntityID domain,
       final EntityID entity,
       final FlatProperty fp,
@@ -76,10 +111,114 @@ public class MySQLInsertEntityProperties extends MySQLTransaction
       stmt.execute();
     } catch (final SQLIntegrityConstraintViolationException exc) {
       throw new IntegrityException(exc);
-    } catch (final SQLException exc) {
-      throw new TransactionException(exc);
-    } catch (final ConnectionException exc) {
+    } catch (final SQLException | ConnectionException exc) {
       throw new TransactionException(exc);
     }
   }
+
+  private void insertStages(
+      final List<Property> stage1Inserts, final EntityID domain, final EntityID entity)
+      throws TransactionException {
+
+    for (final Property property : stage1Inserts) {
+
+      // prepare flat property
+      final FlatProperty fp = new FlatProperty();
+      Table table = Table.null_data;
+      Long unit_sig = null;
+      fp.id = property.getId().toInteger();
+      fp.idx = property.getPIdx();
+      fp.status = property.getStatementStatus().name();
+
+      if (property.getStatementStatus() == StatementStatus.REPLACEMENT) {
+        table = Table.reference_data;
+        fp.value = fp.id.toString();
+        fp.id = ((ReferenceValue) property.getValue()).getId().toInteger();
+      } else {
+
+        if (property.hasUnit()) {
+          unit_sig = property.getUnit().getSignature();
+        }
+        if (property.hasValue()) {
+          if (property.getValue() instanceof CollectionValue) {
+            // insert collection of values
+            final CollectionValue v = (CollectionValue) property.getValue();
+            final Iterator<IndexedSingleValue> iterator = v.iterator();
+            final SingleValue firstValue = iterator.next();
+
+            // insert 2nd to nth item
+            for (int i = 1; i < v.size(); i++) {
+              final SingleValue vi = iterator.next();
+              fp.idx = i;
+              if (vi == null) {
+                fp.value = null;
+                table = Table.null_data;
+              } else {
+                fp.value = vi.toDatabaseString();
+                table = vi.getTable();
+              }
+              insertFlatProperty(
+                  domain, entity != null ? entity : property.getDomain(), fp, table, unit_sig);
+            }
+
+            // insert first item
+            fp.idx = 0;
+            if (firstValue == null) {
+              fp.value = null;
+              table = Table.null_data;
+            } else {
+              fp.value = firstValue.toDatabaseString();
+              table = firstValue.getTable();
+            }
+
+          } else {
+            // insert single value
+            fp.value = ((SingleValue) property.getValue()).toDatabaseString();
+            if (property instanceof Property && ((Property) property).isName()) {
+              table = Table.name_data;
+            } else {
+              table = ((SingleValue) property.getValue()).getTable();
+            }
+          }
+        }
+        if (property.isNameOverride()) {
+          fp.name = property.getName();
+        }
+        if (property.isDescOverride()) {
+          fp.desc = property.getDescription();
+        }
+        if (property.isDatatypeOverride()) {
+          if (property.getDatatype() instanceof AbstractCollectionDatatype) {
+            fp.type =
+                ((AbstractCollectionDatatype) property.getDatatype())
+                    .getDatatype()
+                    .getId()
+                    .toString();
+            fp.collection =
+                ((AbstractCollectionDatatype) property.getDatatype()).getCollectionName();
+          } else {
+            fp.type = property.getDatatype().getId().toString();
+          }
+        }
+      }
+
+      insertFlatProperty(
+          domain, entity != null ? entity : property.getDomain(), fp, table, unit_sig);
+    }
+  }
+
+  public static final String STMT_REGISTER_SUBDOMAIN = "call registerSubdomain(?)";
+
+  public Deque<EntityID> registerReplacementId(final int domainCount)
+      throws SQLException, ConnectionException {
+    final PreparedStatement stmt = prepareStatement(STMT_REGISTER_SUBDOMAIN);
+    stmt.setInt(1, domainCount);
+    try (final ResultSet rs = stmt.executeQuery()) {
+      final Deque<EntityID> ret = new ArrayDeque<>();
+      while (rs.next()) {
+        ret.add(new EntityID(rs.getInt(1)));
+      }
+      return ret;
+    }
+  }
 }
diff --git a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRegisterSubDomain.java b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRegisterSubDomain.java
deleted file mode 100644
index 1e14600e71023dff544a09910fabe0dc8b17ca42..0000000000000000000000000000000000000000
--- a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRegisterSubDomain.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * ** header v3.0
- * This file is a part of the CaosDB Project.
- *
- * Copyright (C) 2018 Research Group Biomedical Physics,
- * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * ** end header
- */
-package org.caosdb.server.database.backend.implementation.MySQL;
-
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.ArrayDeque;
-import java.util.Deque;
-import org.caosdb.server.database.access.Access;
-import org.caosdb.server.database.backend.interfaces.RegisterSubDomainImpl;
-import org.caosdb.server.database.exceptions.TransactionException;
-import org.caosdb.server.entity.EntityID;
-
-public class MySQLRegisterSubDomain extends MySQLTransaction implements RegisterSubDomainImpl {
-
-  public MySQLRegisterSubDomain(final Access access) {
-    super(access);
-  }
-
-  public static final String STMT_REGISTER_SUBDOMAIN = "call registerSubdomain(?)";
-
-  @Override
-  public Deque<EntityID> execute(final int domainCount) throws TransactionException {
-    try {
-      final PreparedStatement stmt = prepareStatement(STMT_REGISTER_SUBDOMAIN);
-      stmt.setInt(1, domainCount);
-      final ResultSet rs = stmt.executeQuery();
-      try {
-        final Deque<EntityID> ret = new ArrayDeque<>();
-        while (rs.next()) {
-          ret.add(new EntityID(rs.getInt(1)));
-        }
-        return ret;
-      } finally {
-        rs.close();
-      }
-    } catch (final SQLException e) {
-      throw new TransactionException(e);
-    } catch (final ConnectionException e) {
-      throw new TransactionException(e);
-    }
-  }
-}
diff --git a/src/main/java/org/caosdb/server/database/backend/interfaces/InsertEntityPropertiesImpl.java b/src/main/java/org/caosdb/server/database/backend/interfaces/InsertEntityPropertiesImpl.java
index 2406d4895487bdec5f271b41bf46207a48c7375d..f17643fd6ff0e980aef122a318fd9fc2668e2b79 100644
--- a/src/main/java/org/caosdb/server/database/backend/interfaces/InsertEntityPropertiesImpl.java
+++ b/src/main/java/org/caosdb/server/database/backend/interfaces/InsertEntityPropertiesImpl.java
@@ -22,15 +22,10 @@
  */
 package org.caosdb.server.database.backend.interfaces;
 
-import org.caosdb.server.database.exceptions.TransactionException;
-import org.caosdb.server.database.proto.FlatProperty;
-import org.caosdb.server.datatype.AbstractDatatype.Table;
-import org.caosdb.server.entity.EntityID;
+import org.caosdb.server.entity.EntityInterface;
 import org.caosdb.server.utils.Undoable;
 
 public interface InsertEntityPropertiesImpl extends BackendTransactionImpl, Undoable {
 
-  public abstract void execute(
-      EntityID domain, EntityID entity, FlatProperty fp, Table table, Long unit_sig)
-      throws TransactionException;
+  public abstract void execute(EntityInterface entity);
 }
diff --git a/src/main/java/org/caosdb/server/database/backend/interfaces/RegisterSubDomainImpl.java b/src/main/java/org/caosdb/server/database/backend/interfaces/RegisterSubDomainImpl.java
deleted file mode 100644
index 87ea0c85db6a698f49c103506b520342deff2fb0..0000000000000000000000000000000000000000
--- a/src/main/java/org/caosdb/server/database/backend/interfaces/RegisterSubDomainImpl.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * ** header v3.0
- * This file is a part of the CaosDB Project.
- *
- * Copyright (C) 2018 Research Group Biomedical Physics,
- * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * ** end header
- */
-package org.caosdb.server.database.backend.interfaces;
-
-import java.util.Deque;
-import org.caosdb.server.database.exceptions.TransactionException;
-import org.caosdb.server.entity.EntityID;
-
-public interface RegisterSubDomainImpl extends BackendTransactionImpl {
-
-  public abstract Deque<EntityID> execute(int domainCount) throws TransactionException;
-}
diff --git a/src/main/java/org/caosdb/server/database/backend/transaction/InsertEntityProperties.java b/src/main/java/org/caosdb/server/database/backend/transaction/InsertEntityProperties.java
index f9af6a482efaccf896a1a85fc65d0e1217bd6a53..8de8afc084ae16dea370a519a4fde3524fa8c7c9 100644
--- a/src/main/java/org/caosdb/server/database/backend/transaction/InsertEntityProperties.java
+++ b/src/main/java/org/caosdb/server/database/backend/transaction/InsertEntityProperties.java
@@ -22,25 +22,10 @@
  */
 package org.caosdb.server.database.backend.transaction;
 
-import java.util.ArrayList;
-import java.util.Deque;
-import java.util.Iterator;
-import java.util.List;
 import org.caosdb.server.database.BackendTransaction;
-import org.caosdb.server.database.DatabaseUtils;
 import org.caosdb.server.database.backend.interfaces.InsertEntityPropertiesImpl;
 import org.caosdb.server.database.exceptions.TransactionException;
-import org.caosdb.server.database.proto.FlatProperty;
-import org.caosdb.server.datatype.AbstractCollectionDatatype;
-import org.caosdb.server.datatype.AbstractDatatype.Table;
-import org.caosdb.server.datatype.CollectionValue;
-import org.caosdb.server.datatype.IndexedSingleValue;
-import org.caosdb.server.datatype.SingleValue;
-import org.caosdb.server.entity.EntityID;
 import org.caosdb.server.entity.EntityInterface;
-import org.caosdb.server.entity.Role;
-import org.caosdb.server.entity.StatementStatus;
-import org.caosdb.server.entity.wrapper.Property;
 
 public class InsertEntityProperties extends BackendTransaction {
 
@@ -54,126 +39,6 @@ public class InsertEntityProperties extends BackendTransaction {
   public void execute() throws TransactionException {
 
     final InsertEntityPropertiesImpl t = getImplementation(InsertEntityPropertiesImpl.class);
-
-    final ArrayList<EntityInterface> stage1Inserts = new ArrayList<EntityInterface>();
-    final ArrayList<EntityInterface> stage2Inserts = new ArrayList<EntityInterface>();
-
-    DatabaseUtils.deriveStage1Inserts(stage1Inserts, this.entity);
-
-    final int domainCount = DatabaseUtils.deriveStage2Inserts(stage2Inserts, stage1Inserts);
-
-    final Deque<EntityID> domainIds = execute(new RegisterSubDomain(domainCount)).getDomains();
-
-    insertStages(t, domainIds, stage1Inserts, this.entity.getDomain(), this.entity.getId());
-    insertStages(t, domainIds, stage2Inserts, this.entity.getId(), null);
-  }
-
-  private void insertStages(
-      final InsertEntityPropertiesImpl t,
-      final Deque<EntityID> domainIds,
-      final List<EntityInterface> stage1Inserts,
-      final EntityID domain,
-      final EntityID entity)
-      throws TransactionException {
-
-    for (final EntityInterface property : stage1Inserts) {
-      if (property.hasRole() && property.getRole() == Role.Domain && !property.hasId()) {
-        property.setId(domainIds.removeFirst());
-      }
-      int pIdx;
-      if (property instanceof Property) {
-        // this is a normal property
-        pIdx = ((Property) property).getPIdx();
-      } else {
-        // this is a replacement
-        pIdx = 0;
-      }
-
-      // prepare flat property
-      final FlatProperty fp = new FlatProperty();
-      Table table = Table.null_data;
-      Long unit_sig = null;
-      fp.id = property.getId().toInteger();
-      fp.idx = pIdx;
-
-      if (property.hasReplacement()) {
-        if (!property.getReplacement().hasId()) {
-          property.getReplacement().setId(domainIds.removeFirst());
-        }
-
-        fp.value = property.getReplacement().getId().toString();
-        fp.status = StatementStatus.REPLACEMENT.toString();
-
-        table = Table.reference_data;
-      } else {
-        if (property.hasUnit()) {
-          unit_sig = property.getUnit().getSignature();
-        }
-        fp.status = property.getStatementStatus().toString();
-        if (property.hasValue()) {
-          if (property.getValue() instanceof CollectionValue) {
-            // insert collection of values
-            final CollectionValue v = (CollectionValue) property.getValue();
-            final Iterator<IndexedSingleValue> iterator = v.iterator();
-            final SingleValue firstValue = iterator.next();
-
-            // insert 2nd to nth item
-            for (int i = 1; i < v.size(); i++) {
-              final SingleValue vi = iterator.next();
-              fp.idx = i;
-              if (vi == null) {
-                fp.value = null;
-                table = Table.null_data;
-              } else {
-                fp.value = vi.toDatabaseString();
-                table = vi.getTable();
-              }
-              t.execute(
-                  domain, entity != null ? entity : property.getDomain(), fp, table, unit_sig);
-            }
-
-            // insert first item
-            fp.idx = 0;
-            if (firstValue == null) {
-              fp.value = null;
-              table = Table.null_data;
-            } else {
-              fp.value = firstValue.toDatabaseString();
-              table = firstValue.getTable();
-            }
-
-          } else {
-            // insert single value
-            fp.value = ((SingleValue) property.getValue()).toDatabaseString();
-            if (property instanceof Property && ((Property) property).isName()) {
-              table = Table.name_data;
-            } else {
-              table = ((SingleValue) property.getValue()).getTable();
-            }
-          }
-        }
-        if (property.isNameOverride()) {
-          fp.name = property.getName();
-        }
-        if (property.isDescOverride()) {
-          fp.desc = property.getDescription();
-        }
-        if (property.isDatatypeOverride()) {
-          if (property.getDatatype() instanceof AbstractCollectionDatatype) {
-            fp.type =
-                ((AbstractCollectionDatatype) property.getDatatype())
-                    .getDatatype()
-                    .getId()
-                    .toString();
-            fp.collection =
-                ((AbstractCollectionDatatype) property.getDatatype()).getCollectionName();
-          } else {
-            fp.type = property.getDatatype().getId().toString();
-          }
-        }
-      }
-
-      t.execute(domain, entity != null ? entity : property.getDomain(), fp, table, unit_sig);
-    }
+    t.execute(this.entity);
   }
 }
diff --git a/src/main/java/org/caosdb/server/database/backend/transaction/InsertEntityTransaction.java b/src/main/java/org/caosdb/server/database/backend/transaction/InsertEntityTransaction.java
index 5871c97e8ff172fe58b37627cc93824e96c7b32e..2846fa64d56ea696d4ecb0412a88de449d0483a1 100644
--- a/src/main/java/org/caosdb/server/database/backend/transaction/InsertEntityTransaction.java
+++ b/src/main/java/org/caosdb/server/database/backend/transaction/InsertEntityTransaction.java
@@ -54,7 +54,9 @@ public class InsertEntityTransaction extends BackendTransaction {
         if (newEntity.hasFileProperties()) {
           execute(new InsertFile(newEntity));
         }
-        execute(new InsertEntityProperties(newEntity));
+        if (newEntity.hasProperties() || newEntity.hasValue()) {
+          execute(new InsertEntityProperties(newEntity));
+        }
         execute(new InsertParents(newEntity));
 
         if (newEntity.getEntityStatus() == EntityStatus.QUALIFIED) {
diff --git a/src/main/java/org/caosdb/server/database/backend/transaction/RegisterSubDomain.java b/src/main/java/org/caosdb/server/database/backend/transaction/RegisterSubDomain.java
deleted file mode 100644
index 0321a621a82a9ae2841d31b55b05a46743f963bd..0000000000000000000000000000000000000000
--- a/src/main/java/org/caosdb/server/database/backend/transaction/RegisterSubDomain.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * ** header v3.0
- * This file is a part of the CaosDB Project.
- *
- * Copyright (C) 2018 Research Group Biomedical Physics,
- * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * ** end header
- */
-package org.caosdb.server.database.backend.transaction;
-
-import java.util.Deque;
-import org.caosdb.server.database.BackendTransaction;
-import org.caosdb.server.database.backend.interfaces.RegisterSubDomainImpl;
-import org.caosdb.server.database.exceptions.TransactionException;
-import org.caosdb.server.entity.EntityID;
-
-public class RegisterSubDomain extends BackendTransaction {
-
-  private final int domainCount;
-  private Deque<EntityID> list;
-
-  public RegisterSubDomain(final int domainCount) {
-    this.domainCount = domainCount;
-  }
-
-  @Override
-  public void execute() throws TransactionException {
-    final RegisterSubDomainImpl t = getImplementation(RegisterSubDomainImpl.class);
-    this.list = t.execute(this.domainCount);
-  }
-
-  public Deque<EntityID> getDomains() {
-    return this.list;
-  }
-}
diff --git a/src/main/java/org/caosdb/server/database/proto/FlatProperty.java b/src/main/java/org/caosdb/server/database/proto/FlatProperty.java
index b92d3def38d26f0f5f6cd6a0455d472b8f4f3ccb..b4f0f62a2e5f596219180140a4905f5b20abe2d3 100644
--- a/src/main/java/org/caosdb/server/database/proto/FlatProperty.java
+++ b/src/main/java/org/caosdb/server/database/proto/FlatProperty.java
@@ -26,6 +26,19 @@ import java.io.Serializable;
 
 public class FlatProperty implements Serializable {
 
+  public FlatProperty() {}
+
+  public FlatProperty(FlatProperty fp) {
+    id = fp.id;
+    value = fp.value;
+    status = fp.status;
+    idx = fp.idx;
+    name = fp.name;
+    desc = fp.desc;
+    type = fp.type;
+    collection = fp.collection;
+  }
+
   private static final long serialVersionUID = 6039288034435124195L;
   public Integer id = null;
   public String value = null;
diff --git a/src/main/java/org/caosdb/server/database/proto/ProtoProperty.java b/src/main/java/org/caosdb/server/database/proto/ProtoProperty.java
index 898565aca9e7e346f76ff60b9fc45ea0b1547331..c6cdbd5495dfbd596fe5ef564b557257706835cb 100644
--- a/src/main/java/org/caosdb/server/database/proto/ProtoProperty.java
+++ b/src/main/java/org/caosdb/server/database/proto/ProtoProperty.java
@@ -26,21 +26,14 @@ import java.io.Serializable;
 import java.util.List;
 
 public class ProtoProperty extends FlatProperty implements Serializable {
+  private static final long serialVersionUID = 7731301985162924975L;
 
   public ProtoProperty(FlatProperty fp) {
-    id = fp.id;
-    value = fp.value;
-    status = fp.status;
-    idx = fp.idx;
-    name = fp.name;
-    desc = fp.desc;
-    type = fp.type;
-    collection = fp.collection;
+    super(fp);
   }
 
   public ProtoProperty() {}
 
-  private static final long serialVersionUID = 7731301985162924975L;
   public List<ProtoProperty> subProperties = null;
   public List<Object> collValues = null;
 }
diff --git a/src/test/java/org/caosdb/server/database/InsertTest.java b/src/test/java/org/caosdb/server/database/InsertTest.java
index 59aa6f55084edacc93ad371e5f55b16e72a940f5..e385d6cb2038496b5c90715347cd34e88b8c60c8 100644
--- a/src/test/java/org/caosdb/server/database/InsertTest.java
+++ b/src/test/java/org/caosdb/server/database/InsertTest.java
@@ -28,13 +28,15 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
+import java.util.ArrayDeque;
+import java.util.Deque;
 import java.util.LinkedList;
 import org.caosdb.server.datatype.CollectionValue;
 import org.caosdb.server.datatype.GenericValue;
+import org.caosdb.server.datatype.ReferenceValue;
 import org.caosdb.server.datatype.SingleValue;
 import org.caosdb.server.entity.Entity;
 import org.caosdb.server.entity.EntityID;
-import org.caosdb.server.entity.EntityInterface;
 import org.caosdb.server.entity.InsertEntity;
 import org.caosdb.server.entity.RetrieveEntity;
 import org.caosdb.server.entity.Role;
@@ -44,6 +46,14 @@ import org.junit.jupiter.api.Test;
 
 public class InsertTest {
 
+  private Deque<EntityID> registerReplacementIds(int count) {
+    Deque<EntityID> replacementIds = new ArrayDeque<>();
+    for (int i = 1; i < count + 1; i++) {
+      replacementIds.add(new EntityID(-i));
+    }
+    return replacementIds;
+  }
+
   /**
    * Record with very deep property tree.
    *
@@ -122,85 +132,67 @@ public class InsertTest {
     p10.setStatementStatus(StatementStatus.OBLIGATORY);
     p9.addProperty(p10);
 
-    final LinkedList<EntityInterface> stage1Inserts = new LinkedList<EntityInterface>();
-    final LinkedList<EntityInterface> stage2Inserts = new LinkedList<EntityInterface>();
+    final LinkedList<Property> stage1Inserts = new LinkedList<>();
+    final LinkedList<Property> stage2Inserts = new LinkedList<>();
 
-    deriveStage1Inserts(stage1Inserts, r);
+    int replacementCount = deriveStage1Inserts(stage1Inserts, r);
+    assertEquals(3, replacementCount);
+
+    deriveStage2Inserts(stage2Inserts, stage1Inserts, registerReplacementIds(replacementCount), r);
 
     assertEquals(7, stage1Inserts.size());
-    assertEquals(Role.Property, stage1Inserts.get(0).getRole());
-    assertEquals(new EntityID(1), stage1Inserts.get(0).getId());
+    assertFalse(stage1Inserts.get(0) instanceof Replacement);
+    assertEquals(1, stage1Inserts.get(0).getId().toInteger());
     assertEquals("V1", ((SingleValue) stage1Inserts.get(0).getValue()).toDatabaseString());
-    assertFalse(stage1Inserts.get(0).hasReplacement());
 
-    assertEquals(Role.Property, stage1Inserts.get(1).getRole());
-    assertEquals(new EntityID(2), stage1Inserts.get(1).getId());
+    assertFalse(stage1Inserts.get(1) instanceof Replacement);
+    assertEquals(2, stage1Inserts.get(1).getId().toInteger());
     assertEquals("V2", ((SingleValue) stage1Inserts.get(1).getValue()).toDatabaseString());
-    assertFalse(stage1Inserts.get(1).hasReplacement());
 
-    assertEquals(Role.Property, stage1Inserts.get(2).getRole());
-    assertEquals(new EntityID(4), stage1Inserts.get(2).getId());
+    assertFalse(stage1Inserts.get(2) instanceof Replacement);
+    assertEquals(4, stage1Inserts.get(2).getId().toInteger());
     assertEquals("V4", ((SingleValue) stage1Inserts.get(2).getValue()).toDatabaseString());
-    assertFalse(stage1Inserts.get(2).hasReplacement());
 
-    assertEquals(Role.Domain, stage1Inserts.get(3).getRole());
+    assertTrue(stage1Inserts.get(3) instanceof Replacement);
+    assertEquals(5, stage1Inserts.get(3).getId().toInteger());
     assertEquals("V5", ((SingleValue) stage1Inserts.get(3).getValue()).toDatabaseString());
-    assertFalse(stage1Inserts.get(3).hasReplacement());
 
-    assertEquals(Role.Property, stage1Inserts.get(4).getRole());
-    assertEquals(new EntityID(7), stage1Inserts.get(4).getId());
+    assertFalse(stage1Inserts.get(4) instanceof Replacement);
+    assertEquals(7, stage1Inserts.get(4).getId().toInteger());
     assertEquals("V7", ((SingleValue) stage1Inserts.get(4).getValue()).toDatabaseString());
-    assertFalse(stage1Inserts.get(4).hasReplacement());
 
-    assertEquals(Role.Domain, stage1Inserts.get(5).getRole());
+    assertTrue(stage1Inserts.get(5) instanceof Replacement);
+    assertEquals(8, stage1Inserts.get(5).getId().toInteger());
     assertEquals("V8", ((SingleValue) stage1Inserts.get(5).getValue()).toDatabaseString());
-    assertFalse(stage1Inserts.get(5).hasReplacement());
 
-    assertEquals(Role.Domain, stage1Inserts.get(6).getRole());
+    assertTrue(stage1Inserts.get(6) instanceof Replacement);
+    assertEquals(9, stage1Inserts.get(6).getId().toInteger());
     assertEquals("V9", ((SingleValue) stage1Inserts.get(6).getValue()).toDatabaseString());
-    assertFalse(stage1Inserts.get(6).hasReplacement());
-
-    deriveStage2Inserts(stage2Inserts, stage1Inserts);
 
     assertEquals(6, stage2Inserts.size());
-    assertEquals(Role.Property, stage2Inserts.get(0).getRole());
     assertEquals(new EntityID(3), stage2Inserts.get(0).getId());
     assertEquals("V3", ((SingleValue) stage2Inserts.get(0).getValue()).toDatabaseString());
     assertEquals(new EntityID(2), stage2Inserts.get(0).getDomain());
-    assertFalse(stage2Inserts.get(0).hasReplacement());
 
-    assertEquals(Role.Property, stage2Inserts.get(1).getRole());
     assertEquals(new EntityID(5), stage2Inserts.get(1).getId());
     assertEquals("V5", ((SingleValue) stage2Inserts.get(1).getValue()).toDatabaseString());
-    assertTrue(stage2Inserts.get(1).hasReplacement());
     assertEquals(new EntityID(4), stage2Inserts.get(1).getDomain());
-    assertEquals(stage1Inserts.get(3), stage2Inserts.get(1).getReplacement());
 
-    assertEquals(Role.Property, stage2Inserts.get(2).getRole());
     assertEquals(new EntityID(6), stage2Inserts.get(2).getId());
     assertEquals("V6", ((SingleValue) stage2Inserts.get(2).getValue()).toDatabaseString());
-    assertEquals(new EntityID(5), stage2Inserts.get(2).getDomain());
-    assertFalse(stage2Inserts.get(2).hasReplacement());
+    assertEquals(new EntityID(-1), stage2Inserts.get(2).getDomain());
 
-    assertEquals(Role.Property, stage2Inserts.get(3).getRole());
     assertEquals(new EntityID(8), stage2Inserts.get(3).getId());
     assertEquals("V8", ((SingleValue) stage2Inserts.get(3).getValue()).toDatabaseString());
-    assertTrue(stage2Inserts.get(3).hasReplacement());
     assertEquals(new EntityID(7), stage2Inserts.get(3).getDomain());
-    assertEquals(stage1Inserts.get(5), stage2Inserts.get(3).getReplacement());
 
-    assertEquals(Role.Property, stage2Inserts.get(4).getRole());
     assertEquals(new EntityID(9), stage2Inserts.get(4).getId());
     assertEquals("V9", ((SingleValue) stage2Inserts.get(4).getValue()).toDatabaseString());
-    assertTrue(stage2Inserts.get(4).hasReplacement());
-    assertEquals(new EntityID(8), stage2Inserts.get(4).getDomain());
-    assertEquals(stage1Inserts.get(6), stage2Inserts.get(4).getReplacement());
+    assertEquals(new EntityID(-2), stage2Inserts.get(4).getDomain());
 
-    assertEquals(Role.Property, stage2Inserts.get(5).getRole());
     assertEquals(new EntityID(10), stage2Inserts.get(5).getId());
     assertEquals("V10", ((SingleValue) stage2Inserts.get(5).getValue()).toDatabaseString());
-    assertEquals(new EntityID(9), stage2Inserts.get(5).getDomain());
-    assertFalse(stage2Inserts.get(5).hasReplacement());
+    assertEquals(new EntityID(-3), stage2Inserts.get(5).getDomain());
   }
 
   /**
@@ -233,34 +225,31 @@ public class InsertTest {
     subp.setStatementStatus(StatementStatus.FIX);
     p2.addProperty(subp);
 
-    final LinkedList<EntityInterface> stage1Inserts = new LinkedList<EntityInterface>();
-    final LinkedList<EntityInterface> stage2Inserts = new LinkedList<EntityInterface>();
+    final LinkedList<Property> stage1Inserts = new LinkedList<>();
+    final LinkedList<Property> stage2Inserts = new LinkedList<>();
 
-    deriveStage1Inserts(stage1Inserts, r);
+    int replacementCount = deriveStage1Inserts(stage1Inserts, r);
+    deriveStage2Inserts(stage2Inserts, stage1Inserts, registerReplacementIds(replacementCount), r);
 
     assertEquals(3, stage1Inserts.size());
-    assertEquals(Role.Property, stage1Inserts.get(0).getRole());
+
+    assertFalse(stage1Inserts.get(0) instanceof Replacement);
     assertEquals(new EntityID(1), stage1Inserts.get(0).getId());
     assertEquals("V1-1", ((SingleValue) stage1Inserts.get(0).getValue()).toDatabaseString());
-    assertFalse(stage1Inserts.get(0).hasReplacement());
 
-    assertEquals(Role.Property, stage1Inserts.get(1).getRole());
+    assertTrue(stage1Inserts.get(1) instanceof Replacement);
     assertEquals("V1-2", ((SingleValue) stage1Inserts.get(1).getValue()).toDatabaseString());
     assertEquals(new EntityID(1), stage1Inserts.get(1).getId());
-    assertTrue(stage1Inserts.get(1).hasReplacement());
-    assertEquals(stage1Inserts.get(2), stage1Inserts.get(1).getReplacement());
-
-    assertEquals(Role.Domain, stage1Inserts.get(2).getRole());
-    assertEquals("V1-2", ((SingleValue) stage1Inserts.get(2).getValue()).toDatabaseString());
-    assertFalse(stage1Inserts.get(2).hasReplacement());
 
-    deriveStage2Inserts(stage2Inserts, stage1Inserts);
+    assertFalse(stage1Inserts.get(2) instanceof Replacement);
+    assertEquals(new EntityID(-1), stage1Inserts.get(2).getId());
+    assertEquals("1", ((SingleValue) stage1Inserts.get(2).getValue()).toDatabaseString());
 
     assertEquals(1, stage2Inserts.size());
-    assertEquals(Role.Property, stage2Inserts.get(0).getRole());
+
+    assertFalse(stage2Inserts.get(0) instanceof Replacement);
     assertEquals(new EntityID(2), stage2Inserts.get(0).getId());
     assertEquals("V2", ((SingleValue) stage2Inserts.get(0).getValue()).toDatabaseString());
-    assertFalse(stage2Inserts.get(0).hasReplacement());
   }
 
   /**
@@ -297,39 +286,33 @@ public class InsertTest {
     sub1.setStatementStatus(StatementStatus.FIX);
     p1.addProperty(sub1);
 
-    final LinkedList<EntityInterface> stage1Inserts = new LinkedList<EntityInterface>();
-    final LinkedList<EntityInterface> stage2Inserts = new LinkedList<EntityInterface>();
+    final LinkedList<Property> stage1Inserts = new LinkedList<>();
+    final LinkedList<Property> stage2Inserts = new LinkedList<>();
 
-    deriveStage1Inserts(stage1Inserts, r);
+    int count = deriveStage1Inserts(stage1Inserts, r);
+    deriveStage2Inserts(stage2Inserts, stage1Inserts, registerReplacementIds(count), r);
 
     assertEquals(4, stage1Inserts.size());
-    assertEquals(Role.Property, stage1Inserts.get(0).getRole());
+    assertTrue(stage1Inserts.get(0) instanceof Replacement);
     assertEquals(new EntityID(1), stage1Inserts.get(0).getId());
-    assertTrue(stage1Inserts.get(0).hasReplacement());
-    assertEquals(stage1Inserts.get(1), stage1Inserts.get(0).getReplacement());
     assertEquals(null, stage1Inserts.get(0).getValue());
 
-    assertEquals(Role.Domain, stage1Inserts.get(1).getRole());
-    assertFalse(stage1Inserts.get(1).hasReplacement());
-    assertEquals(null, stage1Inserts.get(1).getValue());
+    assertFalse(stage1Inserts.get(1) instanceof Replacement);
+    assertEquals(new EntityID(-1), stage1Inserts.get(1).getId());
+    assertEquals(1, ((ReferenceValue) stage1Inserts.get(1).getValue()).getId().toInteger());
 
-    assertEquals(Role.Property, stage1Inserts.get(2).getRole());
+    assertFalse(stage1Inserts.get(2) instanceof Replacement);
     assertEquals(new EntityID(1), stage1Inserts.get(2).getId());
-    assertFalse(stage1Inserts.get(2).hasReplacement());
     assertEquals(null, stage1Inserts.get(2).getValue());
 
-    assertEquals(Role.Property, stage1Inserts.get(3).getRole());
+    assertFalse(stage1Inserts.get(3) instanceof Replacement);
     assertEquals(new EntityID(1), stage1Inserts.get(3).getId());
-    assertFalse(stage1Inserts.get(3).hasReplacement());
     assertEquals(null, stage1Inserts.get(3).getValue());
 
-    deriveStage2Inserts(stage2Inserts, stage1Inserts);
-
     assertEquals(1, stage2Inserts.size());
-    assertEquals(Role.Property, stage2Inserts.get(0).getRole());
     assertEquals(new EntityID(2), stage2Inserts.get(0).getId());
     assertEquals("V1", ((SingleValue) stage2Inserts.get(0).getValue()).toDatabaseString());
-    assertFalse(stage2Inserts.get(0).hasReplacement());
+    assertEquals(new EntityID(-1), stage2Inserts.get(0).getDomain());
   }
 
   /**
@@ -366,32 +349,31 @@ public class InsertTest {
     p3.setStatementStatus(StatementStatus.FIX);
     r.addProperty(p3);
 
-    final LinkedList<EntityInterface> stage1Inserts = new LinkedList<EntityInterface>();
-    final LinkedList<EntityInterface> stage2Inserts = new LinkedList<EntityInterface>();
+    final LinkedList<Property> stage1Inserts = new LinkedList<>();
+    final LinkedList<Property> stage2Inserts = new LinkedList<>();
 
-    deriveStage1Inserts(stage1Inserts, r);
+    int count = deriveStage1Inserts(stage1Inserts, r);
+    deriveStage2Inserts(stage2Inserts, stage1Inserts, registerReplacementIds(count), r);
 
     assertEquals(4, stage1Inserts.size());
-    assertEquals(Role.Property, stage1Inserts.get(0).getRole());
+
+    assertFalse(stage1Inserts.get(0) instanceof Replacement);
     assertEquals(new EntityID(1), stage1Inserts.get(0).getId());
     assertFalse(stage1Inserts.get(0).hasReplacement());
     assertEquals("V1", ((SingleValue) stage1Inserts.get(0).getValue()).toDatabaseString());
 
-    assertEquals(Role.Property, stage1Inserts.get(1).getRole());
+    assertTrue(stage1Inserts.get(1) instanceof Replacement);
     assertEquals(new EntityID(2), stage1Inserts.get(1).getId());
-    assertTrue(stage1Inserts.get(1).hasReplacement());
-    assertEquals(stage1Inserts.get(2), stage1Inserts.get(1).getReplacement());
     assertTrue(stage1Inserts.get(1).getValue() instanceof CollectionValue);
 
-    assertEquals(Role.Domain, stage1Inserts.get(2).getRole());
-    assertFalse(stage1Inserts.get(2).hasReplacement());
-    assertTrue(stage1Inserts.get(2).getValue() instanceof CollectionValue);
+    assertFalse(stage1Inserts.get(2) instanceof Replacement);
+    assertEquals(new EntityID(-1), stage1Inserts.get(2).getId());
+    assertEquals(2, ((ReferenceValue) stage1Inserts.get(2).getValue()).getId().toInteger());
 
-    assertEquals(Role.Property, stage1Inserts.get(3).getRole());
+    assertFalse(stage1Inserts.get(3) instanceof Replacement);
     assertEquals(new EntityID(3), stage1Inserts.get(3).getId());
-    assertFalse(stage1Inserts.get(3).hasReplacement());
     assertEquals("V3", ((SingleValue) stage1Inserts.get(3).getValue()).toDatabaseString());
 
-    deriveStage2Inserts(stage2Inserts, stage1Inserts);
+    assertEquals(0, stage2Inserts.size());
   }
 }
diff --git a/src/test/java/org/caosdb/server/database/InsertTest2.java b/src/test/java/org/caosdb/server/database/InsertTest2.java
new file mode 100644
index 0000000000000000000000000000000000000000..58cc58503dbef7e8ee1c300d67888f4d2ff37a7a
--- /dev/null
+++ b/src/test/java/org/caosdb/server/database/InsertTest2.java
@@ -0,0 +1,148 @@
+package org.caosdb.server.database;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.LinkedList;
+import java.util.List;
+import org.caosdb.server.entity.Entity;
+import org.caosdb.server.entity.EntityID;
+import org.caosdb.server.entity.InsertEntity;
+import org.caosdb.server.entity.RetrieveEntity;
+import org.caosdb.server.entity.Role;
+import org.caosdb.server.entity.StatementStatus;
+import org.caosdb.server.entity.wrapper.Property;
+import org.junit.jupiter.api.Test;
+
+public class InsertTest2 {
+
+  private Deque<EntityID> registerReplacementIds(int count) {
+    Deque<EntityID> replacementIds = new ArrayDeque<>();
+    for (int i = 1; i < count + 1; i++) {
+      replacementIds.add(new EntityID(-i));
+    }
+    return replacementIds;
+  }
+
+  @Test
+  public void transformation5() {
+    final Entity r = new InsertEntity("Test", Role.RecordType);
+    final Property p1 = new Property(new RetrieveEntity(new EntityID(1)));
+    p1.setRole("Property");
+    p1.setDatatype("TEXT");
+    p1.setDescription("desc1");
+    p1.setDescOverride(true);
+    p1.setName("P1");
+    p1.setNameOverride(true);
+    p1.setStatementStatus(StatementStatus.RECOMMENDED);
+    r.addProperty(p1);
+
+    final Property p2 = new Property(new RetrieveEntity(new EntityID(2)));
+    p2.setRole("Property");
+    p2.setDatatype("TEXT");
+    p2.setDescription("desc2");
+    p2.setDescOverride(true);
+    p2.setName("P2");
+    p2.setNameOverride(true);
+    p2.setStatementStatus(StatementStatus.RECOMMENDED);
+    r.addProperty(p2);
+
+    final Property p21 = new Property(new RetrieveEntity(new EntityID(1)));
+    p21.setRole("Property");
+    p21.setDatatype("TEXT");
+    p21.setDescription("desc21");
+    p21.setDescOverride(true);
+    p21.setName("P21");
+    p21.setNameOverride(true);
+    p21.setStatementStatus(StatementStatus.RECOMMENDED);
+    p2.addProperty(p21);
+
+    final Property p22 = new Property(new RetrieveEntity(new EntityID(2)));
+    p22.setRole("Property");
+    p22.setDatatype("TEXT");
+    p22.setDescription("desc22");
+    p22.setDescOverride(true);
+    p22.setName("P22");
+    p22.setNameOverride(true);
+    p22.setStatementStatus(StatementStatus.RECOMMENDED);
+    p2.addProperty(p22);
+
+    final Property p3 = new Property(new RetrieveEntity(new EntityID(3)));
+    p3.setRole("Property");
+    p3.setDatatype("TEXT");
+    p3.setDescription("desc3");
+    p3.setDescOverride(true);
+    p3.setName("P3");
+    p3.setNameOverride(true);
+    p3.setStatementStatus(StatementStatus.RECOMMENDED);
+    r.addProperty(p3);
+
+    final Property p31 = new Property(new RetrieveEntity(new EntityID(1)));
+    p31.setRole("Property");
+    p31.setDatatype("TEXT");
+    p31.setDescription("desc31");
+    p31.setDescOverride(true);
+    p31.setName("P31");
+    p31.setNameOverride(true);
+    p31.setStatementStatus(StatementStatus.RECOMMENDED);
+    p3.addProperty(p31);
+
+    final Property p32 = new Property(new RetrieveEntity(new EntityID(2)));
+    p32.setRole("Property");
+    p32.setDatatype("TEXT");
+    p32.setDescription("desc32");
+    p32.setDescOverride(true);
+    p32.setName("P32");
+    p32.setNameOverride(true);
+    p32.setStatementStatus(StatementStatus.RECOMMENDED);
+    p3.addProperty(p32);
+
+    final Property p321 = new Property(new RetrieveEntity(new EntityID(1)));
+    p321.setRole("Property");
+    p321.setDatatype("TEXT");
+    p321.setDescription("desc321");
+    p321.setDescOverride(true);
+    p321.setName("P321");
+    p321.setNameOverride(true);
+    p321.setStatementStatus(StatementStatus.RECOMMENDED);
+    p32.addProperty(p321);
+
+    final Property p322 = new Property(new RetrieveEntity(new EntityID(2)));
+    p322.setRole("Property");
+    p322.setDatatype("TEXT");
+    p322.setDescription("desc322");
+    p322.setDescOverride(true);
+    p322.setName("P322");
+    p322.setNameOverride(true);
+    p322.setStatementStatus(StatementStatus.RECOMMENDED);
+    p32.addProperty(p322);
+
+    final Property p323 = new Property(new RetrieveEntity(new EntityID(3)));
+    p323.setRole("Property");
+    p323.setDatatype("TEXT");
+    p323.setDescription("desc323");
+    p323.setDescOverride(true);
+    p323.setName("P323");
+    p323.setNameOverride(true);
+    p323.setStatementStatus(StatementStatus.RECOMMENDED);
+    p32.addProperty(p323);
+
+    final Property p33 = new Property(new RetrieveEntity(new EntityID(3)));
+    p33.setRole("Property");
+    p33.setDatatype("TEXT");
+    p33.setDescription("desc33");
+    p33.setDescOverride(true);
+    p33.setName("P33");
+    p33.setNameOverride(true);
+    p33.setStatementStatus(StatementStatus.RECOMMENDED);
+    p3.addProperty(p33);
+
+    List<Property> stage1Inserts = new LinkedList<>();
+    List<Property> stage2Inserts = new LinkedList<>();
+    int c = DatabaseUtils.deriveStage1Inserts(stage1Inserts, r);
+    DatabaseUtils.deriveStage2Inserts(stage2Inserts, stage1Inserts, registerReplacementIds(c), r);
+    assertEquals(7, stage1Inserts.size());
+    assertEquals(8, stage2Inserts.size());
+  }
+}