diff --git a/src/main/java/org/caosdb/server/CaosDBServer.java b/src/main/java/org/caosdb/server/CaosDBServer.java
index 2a115c5cfa06ed0e3db85847c27fb4c8424eadaf..e843645cd5570e528f37f601c87e9f48b6299c65 100644
--- a/src/main/java/org/caosdb/server/CaosDBServer.java
+++ b/src/main/java/org/caosdb/server/CaosDBServer.java
@@ -129,6 +129,7 @@ public class CaosDBServer extends Application {
   private static boolean NO_TLS = false;
   public static final String REQUEST_TIME_LOGGER = "REQUEST_TIME_LOGGER";
   public static final String REQUEST_ERRORS_LOGGER = "REQUEST_ERRORS_LOGGER";
+  private static boolean USE_CACHE = false;
   private static Scheduler SCHEDULER;
 
   public static String getServerProperty(final String key) {
@@ -196,6 +197,8 @@ public class CaosDBServer extends Application {
 
   public static void initServerProperties() throws IOException {
     SERVER_PROPERTIES = ServerProperties.initServerProperties();
+    USE_CACHE =
+        !Boolean.parseBoolean(CaosDBServer.getServerProperty(ServerProperties.KEY_CACHE_DISABLE));
   }
 
   /**
@@ -886,6 +889,10 @@ public class CaosDBServer extends Application {
       throws SchedulerException {
     SCHEDULER.scheduleJob(job, trigger);
   }
+
+  public static boolean useCache() {
+    return USE_CACHE;
+  }
 }
 
 class CaosDBComponent extends Component {
diff --git a/src/main/java/org/caosdb/server/caching/JCSCacheHelper.java b/src/main/java/org/caosdb/server/caching/JCSCacheHelper.java
index 1613b8be8194425ab14e5e68b9215a0ba92be8d3..f294e4bb029b7e03d2864ae832b3044685536404 100644
--- a/src/main/java/org/caosdb/server/caching/JCSCacheHelper.java
+++ b/src/main/java/org/caosdb/server/caching/JCSCacheHelper.java
@@ -62,8 +62,7 @@ public class JCSCacheHelper implements CacheHelper {
   }
 
   public static void init() {
-    final boolean disabled =
-        Boolean.parseBoolean(CaosDBServer.getServerProperty(ServerProperties.KEY_CACHE_DISABLE));
+    final boolean disabled = !CaosDBServer.useCache();
     init(CaosDBServer.getServerProperty(ServerProperties.KEY_CACHE_CONF_LOC), disabled);
   }
 
diff --git a/src/main/java/org/caosdb/server/database/access/AbstractAccess.java b/src/main/java/org/caosdb/server/database/access/AbstractAccess.java
index 1d30bd3fee7187b9c44378e5b94c1c6d97287f00..680b18275a27d9d55ffecffa8b66e65eb87237bb 100644
--- a/src/main/java/org/caosdb/server/database/access/AbstractAccess.java
+++ b/src/main/java/org/caosdb/server/database/access/AbstractAccess.java
@@ -1,5 +1,4 @@
 /*
- * ** header v3.0
  * This file is a part of the CaosDB Project.
  *
  * Copyright (C) 2018 Research Group Biomedical Physics,
@@ -17,8 +16,6 @@
  *
  * 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.access;
 
@@ -26,11 +23,12 @@ import java.util.HashMap;
 import org.caosdb.server.database.misc.DBHelper;
 import org.caosdb.server.database.misc.RollBackHandler;
 import org.caosdb.server.transaction.TransactionInterface;
+import org.caosdb.server.utils.UseCacheResourceDelegate;
 
-public abstract class AbstractAccess<T extends TransactionInterface> implements Access {
+public abstract class AbstractAccess<T extends TransactionInterface>
+    extends UseCacheResourceDelegate implements Access {
 
   private HashMap<String, DBHelper> helpers = new HashMap<String, DBHelper>();
-  private Boolean useCache = true;
   private final T transaction;
   private boolean released = false;
 
@@ -73,22 +71,6 @@ public abstract class AbstractAccess<T extends TransactionInterface> implements
     }
   }
 
-  @Override
-  public void setUseCache(final Boolean useCache) {
-    this.useCache = useCache;
-  }
-  /**
-   * Whether the transaction allows to use the query cache or other caches. This is controlled by
-   * the "cache" flag.
-   *
-   * @see {@link NoCache}
-   * @return true if caching is encouraged.
-   */
-  @Override
-  public boolean useCache() {
-    return this.useCache;
-  }
-
   @Override
   public void commit() throws Exception {
     synchronized (this.helpers) {
diff --git a/src/main/java/org/caosdb/server/database/access/Access.java b/src/main/java/org/caosdb/server/database/access/Access.java
index 228e8e004aea7454a287bccd898794c2bb4f1b9c..a98afa2737656a9f5bdd0e3d720354b742030584 100644
--- a/src/main/java/org/caosdb/server/database/access/Access.java
+++ b/src/main/java/org/caosdb/server/database/access/Access.java
@@ -1,5 +1,4 @@
 /*
- * ** header v3.0
  * This file is a part of the CaosDB Project.
  *
  * Copyright (C) 2018 Research Group Biomedical Physics,
@@ -17,14 +16,13 @@
  *
  * 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.access;
 
 import org.caosdb.server.database.misc.DBHelper;
+import org.caosdb.server.utils.UseCacheResource;
 
-public interface Access {
+public interface Access extends UseCacheResource {
 
   public abstract void setHelper(String name, DBHelper helper);
 
@@ -33,8 +31,4 @@ public interface Access {
   public abstract void release();
 
   public abstract void commit() throws Exception;
-
-  public abstract void setUseCache(Boolean useCache);
-
-  public boolean useCache();
 }
diff --git a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLGetDependentEntities.java b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLGetDependentEntities.java
index fabe5233d48cbda8b57fe4af10797aa0bd8ad8c5..bb33b4df1adcf38466bcaeaa72923ddc7fe30b65 100644
--- a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLGetDependentEntities.java
+++ b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLGetDependentEntities.java
@@ -51,7 +51,7 @@ public class MySQLGetDependentEntities extends MySQLTransaction
       try {
         final List<EntityID> ret = new LinkedList<>();
         while (rs.next()) {
-          ret.add(new EntityID(rs.getInt(1)));
+          ret.add(new EntityID(rs.getString(1)));
         }
         return ret;
       } finally {
diff --git a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLGetIDByName.java b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLGetIDByName.java
index 611535a946eaaef79c898911b5b5cd67278ca7b0..4837fc591df2ba6a61f28b6608b469ab0fb0f5cb 100644
--- a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLGetIDByName.java
+++ b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLGetIDByName.java
@@ -65,7 +65,7 @@ public class MySQLGetIDByName extends MySQLTransaction implements GetIDByNameImp
       try (ResultSet rs = stmt.executeQuery()) {
         final List<EntityID> ret = new LinkedList<>();
         while (rs.next()) {
-          ret.add(new EntityID(rs.getInt("id")));
+          ret.add(new EntityID(rs.getString("id")));
         }
 
         return ret;
diff --git a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLGetUpdateableChecksums.java b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLGetUpdateableChecksums.java
index dd6c87760c18702b4e69dd5ec46996f0dbd15a63..2081b026903026a0aa704290d6fa16d8d5e64800 100644
--- a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLGetUpdateableChecksums.java
+++ b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLGetUpdateableChecksums.java
@@ -46,7 +46,7 @@ public class MySQLGetUpdateableChecksums extends MySQLTransaction
       final PreparedStatement stmt = prepareStatement(this.GET_UPDATEABLE_CHECKSUMS);
       final ResultSet rs = stmt.executeQuery();
       if (rs.next()) {
-        return new EntityID(rs.getInt(1));
+        return new EntityID(rs.getString(1));
       } else {
         return null;
       }
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 8d70660486b571f7f81e125df200b2be0fce89e0..2fb7c95f766748571009177fa38bf99405637101 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
@@ -224,7 +224,7 @@ public class MySQLInsertEntityProperties extends MySQLTransaction
     try (final ResultSet rs = stmt.executeQuery()) {
       final Deque<EntityID> ret = new ArrayDeque<>();
       while (rs.next()) {
-        ret.add(new EntityID(rs.getInt(1)));
+        ret.add(new EntityID(rs.getString(1)));
       }
       return ret;
     }
diff --git a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLListUsers.java b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLListUsers.java
index 83ebffe679e6625da720fd2933a5d8defb7264c3..3b68c45d0ff60473ae837f3c9ebc17ae82e68c2d 100644
--- a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLListUsers.java
+++ b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLListUsers.java
@@ -53,8 +53,8 @@ public class MySQLListUsers extends MySQLTransaction implements ListUsersImpl {
           user.name = rs.getString("name");
           user.realm = rs.getString("realm");
           user.email = rs.getString("email");
-          user.entity = rs.getInt("entity");
-          if (user.entity == 0) {
+          user.entity = rs.getString("entity");
+          if (user.entity.isBlank() || user.entity.equals("0")) {
             user.entity = null;
           }
           user.status = UserStatus.valueOf(rs.getString("status"));
diff --git a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveAll.java b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveAll.java
index 9a2ea81629853e3baf9de7757e1abe6c8f01fe28..55b8f194ea0be90b5a77fa0c50930c836c48b3f7 100644
--- a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveAll.java
+++ b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveAll.java
@@ -75,7 +75,7 @@ public class MySQLRetrieveAll extends MySQLTransaction implements RetrieveAllImp
           final String acl = DatabaseUtils.bytes2UTF8(rs.getBytes("ACL"));
           if (EntityACL.deserialize(acl)
               .isPermitted(SecurityUtils.getSubject(), EntityPermission.RETRIEVE_ENTITY)) {
-            ret.add(new EntityID(rs.getInt("ID")));
+            ret.add(new EntityID(rs.getString("ID")));
           }
         }
         return ret;
diff --git a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveCurrentMaxId.java b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveCurrentMaxId.java
index 18cf01f159d10aac470bdeb919df185b09d6c7fa..1bc9a89dd119a66eecc33799849977019422fde1 100644
--- a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveCurrentMaxId.java
+++ b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveCurrentMaxId.java
@@ -14,7 +14,8 @@ public class MySQLRetrieveCurrentMaxId extends MySQLTransaction
     super(access);
   }
 
-  public static final String STMT = "SELECT max(entity_id) AS max_id FROM transaction_log";
+  public static final String STMT =
+      "SELECT max(CAST(entity_id AS UNSIGNED INT)) AS max_id FROM transaction_log WHERE transaction='Insert'";
 
   @Override
   public Integer execute() {
diff --git a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveProperties.java b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveProperties.java
index 546b5675cb5e1b0d51398230155f61b1e11f2ebb..30a0f530bb77458f95d21278f0474e2cdc89a457 100644
--- a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveProperties.java
+++ b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveProperties.java
@@ -22,6 +22,7 @@
  */
 package org.caosdb.server.database.backend.implementation.MySQL;
 
+import com.mysql.cj.jdbc.exceptions.MysqlDataTruncation;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
@@ -92,6 +93,8 @@ public class MySQLRetrieveProperties extends MySQLTransaction implements Retriev
       }
 
       return properties;
+    } catch (MysqlDataTruncation e) {
+      throw e;
     }
   }
 
diff --git a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveUser.java b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveUser.java
index 40f036f1d63753c0be9e6153f741db7d4f9d04ad..b149fae264549f88c21d996f854662401d744beb 100644
--- a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveUser.java
+++ b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveUser.java
@@ -66,7 +66,7 @@ public class MySQLRetrieveUser extends MySQLTransaction implements RetrieveUserI
           if (rs.getString("entity") == null) {
             ret.entity = null;
           } else {
-            ret.entity = rs.getInt("entity");
+            ret.entity = rs.getString("entity");
           }
         }
       } finally {
diff --git a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLUpdateUser.java b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLUpdateUser.java
index bd368698956163a8473ead7507aac0ba2b83d552..43f71e386fcad42b4a3e39e14eeedf7cb924a535 100644
--- a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLUpdateUser.java
+++ b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLUpdateUser.java
@@ -49,7 +49,7 @@ public class MySQLUpdateUser extends MySQLTransaction implements UpdateUserImpl
       stmt.setString(3, user.status.toString());
       stmt.setString(4, user.email);
       if (user.entity != null) {
-        stmt.setInt(5, user.entity);
+        stmt.setString(5, user.entity);
       } else {
         stmt.setNull(5, Types.INTEGER);
       }
@@ -57,7 +57,7 @@ public class MySQLUpdateUser extends MySQLTransaction implements UpdateUserImpl
       stmt.setString(6, user.status.toString());
       stmt.setString(7, user.email);
       if (user.entity != null) {
-        stmt.setInt(8, user.entity);
+        stmt.setString(8, user.entity);
       } else {
         stmt.setNull(8, Types.INTEGER);
       }
diff --git a/src/main/java/org/caosdb/server/database/proto/ProtoUser.java b/src/main/java/org/caosdb/server/database/proto/ProtoUser.java
index 643f4250216c7829c8218113a8842ff139b313ec..8b2d97a85044881d61fa6ea795443ae13f3cabc2 100644
--- a/src/main/java/org/caosdb/server/database/proto/ProtoUser.java
+++ b/src/main/java/org/caosdb/server/database/proto/ProtoUser.java
@@ -36,7 +36,7 @@ public class ProtoUser implements Serializable {
   public UserStatus status = null;
   public String name = null;
   public String email = null;
-  public Integer entity = null;
+  public String entity = null;
   public String realm = null;
   public HashSet<String> roles = null;
 }
diff --git a/src/main/java/org/caosdb/server/datatype/ReferenceValue.java b/src/main/java/org/caosdb/server/datatype/ReferenceValue.java
index a24e2ddfda7faf333fd7d7f64420d4a6c7fdc290..20620a4327ddbc46fb5f5f29abad4ef93e4fee88 100644
--- a/src/main/java/org/caosdb/server/datatype/ReferenceValue.java
+++ b/src/main/java/org/caosdb/server/datatype/ReferenceValue.java
@@ -66,7 +66,7 @@ public class ReferenceValue implements SingleValue {
       throw ServerMessages.DATA_TYPE_DOES_NOT_ACCEPT_COLLECTION_VALUES;
     } else {
       try {
-        return new ReferenceValue(Integer.parseInt(reference.toString()));
+        return new ReferenceValue(reference.toString());
       } catch (final NumberFormatException e) {
         return new ReferenceValue(reference.toString());
       }
@@ -81,9 +81,9 @@ public class ReferenceValue implements SingleValue {
   public static ReferenceValue parseIdVersion(final String str) {
     final String[] split = str.split("@", 2);
     if (split.length == 2) {
-      return new ReferenceValue(Integer.parseInt(split[0]), split[1]);
+      return new ReferenceValue(split[0], split[1]);
     } else {
-      return new ReferenceValue(Integer.parseInt(str));
+      return new ReferenceValue(str);
     }
   }
 
@@ -150,14 +150,13 @@ public class ReferenceValue implements SingleValue {
   /** If the reference is given by name, versioning is not possible (at the moment). */
   public ReferenceValue(final String name) {
     this.name = name;
+    this.id = new EntityID(name);
   }
 
-  public ReferenceValue(final int id, final String name) {
-    this(new EntityID(id), name);
-  }
-
-  public ReferenceValue(final int id) {
-    this(new EntityID(id));
+  public ReferenceValue(String name, String version) {
+    this.name = name;
+    this.id = new EntityID(name);
+    this.version = version;
   }
 
   public final EntityInterface getEntity() {
diff --git a/src/main/java/org/caosdb/server/entity/Entity.java b/src/main/java/org/caosdb/server/entity/Entity.java
index 19934568c93a421af5dab35635686de61052bc93..9c75e91d50e84bd06356c7f85eb1a1018232638b 100644
--- a/src/main/java/org/caosdb/server/entity/Entity.java
+++ b/src/main/java/org/caosdb/server/entity/Entity.java
@@ -73,7 +73,7 @@ public abstract class Entity extends AbstractObservable implements EntityInterfa
   private String name = null;
   private String description = null;
   private Value value = null;
-  private final EntityID domain = new EntityID(0);
+  private final EntityID domain = new EntityID("0");
   private final EntityID id = new EntityID();
   private AbstractDatatype datatype = null;
   private final ParentContainer parents = new ParentContainer(this);
diff --git a/src/main/java/org/caosdb/server/entity/EntityID.java b/src/main/java/org/caosdb/server/entity/EntityID.java
index f1a13769140e856d62e197108c9cc8e1c298de11..469b2e50ef124061eb400878d59b98de1ebbe840 100644
--- a/src/main/java/org/caosdb/server/entity/EntityID.java
+++ b/src/main/java/org/caosdb/server/entity/EntityID.java
@@ -22,12 +22,8 @@ public class EntityID implements Serializable {
 
   public EntityID() {}
 
-  public EntityID(final int id) {
-    this(Integer.toString(id));
-  }
-
   public EntityID(final String id) {
-    this.id = id.toString();
+    this.id = id;
   }
 
   public void setId(final String id) {
diff --git a/src/main/java/org/caosdb/server/entity/EntityIdRegistry.java b/src/main/java/org/caosdb/server/entity/EntityIdRegistry.java
index 6ab18d156225fc683e73128c1d92381cfe87892d..c6010eda5e1b8b590fae2afbf5f5964021ef8a99 100644
--- a/src/main/java/org/caosdb/server/entity/EntityIdRegistry.java
+++ b/src/main/java/org/caosdb/server/entity/EntityIdRegistry.java
@@ -1,51 +1,46 @@
 package org.caosdb.server.entity;
 
-import org.caosdb.server.database.backend.transaction.RetrieveCurrentMaxId;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import org.caosdb.server.database.exceptions.TransactionException;
 import org.caosdb.server.transaction.Transaction;
 
-/**
- * Aufgaben:
- *
- * <ul>
- *   <li>Ids generieren
- *       <ul>
- *         <li>Pattern (positive Integer, uuid)
- *       </ul>
- *   <li>
- * </ul>
- *
- * @author tf
- */
 public class EntityIdRegistry {
 
-  private boolean isInit;
-  private Integer currentMaxId;
-  private Transaction<?> transaction;
+  private EntityIdRegistryStrategy strategy;
 
   public EntityIdRegistry(Transaction<?> t) {
-    this.transaction = t;
-    this.isInit = false;
+    // this("org.caosdb.server.entity.StringIds", t);
+    this("org.caosdb.server.entity.LegacyIds", t);
   }
 
-  public void init() {
-    isInit = true;
-    initCurrentMaxId();
+  public EntityIdRegistry(EntityIdRegistryStrategy strategy) {
+    this.strategy = strategy;
   }
 
-  private void initCurrentMaxId() {
-    this.currentMaxId =
-        Math.max(
-            101,
-            transaction
-                .execute(new RetrieveCurrentMaxId(), transaction.getAccess())
-                .getCurrentMaxId());
+  public String generate() {
+    return this.strategy.generate();
   }
 
-  public String generate() {
-    if (!isInit) {
-      init();
+  public EntityIdRegistry(String strategy, Transaction<?> t) {
+    try {
+      @SuppressWarnings("unchecked")
+      Class<? extends EntityIdRegistry> clazz =
+          (Class<? extends EntityIdRegistry>) Class.forName(strategy);
+      Constructor<?> constructor = clazz.getConstructor(Transaction.class);
+      this.strategy = (EntityIdRegistryStrategy) constructor.newInstance(t);
+    } catch (ClassNotFoundException
+        | NoSuchMethodException
+        | SecurityException
+        | InstantiationException
+        | IllegalAccessException
+        | IllegalArgumentException
+        | InvocationTargetException e) {
+      throw new TransactionException(e);
     }
-    ++currentMaxId;
-    return Integer.toString(++currentMaxId);
+  }
+
+  public boolean matchIdPattern(String id) {
+    return this.strategy.matchIdPattern(id);
   }
 }
diff --git a/src/main/java/org/caosdb/server/entity/EntityIdRegistryStrategy.java b/src/main/java/org/caosdb/server/entity/EntityIdRegistryStrategy.java
new file mode 100644
index 0000000000000000000000000000000000000000..66235e980d1c82ecf6a7d3ef5b5fd30b702b41dd
--- /dev/null
+++ b/src/main/java/org/caosdb/server/entity/EntityIdRegistryStrategy.java
@@ -0,0 +1,20 @@
+package org.caosdb.server.entity;
+
+import org.caosdb.server.transaction.Transaction;
+
+public abstract class EntityIdRegistryStrategy {
+
+  private Transaction<?> transaction;
+
+  public EntityIdRegistryStrategy(Transaction<?> transaction) {
+    this.transaction = transaction;
+  }
+
+  public abstract String generate();
+
+  public Transaction<?> getTransaction() {
+    return transaction;
+  }
+
+  public abstract boolean matchIdPattern(String id);
+}
diff --git a/src/main/java/org/caosdb/server/entity/LegacyIds.java b/src/main/java/org/caosdb/server/entity/LegacyIds.java
new file mode 100644
index 0000000000000000000000000000000000000000..38f5bfefdc8f3028585881c489f3ff143498acfc
--- /dev/null
+++ b/src/main/java/org/caosdb/server/entity/LegacyIds.java
@@ -0,0 +1,48 @@
+package org.caosdb.server.entity;
+
+import org.caosdb.server.database.backend.transaction.RetrieveCurrentMaxId;
+import org.caosdb.server.transaction.Transaction;
+
+public class LegacyIds extends EntityIdRegistryStrategy {
+
+  private boolean isInit;
+  private Integer currentMaxId;
+
+  public LegacyIds(Transaction<?> t) {
+    super(t);
+    this.isInit = false;
+  }
+
+  private void init() {
+    isInit = true;
+    initCurrentMaxId();
+  }
+
+  private void initCurrentMaxId() {
+    this.currentMaxId =
+        Math.max(
+            101,
+            getTransaction()
+                .execute(new RetrieveCurrentMaxId(), getTransaction().getAccess())
+                .getCurrentMaxId());
+  }
+
+  @Override
+  public String generate() {
+    if (!isInit) {
+      init();
+    }
+    ++currentMaxId;
+    return Integer.toString(++currentMaxId);
+  }
+
+  @Override
+  public boolean matchIdPattern(String id) {
+    try {
+      Integer.parseInt(id);
+      return true;
+    } catch (NumberFormatException e) {
+      return false;
+    }
+  }
+}
diff --git a/src/main/java/org/caosdb/server/entity/MagicTypes.java b/src/main/java/org/caosdb/server/entity/MagicTypes.java
index e132ddc00c2aeac2630c0aabfc5a93a07ce504dc..6e987af95c0188fa21a50f19d11a493d97bbe8d8 100644
--- a/src/main/java/org/caosdb/server/entity/MagicTypes.java
+++ b/src/main/java/org/caosdb/server/entity/MagicTypes.java
@@ -33,9 +33,9 @@ public enum MagicTypes {
   NAME,
   DESCRIPTION;
 
-  private static final EntityID UNIT_ID = new EntityID(21);
-  private static final EntityID DESCRIPTION_ID = new EntityID(24);
-  private static final EntityID NAME_ID = new EntityID(20);
+  private static final EntityID UNIT_ID = new EntityID("21");
+  private static final EntityID DESCRIPTION_ID = new EntityID("24");
+  private static final EntityID NAME_ID = new EntityID("20");
 
   public EntityID getId() {
     switch (this) {
@@ -82,7 +82,7 @@ public enum MagicTypes {
     final RetrieveContainer container =
         new RetrieveContainer(null, System.currentTimeMillis(), null, null);
     for (final MagicTypes mt : MagicTypes.values()) {
-      container.add(mt.getId());
+      container.add(mt.getId(), null);
     }
     final Retrieve retrieve = new Retrieve(container);
     retrieve.execute();
diff --git a/src/main/java/org/caosdb/server/entity/RetrieveEntity.java b/src/main/java/org/caosdb/server/entity/RetrieveEntity.java
index 2d1ca6f2175ca2377b7f1a73f847a48377cc4694..00a120fbf023024eae8acc5788a9260d020a956d 100644
--- a/src/main/java/org/caosdb/server/entity/RetrieveEntity.java
+++ b/src/main/java/org/caosdb/server/entity/RetrieveEntity.java
@@ -47,6 +47,11 @@ public class RetrieveEntity extends Entity {
     this.setVersion(new Version(version));
   }
 
+  public RetrieveEntity(final EntityID id, String name, final String version) {
+    this(id, version);
+    this.setName(name);
+  }
+
   public RetrieveEntity(final String name, final String version) {
     super(name);
     this.setVersion(new Version(version));
diff --git a/src/main/java/org/caosdb/server/entity/StringIds.java b/src/main/java/org/caosdb/server/entity/StringIds.java
new file mode 100644
index 0000000000000000000000000000000000000000..ca60730a0efac6b24060077dbbbb0185cfb1763c
--- /dev/null
+++ b/src/main/java/org/caosdb/server/entity/StringIds.java
@@ -0,0 +1,26 @@
+package org.caosdb.server.entity;
+
+import java.util.UUID;
+import org.caosdb.server.transaction.Transaction;
+
+public class StringIds extends EntityIdRegistryStrategy {
+
+  public StringIds(Transaction<?> t) {
+    super(t);
+  }
+
+  @Override
+  public String generate() {
+    return UUID.randomUUID().toString();
+  }
+
+  @Override
+  public boolean matchIdPattern(String id) {
+    try {
+      UUID.fromString(id);
+      return true;
+    } catch (IllegalArgumentException e) {
+      return false;
+    }
+  }
+}
diff --git a/src/main/java/org/caosdb/server/entity/container/Container.java b/src/main/java/org/caosdb/server/entity/container/Container.java
index 1618fbed6a1594891ea3ddc615f48869227f2c92..fdbcbf0de68d77c3eef026ef68d559a69f2f0956 100644
--- a/src/main/java/org/caosdb/server/entity/container/Container.java
+++ b/src/main/java/org/caosdb/server/entity/container/Container.java
@@ -36,9 +36,11 @@ public class Container<T extends EntityInterface> extends ArrayList<T> {
    * Return the entity with the matching id, if it can be found inside this Container, else null.
    */
   public T getEntityById(final EntityID id) {
-    for (final T e : this) {
-      if (e.hasId() && e.getId().equals(id)) {
-        return e;
+    if (id != null) {
+      for (final T e : this) {
+        if (e.hasId() && e.getId().equals(id)) {
+          return e;
+        }
       }
     }
     return null;
diff --git a/src/main/java/org/caosdb/server/entity/container/EntityByIdContainer.java b/src/main/java/org/caosdb/server/entity/container/EntityByIdContainer.java
index a8c3e6a832848903884edda270e003a0c0dd6feb..1e756e3313fc4a816c096351527df7022a79f47b 100644
--- a/src/main/java/org/caosdb/server/entity/container/EntityByIdContainer.java
+++ b/src/main/java/org/caosdb/server/entity/container/EntityByIdContainer.java
@@ -37,7 +37,5 @@ public abstract class EntityByIdContainer extends TransactionContainer {
     super(user, timestamp, srid, flags);
   }
 
-  public abstract void add(EntityID id);
-
   public abstract void add(EntityID id, String version);
 }
diff --git a/src/main/java/org/caosdb/server/entity/container/RetrieveContainer.java b/src/main/java/org/caosdb/server/entity/container/RetrieveContainer.java
index bc0da7c1de2bb876551d29ad7daffb50494f9720..d58d85dc1d6a627757a9e0c8fd851aef899901bd 100644
--- a/src/main/java/org/caosdb/server/entity/container/RetrieveContainer.java
+++ b/src/main/java/org/caosdb/server/entity/container/RetrieveContainer.java
@@ -27,7 +27,7 @@ import org.apache.shiro.subject.Subject;
 import org.caosdb.server.entity.EntityID;
 import org.caosdb.server.entity.RetrieveEntity;
 
-public class RetrieveContainer extends EntityByIdContainer {
+public class RetrieveContainer extends TransactionContainer {
 
   private static final long serialVersionUID = 4816050921531043503L;
 
@@ -39,21 +39,11 @@ public class RetrieveContainer extends EntityByIdContainer {
     super(user, timestamp, srid, flags);
   }
 
-  @Override
-  public void add(final EntityID id) {
-    add(new RetrieveEntity(id));
-  }
-
-  public void add(final String name) {
-    add(new RetrieveEntity(name));
-  }
-
-  public void add(final String name, final String version) {
-    add(new RetrieveEntity(name, version));
-  }
-
-  @Override
   public void add(final EntityID id, final String version) {
     add(new RetrieveEntity(id, version));
   }
+
+  public void add(final EntityID id, final String name, final String version) {
+    add(new RetrieveEntity(id, name, version));
+  }
 }
diff --git a/src/main/java/org/caosdb/server/entity/container/TransactionContainer.java b/src/main/java/org/caosdb/server/entity/container/TransactionContainer.java
index 3e5ec4d55f086061e2d0766c9f700ef61fbe809f..f2f2c0254a2b9092e8c33c00a4b60f35d88fdeee 100644
--- a/src/main/java/org/caosdb/server/entity/container/TransactionContainer.java
+++ b/src/main/java/org/caosdb/server/entity/container/TransactionContainer.java
@@ -153,9 +153,11 @@ public class TransactionContainer extends Container<EntityInterface>
    * @param name
    */
   public EntityInterface getEntityByName(final String name) {
-    for (final EntityInterface e : this) {
-      if (e.hasName() && e.getName().equals(name)) {
-        return e;
+    if (name != null) {
+      for (final EntityInterface e : this) {
+        if (e.hasName() && e.getName().equals(name)) {
+          return e;
+        }
       }
     }
     return null;
diff --git a/src/main/java/org/caosdb/server/grpc/AccessControlManagementServiceImpl.java b/src/main/java/org/caosdb/server/grpc/AccessControlManagementServiceImpl.java
index 88429828f27ac843903cfcfc801847c35eedb607..00a433d72c0a00e8e8ef796777bfa016679cbfe6 100644
--- a/src/main/java/org/caosdb/server/grpc/AccessControlManagementServiceImpl.java
+++ b/src/main/java/org/caosdb/server/grpc/AccessControlManagementServiceImpl.java
@@ -129,8 +129,7 @@ public class AccessControlManagementServiceImpl extends AccessControlManagementS
       result.setEmailSetting(EmailSetting.newBuilder().setEmail(user.email));
     }
     if (user.entity != null) {
-      result.setEntitySetting(
-          EntitySetting.newBuilder().setEntityId(Integer.toString(user.entity)));
+      result.setEntitySetting(EntitySetting.newBuilder().setEntityId(user.entity));
     }
     if (user.roles != null && !user.roles.isEmpty()) {
       result.addAllRoles(user.roles);
diff --git a/src/main/java/org/caosdb/server/grpc/EntityTransactionServiceImpl.java b/src/main/java/org/caosdb/server/grpc/EntityTransactionServiceImpl.java
index 030b52544fec858ef3c62c531e9627baf5500551..61724779d7d9ae466a5acc3eb8116a309db5a5f6 100644
--- a/src/main/java/org/caosdb/server/grpc/EntityTransactionServiceImpl.java
+++ b/src/main/java/org/caosdb/server/grpc/EntityTransactionServiceImpl.java
@@ -47,11 +47,11 @@ import org.caosdb.api.entity.v1.RetrieveResponse;
 import org.caosdb.api.entity.v1.SelectQueryResult;
 import org.caosdb.api.entity.v1.TransactionRequest;
 import org.caosdb.api.entity.v1.TransactionRequest.WrappedRequestsCase;
-import org.caosdb.api.entity.v1.TransactionResponse;
 import org.caosdb.api.entity.v1.UpdateRequest;
 import org.caosdb.api.entity.v1.UpdateResponse;
 import org.caosdb.server.CaosDBException;
 import org.caosdb.server.entity.DeleteEntity;
+import org.caosdb.server.entity.EntityID;
 import org.caosdb.server.entity.EntityInterface;
 import org.caosdb.server.entity.FileProperties;
 import org.caosdb.server.entity.InsertEntity;
@@ -135,15 +135,19 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa
       } else { // or ID retrieves.
         final String id = sub_request.getRetrieveRequest().getId();
         if (!id.isBlank()) {
+          /*
           try {
-            final RetrieveEntity entity = new RetrieveEntity(grpcToCaosdb.getId(id));
-            if (isFileDownload) {
-              entity.setFlag("download_files", "true");
-            }
-            container.add(entity);
+          */
+          final RetrieveEntity entity = new RetrieveEntity(new EntityID(id));
+          if (isFileDownload) {
+            entity.setFlag("download_files", "true");
+          }
+          container.add(entity);
+          /*
           } catch (final NumberFormatException e) {
             // We handle this after the retrieval
           }
+          */
         }
       }
     }
@@ -194,7 +198,7 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa
     }
 
     // Add those entities which have not been retrieved because they have a string id
-    for (final TransactionRequest sub_request : request.getRequestsList()) {
+    /*for (final TransactionRequest sub_request : request.getRequestsList()) {
       final String id = sub_request.getRetrieveRequest().getId();
       if (!id.isBlank()) {
         try {
@@ -208,16 +212,18 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa
                       RetrieveResponse.newBuilder().setEntityResponse(entityDoesNotExist(id))));
         }
       }
-    }
+    }*/
     return builder.build();
   }
 
+  /*
   private EntityResponse entityDoesNotExist(final String id) {
     return EntityResponse.newBuilder()
         .addErrors(caosdbToGrpc.convert(ServerMessages.ENTITY_DOES_NOT_EXIST))
         .setEntity(Entity.newBuilder().setId(id))
         .build();
   }
+  */
 
   private String getSRID() {
     return UUID.randomUUID().toString();
@@ -298,7 +304,7 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa
           try {
             final UpdateEntity entity =
                 new UpdateEntity(
-                    grpcToCaosdb.getId(updateEntity.getId()), // ID is not handled by grpc convert
+                    new EntityID(updateEntity.getId()), // ID is not handled by grpc convert
                     grpcToCaosdb.convert(updateEntity.getRole()));
             grpcToCaosdb.convert(updateEntity, entity);
             addFileUpload(container, entity, updateRequest.getEntityRequest());
@@ -311,7 +317,7 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa
         case DELETE_REQUEST:
           final DeleteRequest deleteRequest = subRequest.getDeleteRequest();
           try {
-            final DeleteEntity entity = new DeleteEntity(grpcToCaosdb.getId(deleteRequest.getId()));
+            final DeleteEntity entity = new DeleteEntity(new EntityID(deleteRequest.getId()));
             container.add(entity);
 
           } catch (final NumberFormatException e) {
@@ -383,12 +389,14 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa
           final Entity updateEntity = updateRequest.getEntityRequest().getEntity();
 
           idResponse.setId(updateEntity.getId());
+          /*
           try {
             grpcToCaosdb.getId(updateEntity.getId());
           } catch (final NumberFormatException e) {
             // ID wasn't an integer
             idResponse.addErrors(caosdbToGrpc.convert(ServerMessages.ENTITY_DOES_NOT_EXIST));
           }
+          */
           builder
               .addResponsesBuilder()
               .setUpdateResponse(UpdateResponse.newBuilder().setIdResponse(idResponse));
@@ -396,12 +404,14 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa
         case DELETE_REQUEST:
           final DeleteRequest deleteRequest = subRequest.getDeleteRequest();
           idResponse.setId(deleteRequest.getId());
+          /*
           try {
             grpcToCaosdb.getId(deleteRequest.getId());
           } catch (final NumberFormatException e) {
             // ID wasn't an integer
             idResponse.addErrors(caosdbToGrpc.convert(ServerMessages.ENTITY_DOES_NOT_EXIST));
           }
+          */
           builder
               .addResponsesBuilder()
               .setDeleteResponse(DeleteResponse.newBuilder().setIdResponse(idResponse));
diff --git a/src/main/java/org/caosdb/server/grpc/GrpcToCaosDBConverters.java b/src/main/java/org/caosdb/server/grpc/GrpcToCaosDBConverters.java
index 0430a795457152141473c2819997ebd1597028fd..1c0b0f429d1702c9e952e3aeda95bcd13355b4df 100644
--- a/src/main/java/org/caosdb/server/grpc/GrpcToCaosDBConverters.java
+++ b/src/main/java/org/caosdb/server/grpc/GrpcToCaosDBConverters.java
@@ -66,9 +66,11 @@ import org.caosdb.server.utils.ServerMessages;
 
 public class GrpcToCaosDBConverters {
 
+  /*
   public EntityID getId(final String id) {
     return new EntityID(Integer.parseInt(id));
   }
+  */
 
   public Role convert(final EntityRole role) {
     switch (role) {
@@ -256,7 +258,7 @@ public class GrpcToCaosDBConverters {
     final Property result = new Property(new RetrieveEntity());
 
     try {
-      result.setId(e.getId().isBlank() ? null : getId(e.getId()));
+      result.setId(e.getId().isBlank() ? null : new EntityID(e.getId()));
     } catch (final NumberFormatException exc) {
       result.addError(ServerMessages.ENTITY_DOES_NOT_EXIST);
     }
@@ -314,7 +316,7 @@ public class GrpcToCaosDBConverters {
         new org.caosdb.server.entity.wrapper.Parent(new RetrieveEntity());
 
     try {
-      result.setId(e.getId().isBlank() ? null : getId(e.getId()));
+      result.setId(e.getId().isBlank() ? null : new EntityID(e.getId()));
     } catch (final NumberFormatException exc) {
       result.addError(ServerMessages.ENTITY_DOES_NOT_EXIST);
     }
@@ -336,7 +338,7 @@ public class GrpcToCaosDBConverters {
 
   private EntityInterface convert(EntityACL acl) {
     try {
-      EntityID id = getId(acl.getId());
+      EntityID id = new EntityID(acl.getId());
       UpdateEntity result = new UpdateEntity(id);
       result.setEntityACL(convertAcl(acl));
       return result;
diff --git a/src/main/java/org/caosdb/server/jobs/Job.java b/src/main/java/org/caosdb/server/jobs/Job.java
index 9f6103a9bea047fb11b1b25d6ecc9cfa67988ab8..5134de6ccd796aa7a1ca6111af0c56447ad9925e 100644
--- a/src/main/java/org/caosdb/server/jobs/Job.java
+++ b/src/main/java/org/caosdb/server/jobs/Job.java
@@ -3,8 +3,8 @@
  *
  * Copyright (C) 2018 Research Group Biomedical Physics,
  *   Max-Planck-Institute for Dynamics and Self-Organization Göttingen
- * Copyright (C) 2020-2021 IndiScale GmbH <info@indiscale.com>
- * Copyright (C) 2020-2021 Timm Fitschen <t.fitschen@indiscale.com>
+ * Copyright (C) 2020-2023 IndiScale GmbH <info@indiscale.com>
+ * Copyright (C) 2020-2023 Timm Fitschen <t.fitschen@indiscale.com>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -25,6 +25,7 @@ import java.lang.reflect.InvocationTargetException;
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 import org.apache.shiro.subject.Subject;
@@ -32,9 +33,8 @@ import org.caosdb.server.CaosDBException;
 import org.caosdb.server.database.BackendTransaction;
 import org.caosdb.server.database.backend.transaction.GetIDByName;
 import org.caosdb.server.database.backend.transaction.IsSubType;
-import org.caosdb.server.database.backend.transaction.RetrieveFullEntityTransaction;
-import org.caosdb.server.database.backend.transaction.RetrieveParents;
 import org.caosdb.server.database.backend.transaction.RetrieveSparseEntity;
+import org.caosdb.server.database.exceptions.EntityDoesNotExistException;
 import org.caosdb.server.database.exceptions.EntityWasNotUniqueException;
 import org.caosdb.server.database.exceptions.TransactionException;
 import org.caosdb.server.datatype.AbstractCollectionDatatype;
@@ -43,13 +43,12 @@ import org.caosdb.server.datatype.ReferenceDatatype2;
 import org.caosdb.server.entity.EntityID;
 import org.caosdb.server.entity.EntityInterface;
 import org.caosdb.server.entity.Message;
-import org.caosdb.server.entity.container.ParentContainer;
+import org.caosdb.server.entity.Version;
 import org.caosdb.server.entity.container.TransactionContainer;
 import org.caosdb.server.entity.wrapper.Parent;
 import org.caosdb.server.jobs.core.JobFailureSeverity;
 import org.caosdb.server.transaction.Transaction;
 import org.caosdb.server.utils.EntityStatus;
-import org.caosdb.server.utils.ServerMessages;
 import org.reflections.Reflections;
 
 /**
@@ -72,7 +71,7 @@ public abstract class Job {
 
   public abstract JobTarget getTarget();
 
-  protected <S, T> HashMap<S, T> getCache(final String name) {
+  protected <S, T> Map<S, T> getCache(final String name) {
     return getTransaction().getCache(name);
   }
 
@@ -88,7 +87,7 @@ public abstract class Job {
     return getTransaction().getTransactor();
   }
 
-  public <K extends BackendTransaction> K execute(final K t) {
+  protected <K extends BackendTransaction> K execute(final K t) {
     return getTransaction().execute(t, getTransaction().getAccess());
   }
 
@@ -184,8 +183,8 @@ public abstract class Job {
       if (targetParent.getId().equals(child.getId())) {
         return true;
       }
-
-    } else if (targetParent.hasName()) {
+    }
+    if (targetParent.hasName()) {
       if (targetParent.getName().equals(child.getName())) {
         return true;
       } else {
@@ -194,13 +193,7 @@ public abstract class Job {
     }
 
     // check direct parents of child
-    ParentContainer directParents;
-    if (child.hasParents()) {
-      directParents = child.getParents();
-    } else {
-      directParents = resolve(child).getParents();
-    }
-    for (final Parent directParent : directParents) {
+    for (final Parent directParent : child.getParents()) {
       EntityInterface resolvedDirectParent = null;
       if (directParent.hasId() && targetParent.hasId()) {
         if (directParent.getId().equals(targetParent.getId())) {
@@ -230,78 +223,73 @@ public abstract class Job {
   }
 
   protected final boolean isValidSubType(final EntityID child, final EntityID parent) {
-    if (!"false".equals(getContainer().getFlags().get("cache"))) {
-      final HashMap<String, Boolean> isSubTypeCache = getCache("isSubType");
-      final String key = child + "->" + parent;
-      final Boolean cached = isSubTypeCache.get(key);
-      if (cached == null) {
-        final Boolean toCache = isValidSubTypeNoCache(child, parent);
-        isSubTypeCache.put(key, toCache);
-        return toCache;
-      } else {
-        return cached;
-      }
-    } else {
-      return isValidSubTypeNoCache(child, parent);
+    Boolean result = null;
+    final Map<String, Boolean> isSubTypeCache = getCache("isSubType");
+
+    final String key = child + "->" + parent;
+    result = isSubTypeCache.get(key);
+
+    if (result == null) {
+      result = isValidSubTypeNoCache(child, parent);
+      isSubTypeCache.put(key, result);
     }
+
+    return result;
   }
 
-  protected final boolean isValidSubTypeNoCache(final EntityID child, final EntityID parent) {
+  private final boolean isValidSubTypeNoCache(final EntityID child, final EntityID parent) {
     return Objects.equals(child, parent) || execute(new IsSubType(child, parent)).isSubType();
   }
 
-  protected final EntityInterface retrieveValidSparseEntityByName(final String name)
-      throws Message {
-    return retrieveValidSparseEntityById(retrieveValidIDByName(name), null);
+  private final EntityInterface retrieveValidLazyEntityByName(final String name, String version) {
+    EntityID id = null;
+
+    final Map<String, EntityID> cache = getCache("validEntityByName");
+    String key = name;
+    if (version != null && !version.equals("HEAD")) {
+      key += version;
+    }
+
+    id = cache.get(key);
+    if (id == null) {
+      id = retrieveValidIDByName(name, version);
+      cache.put(key, id);
+    }
+
+    return retrieveValidLazyEntityById(id, version);
   }
 
-  protected final EntityInterface retrieveValidSparseEntityById(
-      final EntityID id, final String version) throws Message {
+  private final EntityInterface retrieveValidLazyEntityById(
+      final EntityID id, final String version) {
+    EntityInterface result = null;
 
-    String resulting_version = version;
-    if (version == null || version.equals("HEAD")) {
-      // the targeted entity version is the entity after the transaction or the
-      // entity without a specific version. Thus we have to fetch the entity
-      // from the container if possible.
-      final EntityInterface ret = getEntityById(id);
-      if (ret != null) {
-        return ret;
-      }
-    } else if (version.startsWith("HEAD~")) {
-      final EntityInterface entById = getEntityById(id);
-      if (entById != null && entById.getEntityStatus() != EntityStatus.VALID) {
-        // if version is HEAD~{OFFSET} with {OFFSET} > 0 and the targeted entity is is to be
-        // updated, the actual offset has to be reduced by 1. HEAD always denotes the entity@HEAD
-        // *after* the successful transaction, so that it is consistent with subsequent retrieves.
-        final int offset = Integer.parseInt(version.substring(5)) - 1;
-        if (offset == 0) {
-          // special case HEAD~1
-          resulting_version = "HEAD";
-        } else {
-          resulting_version = new StringBuilder().append("HEAD~").append(offset).toString();
-        }
-      }
+    final Map<String, EntityInterface> cache = getCache("validEntityById");
+    String key = id.toString();
+    if (version != null && !version.equals("HEAD")) {
+      key += version;
     }
 
-    final EntityInterface ret =
-        execute(new RetrieveSparseEntity(id, resulting_version)).getEntity();
-    if (ret.getEntityStatus() == EntityStatus.NONEXISTENT) {
-      throw ServerMessages.ENTITY_DOES_NOT_EXIST;
+    result = cache.get(key);
+    if (result == null) {
+      result = retrieveValidLazyEntityByIdNoCache(id, version);
+      cache.put(key, result);
     }
-    return ret;
-  }
 
-  protected final EntityInterface retrieveValidEntity(final EntityID id) {
-    return execute(new RetrieveFullEntityTransaction(id)).getContainer().get(0);
+    return result;
   }
 
-  protected final EntityID retrieveValidIDByName(final String name) {
-    return execute(new GetIDByName(name)).getId();
+  private final EntityInterface retrieveValidLazyEntityByIdNoCache(
+      final EntityID id, final String version) {
+
+    final EntityInterface ret = execute(new RetrieveSparseEntity(id, version)).getEntity();
+    if (ret.getEntityStatus() == EntityStatus.NONEXISTENT) {
+      throw new EntityDoesNotExistException();
+    }
+    return new LazyEntityResolver(ret, getTransaction());
   }
 
-  protected EntityInterface retrieveParentsOfValidEntity(final EntityInterface entity) {
-    execute(new RetrieveParents(entity));
-    return entity;
+  protected final EntityID retrieveValidIDByName(final String name, String version) {
+    return execute(new GetIDByName(name, version)).getId();
   }
 
   /**
@@ -386,7 +374,7 @@ public abstract class Job {
     }
     if (dt instanceof ReferenceDatatype2) {
       return jobConfig.getConfiguredJobs(
-          EntityID.DEFAULT_DOMAIN, new EntityID(17), entity, transaction);
+          EntityID.DEFAULT_DOMAIN, new EntityID("17"), entity, transaction);
     } else if (dt instanceof AbstractCollectionDatatype) {
       final AbstractDatatype datatype = ((AbstractCollectionDatatype) dt).getDatatype();
       return loadDataTypeSpecificJobs(datatype, entity, transaction);
@@ -414,7 +402,8 @@ public abstract class Job {
 
     // load general rules
     final List<Job> generalRules =
-        jobConfig.getConfiguredJobs(EntityID.DEFAULT_DOMAIN, new EntityID(0), entity, transaction);
+        jobConfig.getConfiguredJobs(
+            EntityID.DEFAULT_DOMAIN, new EntityID("0"), entity, transaction);
     if (generalRules != null) {
       jobs.addAll(generalRules);
     }
@@ -544,10 +533,6 @@ public abstract class Job {
         + "]";
   }
 
-  public void print() {
-    System.out.println(toString());
-  }
-
   public TransactionStage getTransactionStage() {
     return this.stage;
   }
@@ -562,26 +547,72 @@ public abstract class Job {
    */
   protected EntityInterface resolve(final EntityInterface entity)
       throws EntityWasNotUniqueException {
-    EntityInterface resolvedEntity = null;
-    if (!entity.hasId() && entity.hasName()) {
-      resolvedEntity = getEntityByName(entity.getName());
+    return resolve(entity.getId(), entity.getName(), entity.getVersion());
+  }
+
+  protected EntityInterface resolve(EntityID id) {
+    return resolve(id, null, (String) null);
+  }
+
+  protected EntityInterface resolve(EntityID id, String name, String versionId)
+      throws EntityDoesNotExistException, EntityWasNotUniqueException {
+    EntityInterface resolvedEntity = getEntityById(id);
+
+    String resulting_version = versionId;
+    if (versionId == null || versionId.equals("HEAD")) {
+      resulting_version = null;
+      versionId = null;
+    } else if (versionId.startsWith("HEAD~")) {
       if (resolvedEntity == null) {
-        final EntityID eid = retrieveValidIDByName(entity.getName());
-        entity.setId(eid);
+        resolvedEntity = getEntityByName(name);
+      }
+      if (resolvedEntity != null && resolvedEntity.getEntityStatus() == EntityStatus.QUALIFIED) {
+        // if versionId is HEAD~{OFFSET} with {OFFSET} > 0 and the targeted entity is is to be
+        // updated, the actual offset has to be reduced by 1. HEAD always denotes the entity@HEAD
+        // *after* the successful transaction, so that it is consistent with subsequent retrieves.
+        final int offset = Integer.parseInt(versionId.substring(5)) - 1;
+        if (offset == 0) {
+          // special case HEAD~1
+          resulting_version = "HEAD";
+        } else {
+          resulting_version = new StringBuilder().append("HEAD~").append(offset).toString();
+        }
       }
+      resolvedEntity = null;
+    } else {
+      resolvedEntity = null;
     }
 
-    if (entity.hasId()) {
-      // get entity from container
-      resolvedEntity = getEntityById(entity.getId());
-      if (resolvedEntity == null && !entity.getId().isTemporary()) {
-        resolvedEntity = retrieveValidEntity(entity.getId());
+    if (resolvedEntity == null && id != null) {
+      try {
+        resolvedEntity = retrieveValidLazyEntityById(id, resulting_version);
+      } catch (EntityDoesNotExistException e) {
+        // ignore here, try to find by name.
       }
     }
 
+    // find by name in the container...
+    if (resolvedEntity == null && versionId == null) {
+      // from current transaction's container
+      resolvedEntity = getEntityByName(name);
+    }
+
+    if (resolvedEntity == null && name != null) {
+      // from database
+      resolvedEntity = retrieveValidLazyEntityByName(name, resulting_version);
+    }
+
+    if (resolvedEntity == null) {
+      throw new EntityDoesNotExistException();
+    }
     return resolvedEntity;
   }
 
+  protected EntityInterface resolve(EntityID id, String name, Version version) {
+    String versionId = version != null ? version.getId() : null;
+    return resolve(id, name, versionId);
+  }
+
   /**
    * Return those matching jobs which are annotated with the "loadAlways" attribute.
    *
@@ -598,4 +629,22 @@ public abstract class Job {
     }
     return jobs;
   }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj != null && obj instanceof Job) {
+      Job other = (Job) obj;
+      return other.getClass().equals(this.getClass())
+          && Objects.equals(other.getEntity(), this.getEntity())
+          && other.getFailureSeverity().equals(this.getFailureSeverity());
+    }
+    return false;
+  }
+
+  @Override
+  public int hashCode() {
+    return getClass().hashCode()
+        + (getEntity() == null ? 0 : getEntity().hashCode())
+        + getFailureSeverity().hashCode();
+  }
 }
diff --git a/src/main/java/org/caosdb/server/jobs/JobConfig.java b/src/main/java/org/caosdb/server/jobs/JobConfig.java
index ac53b605f5a0d9a5514403a1976b3e42650a75f2..ab6cd819fd338931aa32c41e2d9923ca716c9bf0 100644
--- a/src/main/java/org/caosdb/server/jobs/JobConfig.java
+++ b/src/main/java/org/caosdb/server/jobs/JobConfig.java
@@ -141,8 +141,8 @@ public class JobConfig {
           "Could not parse the job rules. Lines of five comma-separated values expected");
     }
     try {
-      final Integer domain = Integer.parseInt(row[0]);
-      final Integer entity = Integer.parseInt(row[1]);
+      final String domain = row[0];
+      final String entity = row[1];
       final String transaction = row[2];
       final String job = row[3];
       final JobFailureSeverity severity = JobFailureSeverity.valueOf(row[4]);
diff --git a/src/main/java/org/caosdb/server/jobs/LazyEntityResolver.java b/src/main/java/org/caosdb/server/jobs/LazyEntityResolver.java
new file mode 100644
index 0000000000000000000000000000000000000000..285378e16329d0a171eb55e550d916ac2a209a28
--- /dev/null
+++ b/src/main/java/org/caosdb/server/jobs/LazyEntityResolver.java
@@ -0,0 +1,62 @@
+package org.caosdb.server.jobs;
+
+import org.caosdb.server.database.backend.transaction.RetrieveParents;
+import org.caosdb.server.database.backend.transaction.RetrieveProperties;
+import org.caosdb.server.entity.EntityInterface;
+import org.caosdb.server.entity.container.ParentContainer;
+import org.caosdb.server.entity.container.PropertyContainer;
+import org.caosdb.server.entity.wrapper.EntityWrapper;
+import org.caosdb.server.transaction.Transaction;
+
+public class LazyEntityResolver extends EntityWrapper {
+
+  private Transaction<?> transaction;
+  private boolean propertiesResolved = false;
+  private boolean parentsResolved = false;
+
+  public LazyEntityResolver(EntityInterface entity, Transaction<?> transaction) {
+    super(entity);
+    this.transaction = transaction;
+  }
+
+  public void resolveParents() {
+    if (parentsResolved) return;
+    parentsResolved = true;
+    transaction.execute(new RetrieveParents(getWrapped()), transaction.getAccess());
+  }
+
+  private void resolveProperties() {
+    if (propertiesResolved) return;
+    propertiesResolved = true;
+    transaction.execute(new RetrieveProperties(getWrapped()), transaction.getAccess());
+  }
+
+  public void resolveAll() {
+    resolveParents();
+    resolveProperties();
+  }
+
+  @Override
+  public ParentContainer getParents() {
+    resolveParents();
+    return super.getParents();
+  }
+
+  @Override
+  public boolean hasParents() {
+    resolveParents();
+    return super.hasParents();
+  }
+
+  @Override
+  public PropertyContainer getProperties() {
+    resolveProperties();
+    return super.getProperties();
+  }
+
+  @Override
+  public boolean hasProperties() {
+    resolveProperties();
+    return super.hasProperties();
+  }
+}
diff --git a/src/main/java/org/caosdb/server/jobs/Schedule.java b/src/main/java/org/caosdb/server/jobs/Schedule.java
index 57474da515418745ed0457962596dfce233bff48..ab0f63a2105dacfea0fce0a7c5d553799b0ae222 100644
--- a/src/main/java/org/caosdb/server/jobs/Schedule.java
+++ b/src/main/java/org/caosdb/server/jobs/Schedule.java
@@ -44,7 +44,10 @@ public class Schedule {
   public List<ScheduledJob> addAll(final Collection<Job> jobs) {
     final List<ScheduledJob> result = new ArrayList<ScheduledJob>(jobs.size());
     for (final Job j : jobs) {
-      result.add(add(j));
+      ScheduledJob scheduledJob = add(j);
+      if (scheduledJob != null) {
+        result.add(scheduledJob);
+      }
     }
     return result;
   }
@@ -56,8 +59,11 @@ public class Schedule {
       jobs = new CopyOnWriteArrayList<ScheduledJob>();
       jobLists.put(ret.getTransactionStage().ordinal(), jobs);
     }
-    jobs.add(ret);
-    return ret;
+    if (!jobs.contains(ret)) {
+      jobs.add(ret);
+      return ret;
+    }
+    return null;
   }
 
   /** Run all Jobs from the specified {@link TransactionStage}. */
@@ -71,7 +77,7 @@ public class Schedule {
   }
 
   public void runJob(final ScheduledJob scheduledJob) {
-    if (scheduledJob.skip()) {
+    if (scheduledJob == null || scheduledJob.skip()) {
       return;
     }
     final ScheduledJob parent = this.running;
diff --git a/src/main/java/org/caosdb/server/jobs/ScheduledJob.java b/src/main/java/org/caosdb/server/jobs/ScheduledJob.java
index 2122b34de5f0b60db4c2b6d4c1c2358d3df02851..f729e0047c2f2ccc9b924b6650cbb64c7ec3749a 100644
--- a/src/main/java/org/caosdb/server/jobs/ScheduledJob.java
+++ b/src/main/java/org/caosdb/server/jobs/ScheduledJob.java
@@ -102,4 +102,18 @@ public class ScheduledJob {
   public Job getJob() {
     return job;
   }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof ScheduledJob) {
+      ScheduledJob other = (ScheduledJob) obj;
+      return this.job.equals(other.job);
+    }
+    return false;
+  }
+
+  @Override
+  public int hashCode() {
+    return job.hashCode();
+  }
 }
diff --git a/src/main/java/org/caosdb/server/jobs/core/CheckDatatypePresent.java b/src/main/java/org/caosdb/server/jobs/core/CheckDatatypePresent.java
index 40e01d2636509774555f1514c75bb0bf16870539..adc02cafb3c27162d00c8aded5db2eea9a2aa240 100644
--- a/src/main/java/org/caosdb/server/jobs/core/CheckDatatypePresent.java
+++ b/src/main/java/org/caosdb/server/jobs/core/CheckDatatypePresent.java
@@ -115,44 +115,15 @@ public final class CheckDatatypePresent extends EntityJob {
   }
 
   private void checkReference2(final ReferenceDatatype2 datatype) throws Message {
+    EntityInterface datatypeEntity = resolve(datatype.getId(), datatype.getName(), (String) null);
 
-    if (datatype.getId() == null) {
-      // try and get from container...
-      final EntityInterface datatypeEntity = getEntityByName(datatype.getName());
-
-      // if the container carried a corresponding entity
-      if (datatypeEntity != null) {
-        assertAllowedToUse(datatypeEntity);
-
-        // ... we set it as the datatypevalue
-        datatype.setEntity(datatypeEntity);
-      } else {
-
-        // else try and get from database.
-        final EntityInterface validDatatypeEntity =
-            retrieveValidSparseEntityByName(datatype.getName());
-        assertAllowedToUse(validDatatypeEntity);
-        datatype.setId(validDatatypeEntity.getId());
-      }
-    } else if (datatype.getId().isTemporary()) {
-      final EntityInterface datatypeEntity = getEntityById(datatype.getId());
-
-      // if the container carried a corresponding entity
-      if (datatypeEntity != null) {
-        assertAllowedToUse(datatypeEntity);
-        // ... we set it as the datatype
-        datatype.setEntity(datatypeEntity);
-      } else {
-
-        throw ServerMessages.UNKNOWN_DATATYPE;
-      }
-    } else {
-
-      final EntityInterface validDatatypeEntity =
-          retrieveValidSparseEntityById(datatype.getId(), null);
-      assertAllowedToUse(validDatatypeEntity);
-      datatype.setEntity(validDatatypeEntity);
+    if (datatypeEntity == null) {
+      throw ServerMessages.UNKNOWN_DATATYPE;
     }
+
+    // do the actual checking
+    assertAllowedToUse(datatypeEntity);
+    datatype.setEntity(datatypeEntity);
   }
 
   private void assertAllowedToUse(final EntityInterface datatype) {
@@ -160,62 +131,37 @@ public final class CheckDatatypePresent extends EntityJob {
   }
 
   private void checkIfOverride() throws Message {
-    if (getEntity().hasId() && !getEntity().getId().isTemporary()) {
-      // get data type from database
-      final EntityInterface foreign = retrieveValidSparseEntityById(getEntity().getId(), null);
-
-      if (foreign.hasDatatype() && !foreign.getDatatype().equals(getEntity().getDatatype())) {
-        // is override!
-        getEntity().setDatatypeOverride(true);
-      }
-    } else {
-      // get data type from container
-      EntityInterface abstractProperty = null;
-      if (getEntity().hasId()) {
-        abstractProperty = getEntityById(getEntity().getId());
-      } else if (getEntity().hasName()) {
-        abstractProperty = getEntityByName(getEntity().getName());
-      }
-      if (abstractProperty != null && abstractProperty.hasDatatype()) {
-        if (!getEntity().getDatatype().equals(abstractProperty.getDatatype())) {
-          // is override!
-          getEntity().setDatatypeOverride(true);
-        }
-      }
+    EntityInterface abstractProperty = resolve(getEntity());
+    if (abstractProperty != null
+        && abstractProperty.hasDatatype()
+        && !abstractProperty.getDatatype().equals(getEntity().getDatatype())) {
+      // is override!
+      getEntity().setDatatypeOverride(true);
     }
   }
 
   private void inheritDatatypeFromAbstractEntity() throws Message {
     // if this is a record type property or a concrete property, assign
     // the data type of the corresponding abstract property.
-    if (getEntity().hasId() && !getEntity().getId().isTemporary()) {
-      // get from data base
-      final EntityInterface foreign = retrieveValidSparseEntityById(getEntity().getId(), null);
-      inheritDatatypeFromForeignEntity(foreign);
-    } else if (getEntity().hasId() && getEntity().getId().isTemporary()) {
-      // get from container
-      final EntityInterface foreign = getEntityById(getEntity().getId());
-      inheritDatatypeFromForeignEntity(foreign);
-    }
-  }
-
-  private void inheritDatatypeFromForeignEntity(final EntityInterface foreign) {
-    if (foreign != null && foreign.hasDatatype()) {
-      getEntity().setDatatype(foreign.getDatatype());
-    } else if (foreign != null && foreign != getEntity() && foreign.getRole() == Role.RecordType) {
-      getEntity().setDatatype(ReferenceDatatype2.datatypeFactory(foreign.getId()));
+    EntityInterface abstractProperty = resolve(getEntity());
+    if (abstractProperty != null && abstractProperty.hasDatatype()) {
+      getEntity().setDatatype(abstractProperty.getDatatype());
+    } else if (abstractProperty != null
+        && abstractProperty != getEntity()
+        && abstractProperty.getRole() == Role.RecordType) {
+      getEntity().setDatatype(ReferenceDatatype2.datatypeFactory(abstractProperty.getId()));
     }
   }
 
   private void resolveId(final EntityInterface entity) {
     if (!entity.hasId() && entity.hasName()) {
       try {
-        entity.setId(retrieveValidIDByName(entity.getName()));
-        if (entity.getEntityStatus() != EntityStatus.UNQUALIFIED) {
-          entity.setEntityStatus(EntityStatus.VALID);
+        EntityInterface resolved = resolve(entity);
+        if (resolved == null) {
+          entity.addError(ServerMessages.ENTITY_DOES_NOT_EXIST);
+        } else {
+          entity.setId(resolved.getId());
         }
-      } catch (final EntityDoesNotExistException exc) {
-        entity.addError(ServerMessages.ENTITY_DOES_NOT_EXIST);
       } catch (final EntityWasNotUniqueException exc) {
         entity.addError(ServerMessages.ENTITY_NAME_DUPLICATES);
       }
@@ -227,14 +173,12 @@ public final class CheckDatatypePresent extends EntityJob {
 
     AbstractDatatype datatype = null;
     for (final EntityInterface parent : getEntity().getParents()) {
-      EntityInterface parentEntity = null;
-      if (!parent.getId().isTemporary()) {
-        parentEntity = retrieveValidSparseEntityById(parent.getId(), null);
-      } else {
-        parentEntity = getEntityById(parent.getId());
+      EntityInterface parentEntity = resolve(parent);
+      if (!parentEntity.hasDatatype() && parentEntity.getEntityStatus() == EntityStatus.QUALIFIED) {
         runJobFromSchedule(parentEntity, CheckDatatypePresent.class);
       }
-      if (parentEntity.hasDatatype()) {
+      if (parentEntity.hasDatatype()
+          && parentEntity.getEntityStatus() != EntityStatus.UNQUALIFIED) {
         if (datatype != null && !parentEntity.getDatatype().equals(datatype)) {
           getEntity().addError(ServerMessages.DATATYPE_INHERITANCE_AMBIGUOUS);
           return;
diff --git a/src/main/java/org/caosdb/server/jobs/core/CheckParOblPropPresent.java b/src/main/java/org/caosdb/server/jobs/core/CheckParOblPropPresent.java
index e6ba9da430e6218e5c40fba968c309ed94152bf6..eba79831468b1f6799507ca0866a64e594997caa 100644
--- a/src/main/java/org/caosdb/server/jobs/core/CheckParOblPropPresent.java
+++ b/src/main/java/org/caosdb/server/jobs/core/CheckParOblPropPresent.java
@@ -93,7 +93,7 @@ public class CheckParOblPropPresent extends EntityJob {
           // loop over all properties of the entity
           for (final EntityInterface entityProperty : getEntity().getProperties()) {
 
-            if (isSubType(entityProperty, parentProperty)) {
+            if (isSubType(resolve(entityProperty), parentProperty)) {
               // continue outer loop means that we
               // found an entityProperty that
               // implements the obligatory
diff --git a/src/main/java/org/caosdb/server/jobs/core/CheckParValid.java b/src/main/java/org/caosdb/server/jobs/core/CheckParValid.java
index 8895ae9adb4d12da2f7789a8798ca0fb9d183c05..e125e5dda8edbbecd3873a53e04755faba0874e3 100644
--- a/src/main/java/org/caosdb/server/jobs/core/CheckParValid.java
+++ b/src/main/java/org/caosdb/server/jobs/core/CheckParValid.java
@@ -60,73 +60,21 @@ public class CheckParValid extends EntityJob {
           if (!parent.hasId() && !parent.hasName()) {
             // The parent has neither an id nor a name.
             // Therefore it cannot be identified.
-
-            throw ServerMessages.ENTITY_HAS_NO_NAME_OR_ID;
+            parent.addError(ServerMessages.ENTITY_HAS_NO_NAME_OR_ID);
           }
-
-          if (parent.hasId()) {
-            // check parent by id
-            if (!parent.getId().isTemporary()) {
-              // id isn't temporary, i.e., parent is already in the database and
-              // can be retrieved by id
-              final EntityInterface foreign = retrieveValidSparseEntityById(parent.getId(), null);
-              // check permissions for this
-              // parentforeign.acceptObserver(o)
-              assertAllowedToUse(foreign);
-              parent.setAffiliation(getAffiliation(getEntity().getRole(), foreign.getRole()));
-              continue;
-            } else {
-              // id < 0 (parent is to be stored along with
-              // this entity)
-
-              // get entity with corresponding (negative) id
-              // from container
-              final EntityInterface foreign = getEntityById(parent.getId());
-
-              // if the container carried a corresponding
-              // entity
-              if (foreign != null) {
-                assertAllowedToUse(foreign);
-
-                parent.setAffiliation(getAffiliation(getEntity().getRole(), foreign.getRole()));
-
-                // ... we can set it as the parent
-                parent.linkIdToEntity(foreign);
-                continue;
-              }
-            }
-          }
-
-          // parent doesn't have an id.
-          if (parent.hasName()) {
-            if (getEntityByName(parent.getName()) != null) {
-              // get the parent entity from the container by its
-              // name
-              final EntityInterface foreign = getEntityByName(parent.getName());
-
-              assertAllowedToUse(foreign);
-              parent.setAffiliation(getAffiliation(getEntity().getRole(), foreign.getRole()));
-              parent.linkIdToEntity(foreign);
-              continue;
-            } else {
-              // check parent by name (parent is expected to be
-              // valid). This only works if the name is unique.
-              final EntityInterface foreign = retrieveValidSparseEntityByName(parent.getName());
-              assertAllowedToUse(foreign);
-              parent.setAffiliation(getAffiliation(getEntity().getRole(), foreign.getRole()));
-              parent.setId(foreign.getId());
-              continue;
-            }
+          try {
+            EntityInterface foreign = resolve(parent.getId(), parent.getName(), (String) null);
+            assertAllowedToUse(foreign);
+            parent.linkIdToEntity(foreign);
+            parent.setAffiliation(getAffiliation(getEntity().getRole(), foreign.getRole()));
+          } catch (EntityDoesNotExistException e) {
+            parent.addError(ServerMessages.ENTITY_DOES_NOT_EXIST);
           }
-
-          parent.addError(ServerMessages.ENTITY_DOES_NOT_EXIST);
         } catch (final Message m) {
           parent.addError(m);
         } catch (AuthorizationException e) {
           parent.addError(ServerMessages.AUTHORIZATION_ERROR);
           parent.addInfo(e.getMessage());
-        } catch (final EntityDoesNotExistException exc) {
-          parent.addError(ServerMessages.ENTITY_DOES_NOT_EXIST);
         } catch (final EntityWasNotUniqueException exc) {
           parent.addError(ServerMessages.ENTITY_NAME_DUPLICATES);
         }
diff --git a/src/main/java/org/caosdb/server/jobs/core/CheckPropValid.java b/src/main/java/org/caosdb/server/jobs/core/CheckPropValid.java
index 23a92340f5befbfbe7ded2fe95d3244b5ff78594..b57e7abbb1b98b24c107c17372a602370f79afe2 100644
--- a/src/main/java/org/caosdb/server/jobs/core/CheckPropValid.java
+++ b/src/main/java/org/caosdb/server/jobs/core/CheckPropValid.java
@@ -54,75 +54,21 @@ public class CheckPropValid extends EntityJob {
         if (property.getEntityStatus() == EntityStatus.QUALIFIED) {
           // this property is to be tested.
 
-          // does this property have an id at all?
-          if (property.hasId()) {
-            if (!property.getId().isTemporary()) {
-
-              final EntityInterface abstractProperty =
-                  retrieveValidSparseEntityById(property.getId(), null);
-
-              assertAllowedToUse(abstractProperty);
-
-              deriveOverrideStatus(property, abstractProperty);
-              continue;
-            } else {
-              // task here: find the corresponding abstract
-              // property (or rarely any other entity) in this
-              // container which has the same (negative) id.
-
-              // fetch the abstractProperty from the container.
-              final EntityInterface abstractProperty = getEntityById(property.getId());
-
-              if (abstractProperty != null) {
-                assertAllowedToUse(abstractProperty);
-
-                // link the id of the property to the id of
-                // the abstractProperty means. This has the
-                // effect that the property will have a
-                // valid id as soon as the abstractProperty
-                // has been inserted.
-                property.linkIdToEntity(abstractProperty);
-                deriveOverrideStatus(property, abstractProperty);
-                continue;
-              } else if (!property.hasName()) {
-                // an abstractProperty with this (negative) id
-                // had not been found in this container.
-                throw ENTITY_DOES_NOT_EXIST;
-              }
-            }
-          }
-
-          if (property.hasName()) {
-
-            // try and get it from the container
-            EntityInterface foreign = getEntityByName(property.getName());
-            if (foreign != null) {
-              assertAllowedToUse(foreign);
-
-              // link the id of the property to the id of
-              // the abstractProperty means. This has the
-              // effect that the property will have a
-              // valid id as soon as the abstractProperty
-              // has been inserted.
-              property.linkIdToEntity(foreign);
-              deriveOverrideStatus(property, foreign);
-            } else {
-              foreign = retrieveValidSparseEntityByName(property.getName());
-
-              assertAllowedToUse(foreign);
-
-              property.setId(foreign.getId());
-
-              deriveOverrideStatus(property, foreign);
-            }
-          }
-
           if (!property.hasName() && !property.hasId()) {
             // The property has neither an id nor a name.
             // Thus it cannot be identified.
 
             throw ServerMessages.ENTITY_HAS_NO_NAME_OR_ID;
           }
+          EntityInterface abstractProperty =
+              resolve(property.getId(), property.getName(), (String) null);
+          if (abstractProperty == null) {
+            property.addError(ENTITY_DOES_NOT_EXIST);
+            continue;
+          }
+          assertAllowedToUse(abstractProperty);
+          deriveOverrideStatus(property, abstractProperty);
+          property.linkIdToEntity(abstractProperty);
         }
       } catch (final Message m) {
         property.addError(m);
diff --git a/src/main/java/org/caosdb/server/jobs/core/CheckRefidIsaParRefid.java b/src/main/java/org/caosdb/server/jobs/core/CheckRefidIsaParRefid.java
index 0b8ba45b1cae19812641ed733be7aacc2fb78575..af7269a31756eb556729bf71f43bb0feda02bd67 100644
--- a/src/main/java/org/caosdb/server/jobs/core/CheckRefidIsaParRefid.java
+++ b/src/main/java/org/caosdb/server/jobs/core/CheckRefidIsaParRefid.java
@@ -82,24 +82,8 @@ public class CheckRefidIsaParRefid extends EntityJob implements Observer {
           for (final IndexedSingleValue v : vals) {
             if (v != null && v.getWrapped() != null) {
               final ReferenceValue rv = (ReferenceValue) v.getWrapped();
-              if (rv.getEntity() != null
-                  && rv.getEntity().hasRole()
-                  && rv.getEntity().getRole() == Role.File) {
-              } else if (rv.getId() != null
-                  && rv.getId().isTemporary()
-                  && getEntityById(rv.getId()) != null
-                  && getEntityById(rv.getId()).getRole() == Role.File) {
-              } else if (rv.getId() == null
-                  && rv.getName() != null
-                  && getEntityByName(rv.getName()) != null
-                  && getEntityByName(rv.getName()).getRole() == Role.File) {
-              } else if (rv.getId() != null
-                  && !rv.getId().isTemporary()
-                  && retrieveValidSparseEntityById(rv.getId(), rv.getVersion()).getRole()
-                      == Role.File) {
-              } else if (rv.getName() != null
-                  && retrieveValidSparseEntityByName(rv.getName()).getRole() == Role.File) {
-              } else {
+              EntityInterface referencedEntity = resolve(rv.getId(), rv.getName(), rv.getVersion());
+              if (referencedEntity.getRole() != Role.File) {
                 throw ServerMessages.REFERENCE_IS_NOT_ALLOWED_BY_DATATYPE;
               }
             }
diff --git a/src/main/java/org/caosdb/server/jobs/core/CheckRefidValid.java b/src/main/java/org/caosdb/server/jobs/core/CheckRefidValid.java
index 12b545b8e6fd608e20851d37f34e809acfcd1544..b01c5bf389175d1c087ced9acf4f135d7679a5be 100644
--- a/src/main/java/org/caosdb/server/jobs/core/CheckRefidValid.java
+++ b/src/main/java/org/caosdb/server/jobs/core/CheckRefidValid.java
@@ -83,61 +83,12 @@ public class CheckRefidValid extends EntityJob implements Observer {
   }
 
   private void checkRefValue(final ReferenceValue ref) throws Message {
-    if (ref.getId() != null) {
-      if (!ref.getId().isTemporary()) {
-        final EntityInterface referencedValidEntity =
-            retrieveValidSparseEntityById(ref.getId(), ref.getVersion());
-        assertAllowedToUse(referencedValidEntity);
-
-        // link the entity as versioned entity iff the reference specified a version
-        ref.setEntity(referencedValidEntity, ref.getVersion() != null);
-
-      } else {
-
-        // is the referenced entity yet linked to this refid
-        // property?
-        if (ref.getEntity() == null) {
-
-          // link the entity with the corresponding
-          // negative id to this reference object
-          final EntityInterface referencedEntity = getEntityById(ref.getId());
-          if (referencedEntity != null) {
-            assertAllowedToUse(referencedEntity);
-
-            // link the entity as versioned entity iff the reference specified a version
-            ref.setEntity(referencedEntity, ref.getVersion() != null);
-          } else {
-            throw ServerMessages.REFERENCED_ENTITY_DOES_NOT_EXIST;
-          }
-        }
-        ref.getEntity().acceptObserver(this);
-        checkRefEntity(ref);
-      }
-    } else if (ref.getName() != null) {
-      // is the referenced entity yet linked to this
-      // refid property?
-      if (ref.getEntity() == null) {
-        // the entity is in this container?
-        final EntityInterface referencedEntity = getEntityByName(ref.getName());
-
-        if (referencedEntity != null) {
-          assertAllowedToUse(referencedEntity);
-
-          // link the entity as versioned entity iff the reference specified a version
-          ref.setEntity(referencedEntity, ref.getVersion() != null);
-          if (checkRefEntity(ref)) {
-            ref.getEntity().acceptObserver(this);
-          }
-        } else {
-          final EntityInterface referencedValidEntity =
-              retrieveValidSparseEntityByName(ref.getName());
-          assertAllowedToUse(referencedValidEntity);
-
-          // link the entity as versioned entity iff the reference specified a version
-          ref.setEntity(referencedValidEntity, ref.getVersion() != null);
-        }
-      }
+    EntityInterface referencedEntity = resolve(ref.getId(), ref.getName(), ref.getVersion());
+    if (referencedEntity == null) {
+      throw ServerMessages.REFERENCED_ENTITY_DOES_NOT_EXIST;
     }
+    assertAllowedToUse(referencedEntity);
+    ref.setEntity(referencedEntity, ref.getVersion() != null);
   }
 
   private void assertAllowedToUse(final EntityInterface referencedEntity) {
diff --git a/src/main/java/org/caosdb/server/jobs/core/EntityStateJob.java b/src/main/java/org/caosdb/server/jobs/core/EntityStateJob.java
index a4c50f8893935d7bbd6091b970b32a8811a08d93..409718012086063c7de9f5db003b965a188cc061 100644
--- a/src/main/java/org/caosdb/server/jobs/core/EntityStateJob.java
+++ b/src/main/java/org/caosdb/server/jobs/core/EntityStateJob.java
@@ -53,6 +53,7 @@ import org.caosdb.server.entity.container.TransactionContainer;
 import org.caosdb.server.entity.wrapper.Property;
 import org.caosdb.server.entity.xml.ToElementable;
 import org.caosdb.server.jobs.EntityJob;
+import org.caosdb.server.jobs.LazyEntityResolver;
 import org.caosdb.server.permissions.EntityACI;
 import org.caosdb.server.permissions.EntityACL;
 import org.caosdb.server.query.Query;
@@ -572,7 +573,7 @@ public abstract class EntityStateJob extends EntityJob {
             final String key = "transition" + refid.toString();
             EntityInterface transition = getCached(key);
             if (transition == null) {
-              transition = retrieveValidEntity(refid);
+              transition = resolve(refid);
               putCache(key, transition);
             }
             result.add(new Transition(transition));
@@ -659,7 +660,7 @@ public abstract class EntityStateJob extends EntityJob {
 
   private EntityInterface retrieveStateEntity(final String stateName) throws Message {
     try {
-      return retrieveValidEntity(retrieveValidIDByName(stateName));
+      return resolve(null, stateName, (String) null);
     } catch (final EntityDoesNotExistException e) {
       throw STATE_NOT_IN_STATE_MODEL;
     }
@@ -667,7 +668,7 @@ public abstract class EntityStateJob extends EntityJob {
 
   private EntityInterface retrieveStateModelEntity(final String stateModel) throws Message {
     try {
-      return retrieveValidEntity(retrieveValidIDByName(stateModel));
+      return resolve(null, stateModel, (String) null);
     } catch (final EntityDoesNotExistException e) {
       throw STATE_MODEL_NOT_FOUND;
     }
@@ -676,7 +677,7 @@ public abstract class EntityStateJob extends EntityJob {
   protected EntityInterface getStateRecordType() throws Message {
     EntityInterface stateRecordType = getCached(STATE_RECORD_TYPE_NAME);
     if (stateRecordType == null) {
-      stateRecordType = retrieveValidSparseEntityByName(STATE_RECORD_TYPE_NAME);
+      stateRecordType = resolve(null, STATE_RECORD_TYPE_NAME, (String) null);
       putCache(STATE_RECORD_TYPE_NAME, stateRecordType);
     }
     return stateRecordType;
@@ -797,7 +798,7 @@ public abstract class EntityStateJob extends EntityJob {
 
       EntityInterface stateEntity = getCached(key);
       if (stateEntity == null) {
-        stateEntity = retrieveValidEntity(refid.getId());
+        stateEntity = resolve(refid.getId());
         putCache(key, stateEntity);
       }
 
@@ -834,7 +835,7 @@ public abstract class EntityStateJob extends EntityJob {
             getUser(),
             c);
     query.execute(getTransaction().getAccess());
-    result = retrieveValidEntity(c.get(0).getId());
+    result = resolve(c.get(0).getId());
     putCache(key, result);
     return result;
   }
@@ -852,6 +853,11 @@ public abstract class EntityStateJob extends EntityJob {
       if (value instanceof DeleteEntity) {
         throw new RuntimeException("Delete entity in cache. This is an implementation error.");
       }
+      if (value instanceof LazyEntityResolver) {
+        // resolve immediately, otherwise the access might be released when
+        // the object is being resolved.
+        ((LazyEntityResolver) value).resolveAll();
+      }
       id_in_cache.add(value.getId());
       cache.put(key, value);
     }
diff --git a/src/main/java/org/caosdb/server/jobs/core/Inheritance.java b/src/main/java/org/caosdb/server/jobs/core/Inheritance.java
index a1bd800c7ca40b28d7b9ff27dd8f828ed112891f..7bcda3b96cd64bf233444e429b72bb74ca69333d 100644
--- a/src/main/java/org/caosdb/server/jobs/core/Inheritance.java
+++ b/src/main/java/org/caosdb/server/jobs/core/Inheritance.java
@@ -27,12 +27,10 @@ package org.caosdb.server.jobs.core;
 import java.util.ArrayList;
 import java.util.List;
 import org.caosdb.api.entity.v1.MessageCode;
-import org.caosdb.server.database.backend.transaction.RetrieveFullEntityTransaction;
 import org.caosdb.server.entity.EntityInterface;
 import org.caosdb.server.entity.InsertEntity;
 import org.caosdb.server.entity.Message;
 import org.caosdb.server.entity.Message.MessageType;
-import org.caosdb.server.entity.RetrieveEntity;
 import org.caosdb.server.entity.StatementStatus;
 import org.caosdb.server.entity.UpdateEntity;
 import org.caosdb.server.entity.wrapper.Property;
@@ -88,12 +86,7 @@ public class Inheritance extends EntityJob {
             runJobFromSchedule(getEntity(), CheckParValid.class);
 
             // try to get the parent entity from the current transaction container
-            EntityInterface foreign = getEntityByName(parent.getName());
-            if (foreign == null) {
-              // was not in container -> retrieve from database.
-              execute(new RetrieveFullEntityTransaction(parent));
-              foreign = parent;
-            }
+            EntityInterface foreign = resolve(parent);
 
             collectInheritedProperties(transfer, foreign, inheritance);
           } catch (final IllegalArgumentException e) {
@@ -136,26 +129,24 @@ public class Inheritance extends EntityJob {
               break propertyLoop;
             }
 
-            EntityInterface validProperty = new RetrieveEntity(property.getId());
+            EntityInterface abstractProperty = null;
             if (getEntity().hasParents()) {
               outer:
               for (EntityInterface par : getEntity().getParents()) {
-                if (!par.hasProperties()) {
-                  par = resolve(par);
-                }
+                par = resolve(par);
                 for (final EntityInterface prop : par.getProperties()) {
-                  if (validProperty.hasId() && validProperty.getId().equals(prop.getId())) {
-                    validProperty = prop;
+                  if ((property.hasId() && property.getId().equals(prop.getId()))
+                      || property.hasName() && property.getName().equals(prop.getName())) {
+                    abstractProperty = prop;
                     break outer;
                   }
                 }
               }
-            } else {
-              execute(new RetrieveFullEntityTransaction(validProperty));
             }
-            if (validProperty.getEntityStatus() == EntityStatus.VALID) {
-              collectInheritedProperties(transfer, validProperty, inheritance);
+            if (abstractProperty == null) {
+              abstractProperty = resolve(property);
             }
+            collectInheritedProperties(transfer, abstractProperty, inheritance);
           } catch (final IllegalArgumentException e) {
             property.addWarning(ILLEGAL_INHERITANCE_MODE);
             break propertyLoop;
diff --git a/src/main/java/org/caosdb/server/jobs/core/NoCache.java b/src/main/java/org/caosdb/server/jobs/core/NoCache.java
index e408330ee2639d1c5d7dc5f145848e292daa9b3b..6ad38f49268fae7d38612cbf552b7c8cd2d68b85 100644
--- a/src/main/java/org/caosdb/server/jobs/core/NoCache.java
+++ b/src/main/java/org/caosdb/server/jobs/core/NoCache.java
@@ -37,6 +37,6 @@ public class NoCache extends FlagJob {
 
   @Override
   protected void job(final String value) {
-    getTransaction().getAccess().setUseCache(Boolean.valueOf(value));
+    getTransaction().setUseCache(Boolean.valueOf(value));
   }
 }
diff --git a/src/main/java/org/caosdb/server/jobs/core/ProcessNameProperties.java b/src/main/java/org/caosdb/server/jobs/core/ProcessNameProperties.java
index cbcf738ee99716f58e2ca9a9526497e7b9113029..1fdd59e2327425b56b02d478eb1b31f4c135ce5b 100644
--- a/src/main/java/org/caosdb/server/jobs/core/ProcessNameProperties.java
+++ b/src/main/java/org/caosdb/server/jobs/core/ProcessNameProperties.java
@@ -28,6 +28,7 @@ import java.util.Collection;
 import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.Set;
+import org.caosdb.server.database.exceptions.EntityDoesNotExistException;
 import org.caosdb.server.datatype.AbstractDatatype;
 import org.caosdb.server.entity.EntityID;
 import org.caosdb.server.entity.EntityInterface;
@@ -142,12 +143,13 @@ public class ProcessNameProperties extends EntityJob {
       }
       return ret;
     } else if (prop.hasId()) {
-      EntityInterface propertyEntity = getEntityById(prop.getId());
-      if (propertyEntity == null) {
-        propertyEntity = retrieveValidEntity(prop.getId());
-      }
-      if (propertyEntity != null) {
-        return getNearestValidParents(propertyEntity);
+      try {
+        EntityInterface propertyEntity = resolve(prop.getId());
+        if (propertyEntity != null) {
+          return getNearestValidParents(propertyEntity);
+        }
+      } catch (EntityDoesNotExistException e) {
+        // return null
       }
       return null;
     } else {
diff --git a/src/main/java/org/caosdb/server/jobs/core/ResolveNames.java b/src/main/java/org/caosdb/server/jobs/core/ResolveNames.java
index 5ab722c7176e89485e2bd40dfd515a77bc09e38b..d1ab07b7bf5edb967abda9d23bb9828c0acfd69e 100644
--- a/src/main/java/org/caosdb/server/jobs/core/ResolveNames.java
+++ b/src/main/java/org/caosdb/server/jobs/core/ResolveNames.java
@@ -25,6 +25,7 @@ package org.caosdb.server.jobs.core;
 import java.util.ArrayList;
 import java.util.List;
 import org.caosdb.server.database.backend.transaction.GetIDByName;
+import org.caosdb.server.database.backend.transaction.RetrieveSparseEntity;
 import org.caosdb.server.database.exceptions.EntityDoesNotExistException;
 import org.caosdb.server.entity.Entity;
 import org.caosdb.server.entity.EntityID;
@@ -45,6 +46,20 @@ public class ResolveNames extends ContainerJob {
   public void resolve(final TransactionContainer container) {
     final ArrayList<Entity> add = new ArrayList<Entity>();
     for (final EntityInterface e : container) {
+      if (!e.hasId() && e.hasName() && getTransaction().matchIdPattern(e.getName())) {
+        try {
+          EntityInterface valid =
+              execute(
+                      new RetrieveSparseEntity(
+                          new EntityID(e.getName()),
+                          e.hasVersion() ? e.getVersion().getId() : null))
+                  .getEntity();
+          e.setId(valid.getId());
+        } catch (final EntityDoesNotExistException exc) {
+          // definitely not an id.
+        }
+      }
+
       if (e.hasName() && !e.hasId()) {
         try {
           final List<EntityID> c = execute(new GetIDByName(e.getName(), false)).getList();
diff --git a/src/main/java/org/caosdb/server/jobs/core/UniqueName.java b/src/main/java/org/caosdb/server/jobs/core/UniqueName.java
index 86e6c37e35ec91db647e14e30896abb6b884555b..079afdd9a922fa5758e5f4eb6bec80538338db21 100644
--- a/src/main/java/org/caosdb/server/jobs/core/UniqueName.java
+++ b/src/main/java/org/caosdb/server/jobs/core/UniqueName.java
@@ -40,7 +40,7 @@ public class UniqueName extends FlagJob {
 
       // check against data base
       try {
-        final EntityID foreign = retrieveValidIDByName(entity.getName());
+        final EntityID foreign = retrieveValidIDByName(entity.getName(), null);
         if (entity.hasId() && !foreign.equals(entity.getId())) {
           throw new EntityWasNotUniqueException();
         }
diff --git a/src/main/java/org/caosdb/server/query/Query.java b/src/main/java/org/caosdb/server/query/Query.java
index ad3fb778c67c1390973fab1d8ed6391a0f5b7317..038e4d1895c3025759a8d259f27bcd246ac4f683 100644
--- a/src/main/java/org/caosdb/server/query/Query.java
+++ b/src/main/java/org/caosdb/server/query/Query.java
@@ -3,8 +3,8 @@
  *
  * Copyright (C) 2018 Research Group Biomedical Physics,
  * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
- * Copyright (C) 2019-2021 IndiScale GmbH <info@indiscale.com>
- * Copyright (C) 2019-2021 Timm Fitschen <t.fitschen@indiscale.com>
+ * Copyright (C) 2019-2023 IndiScale GmbH <info@indiscale.com>
+ * Copyright (C) 2019-2023 Timm Fitschen <t.fitschen@indiscale.com>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -73,7 +73,6 @@ import org.caosdb.server.query.CQLParser.CqContext;
 import org.caosdb.server.query.CQLParsingErrorListener.ParsingError;
 import org.caosdb.server.transaction.TransactionInterface;
 import org.caosdb.server.transaction.WriteTransaction;
-import org.caosdb.server.utils.ResultSetIterator;
 import org.jdom2.Element;
 import org.slf4j.Logger;
 
@@ -218,22 +217,22 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac
 
   /** A data class for storing triplets of (Entity ID, version hash, ACL string) */
   public static class IdVersionAclTriplet {
-    public IdVersionAclTriplet(final Integer id, final String version, final String acl) {
+    public IdVersionAclTriplet(final String id, final String version, final String acl) {
       this.id = id;
       this.version = version;
       this.acl = acl;
     }
 
-    public Integer id;
+    public String id;
     public String version;
     public String acl;
 
     @Override
     public String toString() {
       if (version == null) {
-        return Integer.toString(id);
+        return id;
       }
-      return Integer.toString(id) + "@" + version;
+      return id + "@" + version;
     }
 
     @Override
@@ -256,6 +255,14 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac
     public int hashCode() {
       return toString().hashCode();
     }
+
+    public boolean isInternal() {
+      try {
+        return Integer.parseInt(id) < 101;
+      } catch (NumberFormatException e) {
+        return false;
+      }
+    }
   }
 
   private final boolean filterEntitiesWithoutRetrievePermisions =
@@ -480,7 +487,7 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac
                       + "` AS r ON (r.id=q.id);");
       rs = stmt.executeQuery();
       while (rs.next()) {
-        ret.put(new EntityID(rs.getInt("id")), rs.getString("definition"));
+        ret.put(new EntityID(rs.getString("id")), rs.getString("definition"));
       }
       return ret;
     } finally {
@@ -652,9 +659,8 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac
   private String generateSelectStatementForResultSet(
       final String resultSetTableName, final boolean versioned) {
     if (resultSetTableName.equals("entity_ids")) {
-      // TODO remove "DOMAIN"
       final String baseStatement =
-          "SELECT entities.id AS internal_id, (SELECT id FROM entity_ids WHERE internal_id = entities.id) as id, entity_acl.acl FROM entities INNER JOIN entity_acl ON entity_acl.id=entities.acl WHERE entities.role!='DOMAIN'";
+          "SELECT entities.id AS internal_id, (SELECT id FROM entity_ids WHERE internal_id = entities.id) as id, entity_acl.acl FROM entities INNER JOIN entity_acl ON entity_acl.id=entities.acl";
       if (!versioned) {
         return baseStatement + ";";
       }
@@ -667,7 +673,7 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac
         return (" SELECT (SELECT id FROM entity_ids WHERE internal_id = tmp.id) AS id, entity_acl.acl FROM "
                 + " (SELECT results.id AS id, entities.acl AS acl_id FROM `"
                 + resultSetTableName
-                + "` AS results JOIN entities ON results.id=entities.id WHERE entities.role!='DOMAIN') AS tmp"
+                + "` AS results JOIN entities ON results.id=entities.id) AS tmp"
                 + " JOIN entity_acl ON entity_acl.id=tmp.acl_id")
             + ";";
       }
@@ -698,10 +704,14 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac
       finishResultSet = finish.executeQuery();
       final List<IdVersionAclTriplet> rs = new LinkedList<>();
       while (finishResultSet.next()) {
+        final String id = finishResultSet.getString("id");
+        if (finishResultSet.wasNull()) {
+          continue;
+        }
         final String version = versioned ? finishResultSet.getString("version") : null;
         final String acl = finishResultSet.getString("acl");
 
-        rs.add(new IdVersionAclTriplet(finishResultSet.getInt("id"), version, acl));
+        rs.add(new IdVersionAclTriplet(id, version, acl));
       }
       return rs;
     } catch (final SQLException e) {
@@ -804,7 +814,7 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac
     final List<IdVersionAclTriplet> filtered = new ArrayList<>();
     for (final IdVersionAclTriplet triplet : resultSet) {
 
-      if (triplet.id >= 100) {
+      if (!triplet.isInternal()) {
         filtered.add(triplet);
       }
     }
@@ -914,11 +924,11 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac
               + "left join entity_acl on entity_n_acl.acl=entity_acl.id;");
       final ResultSet entitiesRS = stmt.executeQuery(query);
       final ResultSetIterator entitiesWithACL = new ResultSetIterator(entitiesRS);
-      final List<Integer> toBeDeleted = collectIdsWithoutPermission(entitiesWithACL);
+      final List<String> toBeDeleted = collectIdsWithoutPermission(entitiesWithACL);
       try (final PreparedStatement pstmt =
           this.getConnection().prepareStatement("DELETE FROM `" + tabname + "` WHERE id = ?")) {
-        for (final Integer id : toBeDeleted) {
-          pstmt.setInt(1, id);
+        for (final String id : toBeDeleted) {
+          pstmt.setString(1, id);
           pstmt.execute();
         }
       }
@@ -937,8 +947,8 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac
    */
   private List<IdVersionAclTriplet> filterEntitiesWithoutRetrievePermission(
       final List<IdVersionAclTriplet> resultSet) {
-    final List<Integer> toBeDeleted = collectIdsWithoutPermission(resultSet.iterator());
-    final List<IdVersionAclTriplet> filtered = new ArrayList<>();
+    final List<String> toBeDeleted = collectIdsWithoutPermission(resultSet.iterator());
+    final List<IdVersionAclTriplet> filtered = new LinkedList<>();
     for (final IdVersionAclTriplet triplet : resultSet) {
       if (-1 == toBeDeleted.indexOf(triplet.id)) {
         filtered.add(triplet);
@@ -953,9 +963,9 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac
    *     triplets.
    * @return compiled list
    */
-  private List<Integer> collectIdsWithoutPermission(Iterator<IdVersionAclTriplet> entityIterator) {
-    final HashMap<String, Boolean> acl_cache = new HashMap<String, Boolean>();
-    final List<Integer> toBeDeleted = new LinkedList<Integer>();
+  private List<String> collectIdsWithoutPermission(Iterator<IdVersionAclTriplet> entityIterator) {
+    final Map<String, Boolean> acl_cache = new HashMap<>();
+    final List<String> toBeDeleted = new LinkedList<>();
     while (entityIterator.hasNext()) {
       final long t1 = System.currentTimeMillis();
 
diff --git a/src/main/java/org/caosdb/server/utils/ResultSetIterator.java b/src/main/java/org/caosdb/server/query/ResultSetIterator.java
similarity index 95%
rename from src/main/java/org/caosdb/server/utils/ResultSetIterator.java
rename to src/main/java/org/caosdb/server/query/ResultSetIterator.java
index 71429f1a704299555ab1d86be0695e3104be828d..27c5e9226ac153bc65e2a42b15d3539f61526c89 100644
--- a/src/main/java/org/caosdb/server/utils/ResultSetIterator.java
+++ b/src/main/java/org/caosdb/server/query/ResultSetIterator.java
@@ -1,4 +1,4 @@
-package org.caosdb.server.utils;
+package org.caosdb.server.query;
 
 import static org.caosdb.server.database.backend.implementation.MySQL.DatabaseUtils.bytes2UTF8;
 
@@ -50,7 +50,7 @@ public class ResultSetIterator implements Iterator<IdVersionAclTriplet> {
       throw new NoSuchElementException();
     }
     try {
-      final Integer id = resultSet.getInt("id");
+      final String id = resultSet.getString("id");
       final String acl_str = bytes2UTF8(resultSet.getBytes("ACL"));
       return new IdVersionAclTriplet(id, "", acl_str);
     } catch (SQLException e) {
diff --git a/src/main/java/org/caosdb/server/resource/UserResource.java b/src/main/java/org/caosdb/server/resource/UserResource.java
index de07331e9637549285d71ca2fd910916cd13316a..362e5eb661cd05ef2098aad5baa1604f8cd5dc09 100644
--- a/src/main/java/org/caosdb/server/resource/UserResource.java
+++ b/src/main/java/org/caosdb/server/resource/UserResource.java
@@ -104,12 +104,12 @@ public class UserResource extends AbstractCaosDBServerResource {
           form.getFirstValue("status") != null
               ? UserStatus.valueOf(form.getFirstValue("status").toUpperCase())
               : null;
-      Integer userEntity = null;
+      String userEntity = null;
       if (form.getFirst("entity") != null) {
         if (form.getFirstValue("entity").isEmpty()) {
-          userEntity = 0;
+          userEntity = "";
         } else {
-          userEntity = Integer.parseInt(form.getFirstValue("entity"));
+          userEntity = form.getFirstValue("entity");
         }
       }
 
@@ -150,9 +150,9 @@ public class UserResource extends AbstractCaosDBServerResource {
                     "status",
                     CaosDBServer.getServerProperty(ServerProperties.KEY_NEW_USER_DEFAULT_ACTIVITY))
                 .toUpperCase());
-    Integer userEntity = null;
+    String userEntity = null;
     if (form.getFirst("entity") != null) {
-      userEntity = Integer.parseInt(form.getFirstValue("entity"));
+      userEntity = form.getFirstValue("entity");
     }
 
     final InsertUserTransaction t =
diff --git a/src/main/java/org/caosdb/server/resource/transaction/EntityResource.java b/src/main/java/org/caosdb/server/resource/transaction/EntityResource.java
index 4cd7b2fcbd4ae9e9dd3d047555194172c4224d38..c920d8c92ce48258822d3ac1c6eed913fbbe84d7 100644
--- a/src/main/java/org/caosdb/server/resource/transaction/EntityResource.java
+++ b/src/main/java/org/caosdb/server/resource/transaction/EntityResource.java
@@ -67,18 +67,14 @@ public class EntityResource extends RetrieveEntityResource {
 
     for (final String item : getRequestedItems()) {
       final String[] elem = item.split("@", 1);
-      Integer id = null;
+      String id = null;
       String version = null;
-      try {
-        id = Integer.parseInt(elem[0]);
-      } catch (final NumberFormatException e) {
-        // pass
-      }
+      id = elem[0];
       if (elem.length > 1) {
         version = elem[1];
       }
 
-      if (id != null && id > 0) {
+      if (id != null) {
         container.add(new DeleteEntity(new EntityID(id), version));
       }
     }
diff --git a/src/main/java/org/caosdb/server/resource/transaction/RetrieveEntityResource.java b/src/main/java/org/caosdb/server/resource/transaction/RetrieveEntityResource.java
index 6527376d71ba31718394f887b7335615d80db5c6..8f2809b27e420da7e014088a15a07d7b5405b098 100644
--- a/src/main/java/org/caosdb/server/resource/transaction/RetrieveEntityResource.java
+++ b/src/main/java/org/caosdb/server/resource/transaction/RetrieveEntityResource.java
@@ -26,7 +26,6 @@ import java.security.NoSuchAlgorithmException;
 import java.sql.SQLException;
 import org.caosdb.server.CaosDBException;
 import org.caosdb.server.database.backend.implementation.MySQL.ConnectionException;
-import org.caosdb.server.entity.EntityID;
 import org.caosdb.server.entity.container.RetrieveContainer;
 import org.caosdb.server.resource.AbstractCaosDBServerResource;
 import org.caosdb.server.transaction.Retrieve;
@@ -51,23 +50,14 @@ public abstract class RetrieveEntityResource extends AbstractCaosDBServerResourc
 
     for (final String item : getRequestedItems()) {
       final String[] elem = item.split("@", 2);
-      Integer id = null;
-      String name = null;
+      String id = null;
       String version = null;
-      try {
-        id = Integer.parseInt(elem[0]);
-      } catch (final NumberFormatException e) {
-        name = elem[0];
-      }
+      id = elem[0];
       if (elem.length > 1) {
         version = elem[1];
       }
 
-      if (id != null) {
-        container.add(new EntityID(id), version);
-      } else {
-        container.add(name);
-      }
+      container.add(null, id, version);
     }
   }
 
diff --git a/src/main/java/org/caosdb/server/transaction/EntityTransactionInterface.java b/src/main/java/org/caosdb/server/transaction/EntityTransactionInterface.java
new file mode 100644
index 0000000000000000000000000000000000000000..dc98f826bff2c3ebed809f45b1f05a197e61b9a7
--- /dev/null
+++ b/src/main/java/org/caosdb/server/transaction/EntityTransactionInterface.java
@@ -0,0 +1,12 @@
+package org.caosdb.server.transaction;
+
+import org.caosdb.server.entity.EntityID;
+
+public interface EntityTransactionInterface extends TransactionInterface {
+
+  public boolean matchIdPattern(String id);
+
+  public default boolean matchIdPattern(EntityID id) {
+    return id != null && matchIdPattern(id.toString());
+  }
+}
diff --git a/src/main/java/org/caosdb/server/transaction/InsertUserTransaction.java b/src/main/java/org/caosdb/server/transaction/InsertUserTransaction.java
index f3f4c7f5fd583ff0ff16d4fd1ce583394258f35b..3174dabf4e3d6a581f27aaf59cb8ffd866401bf5 100644
--- a/src/main/java/org/caosdb/server/transaction/InsertUserTransaction.java
+++ b/src/main/java/org/caosdb/server/transaction/InsertUserTransaction.java
@@ -50,7 +50,7 @@ public class InsertUserTransaction extends AccessControlTransaction {
       final String password,
       final String email,
       final UserStatus status,
-      final Integer entity) {
+      final String entity) {
     this(new ProtoUser(), password);
     this.user.realm = UserSources.getInternalRealm().getName();
     this.user.name = username;
diff --git a/src/main/java/org/caosdb/server/transaction/Retrieve.java b/src/main/java/org/caosdb/server/transaction/Retrieve.java
index 643c1201b530af9821c9a5c1a7b62f7c5d04cf52..4fc4fbc2c534aba2d24793d1efd3cbc6d1512914 100644
--- a/src/main/java/org/caosdb/server/transaction/Retrieve.java
+++ b/src/main/java/org/caosdb/server/transaction/Retrieve.java
@@ -115,6 +115,21 @@ public class Retrieve extends Transaction<RetrieveContainer> {
   private void retrieveFullEntities(final RetrieveContainer container, final Access access)
       throws Exception {
     execute(new RetrieveFullEntityTransaction(container), access);
+    for (EntityInterface e : container) {
+      if (e.getEntityStatus() == EntityStatus.NONEXISTENT
+          && e.hasId()
+          && e.hasName()
+          && e.getName().equals(e.getId().toString())) {
+        // remove duplicates by name
+        for (EntityInterface o : container) {
+          if (o.getEntityStatus() == EntityStatus.VALID
+              && o.hasName()
+              && e.getName().equalsIgnoreCase(o.getName())) {
+            e.setEntityStatus(EntityStatus.IGNORE);
+          }
+        }
+      }
+    }
   }
 
   @Override
diff --git a/src/main/java/org/caosdb/server/transaction/RetrieveACL.java b/src/main/java/org/caosdb/server/transaction/RetrieveACL.java
index ac0a2896451a43ca10985bd38787ad4f847a05cc..b5a4a489c60269dbae906bba1942f8e9525eb710 100644
--- a/src/main/java/org/caosdb/server/transaction/RetrieveACL.java
+++ b/src/main/java/org/caosdb/server/transaction/RetrieveACL.java
@@ -40,7 +40,7 @@ public class RetrieveACL extends Transaction<TransactionContainer> {
         new TransactionContainer(
             SecurityUtils.getSubject(), System.currentTimeMillis(), UUID.randomUUID().toString()));
     for (String strId : idList) {
-      getContainer().add(new RetrieveEntity(new EntityID(Integer.parseInt(strId))));
+      getContainer().add(new RetrieveEntity(new EntityID(strId)));
     }
   }
 
diff --git a/src/main/java/org/caosdb/server/transaction/RetrieveUserTransaction.java b/src/main/java/org/caosdb/server/transaction/RetrieveUserTransaction.java
index eb24fb24db4f1b6a50a279cfcd9e158003a70948..72a1d61929e692e551a53013ac1aabb1a4f28f5a 100644
--- a/src/main/java/org/caosdb/server/transaction/RetrieveUserTransaction.java
+++ b/src/main/java/org/caosdb/server/transaction/RetrieveUserTransaction.java
@@ -77,7 +77,7 @@ public class RetrieveUserTransaction extends AccessControlTransaction {
       ret.setAttribute("email", user.email);
     }
     if (user.entity != null) {
-      ret.setAttribute("entity", Integer.toString(user.entity));
+      ret.setAttribute("entity", user.entity);
     }
     if (user.status != null) {
       ret.setAttribute("status", user.status.toString());
diff --git a/src/main/java/org/caosdb/server/transaction/Transaction.java b/src/main/java/org/caosdb/server/transaction/Transaction.java
index 5fc06f5ec82066d3515cbf524e64beb001ba0fcd..8474125d3c83d6445bb44c9d8ef0ff20759d20b7 100644
--- a/src/main/java/org/caosdb/server/transaction/Transaction.java
+++ b/src/main/java/org/caosdb/server/transaction/Transaction.java
@@ -21,8 +21,12 @@
  */
 package org.caosdb.server.transaction;
 
+import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
 import org.apache.shiro.subject.Subject;
 import org.caosdb.datetime.UTCDateTime;
 import org.caosdb.server.accessControl.Principal;
@@ -31,6 +35,7 @@ import org.caosdb.server.database.access.Access;
 import org.caosdb.server.database.backend.transaction.InsertTransactionHistory;
 import org.caosdb.server.database.exceptions.TransactionException;
 import org.caosdb.server.database.misc.TransactionBenchmark;
+import org.caosdb.server.entity.EntityIdRegistry;
 import org.caosdb.server.entity.EntityInterface;
 import org.caosdb.server.entity.Message;
 import org.caosdb.server.entity.container.TransactionContainer;
@@ -47,9 +52,73 @@ import org.caosdb.server.permissions.EntityACL;
 import org.caosdb.server.utils.AbstractObservable;
 import org.caosdb.server.utils.Info;
 import org.caosdb.server.utils.Observer;
+import org.caosdb.server.utils.UseCacheResource;
+import org.caosdb.server.utils.UseCacheResourceDelegate;
+
+@SuppressWarnings("rawtypes")
+class NoOpCache implements Map {
+
+  @Override
+  public int size() {
+    // TODO Auto-generated method stub
+    return 0;
+  }
+
+  @Override
+  public boolean isEmpty() {
+    // TODO Auto-generated method stub
+    return false;
+  }
+
+  @Override
+  public boolean containsKey(Object key) {
+    return false;
+  }
+
+  @Override
+  public boolean containsValue(Object value) {
+    return false;
+  }
+
+  @Override
+  public Object get(Object key) {
+    return null;
+  }
+
+  @Override
+  public Object put(Object key, Object value) {
+    return null;
+  }
+
+  @Override
+  public Object remove(Object key) {
+    return null;
+  }
+
+  @Override
+  public void putAll(Map m) {}
+
+  @Override
+  public void clear() {}
+
+  @Override
+  public Set keySet() {
+    return Collections.EMPTY_SET;
+  }
+
+  @Override
+  public Collection values() {
+    return Collections.EMPTY_LIST;
+  }
+
+  @Override
+  public Set entrySet() {
+    return Collections.EMPTY_SET;
+  }
+}
 
 public abstract class Transaction<C extends TransactionContainer> extends AbstractObservable
-    implements TransactionInterface {
+    implements EntityTransactionInterface, UseCacheResource {
 
   @Override
   public TransactionBenchmark getTransactionBenchmark() {
@@ -59,6 +128,8 @@ public abstract class Transaction<C extends TransactionContainer> extends Abstra
   private static final DatabaseAccessManager monitor = DatabaseAccessManager.getInstance();
 
   public static final String CLEAN_UP = "TransactionCleanUp";
+
+  protected EntityIdRegistry idRegistry = null;
   private final C container;
   private Access access = null;
   private final Schedule schedule = new Schedule();
@@ -304,27 +375,50 @@ public abstract class Transaction<C extends TransactionContainer> extends Abstra
   /** @see {@link #execute()} */
   protected void commit() throws Exception {}
 
-  public boolean useCache() {
-    return getContainer().getFlags() != null
-        && !getContainer().getFlags().containsKey("disableCache");
-  }
-
   public final Access getAccess() {
     return this.access;
   }
 
   protected void setAccess(final Access a) {
     this.access = a;
+    if (access != null) {
+      this.access.setUseCacheResourceDelegate(useCacheResourceDelegate);
+    }
   }
 
   @SuppressWarnings("unchecked")
-  public <S, T> HashMap<S, T> getCache(final String name) {
+  public <S, T> Map<S, T> getCache(final String name) {
+    if (!useCache()) {
+      return NO_OP_CACHE;
+    }
     if (!this.caches.containsKey(name)) {
       this.caches.put(name, new HashMap<S, T>());
     }
     return this.caches.get(name);
   }
 
+  private static final NoOpCache NO_OP_CACHE = new NoOpCache();
+
   @SuppressWarnings("rawtypes")
-  private final HashMap<String, HashMap> caches = new HashMap<>();
+  private final Map<String, Map> caches = new HashMap<>();
+
+  private final UseCacheResource useCacheResourceDelegate = new UseCacheResourceDelegate();
+
+  @Override
+  public UseCacheResource getUseCacheResourceDelegate() {
+    return this.useCacheResourceDelegate.getUseCacheResourceDelegate();
+  }
+
+  @Override
+  public void setUseCacheResourceDelegate(UseCacheResource delegate) {
+    this.useCacheResourceDelegate.setUseCacheResourceDelegate(delegate);
+  }
+
+  @Override
+  public boolean matchIdPattern(String id) {
+    if (this.idRegistry == null) {
+      this.idRegistry = new EntityIdRegistry(this);
+    }
+    return idRegistry.matchIdPattern(id);
+  }
 }
diff --git a/src/main/java/org/caosdb/server/transaction/UpdateUserTransaction.java b/src/main/java/org/caosdb/server/transaction/UpdateUserTransaction.java
index 6808968f20574242cfdaa9b87793d7a4ad4b6914..7730d82b2fc2fb7ff3d34430ea3d1b60ffb9c16e 100644
--- a/src/main/java/org/caosdb/server/transaction/UpdateUserTransaction.java
+++ b/src/main/java/org/caosdb/server/transaction/UpdateUserTransaction.java
@@ -63,7 +63,7 @@ public class UpdateUserTransaction extends AccessControlTransaction {
       final String username,
       final UserStatus status,
       final String email,
-      final Integer entity,
+      final String entity,
       final String password) {
     this.user = new ProtoUser();
     this.user.realm =
@@ -177,7 +177,7 @@ public class UpdateUserTransaction extends AccessControlTransaction {
           ACMPermissions.PERMISSION_UPDATE_USER_ENTITY(this.user.realm, this.user.name));
       isToBeUpdated = true;
 
-      if (this.user.entity.equals(0)) {
+      if (this.user.entity.isEmpty()) {
         // this means that the entity is to be reset.
         this.user.entity = null;
       } else {
diff --git a/src/main/java/org/caosdb/server/transaction/WriteTransaction.java b/src/main/java/org/caosdb/server/transaction/WriteTransaction.java
index 87d299477119dcc20b6f730d1bb014b253a49497..9a355410c9c29429296d4329e697a2cbca1d5980 100644
--- a/src/main/java/org/caosdb/server/transaction/WriteTransaction.java
+++ b/src/main/java/org/caosdb/server/transaction/WriteTransaction.java
@@ -74,7 +74,6 @@ public class WriteTransaction extends Transaction<WritableContainer>
     implements WriteTransactionInterface {
 
   private boolean noIdIsError = true;
-  private EntityIdRegistry idRegistry;
 
   public WriteTransaction(final WritableContainer container) {
     super(container);
diff --git a/src/main/java/org/caosdb/server/utils/UseCacheResource.java b/src/main/java/org/caosdb/server/utils/UseCacheResource.java
new file mode 100644
index 0000000000000000000000000000000000000000..2319601260a7116d4299f6823628ef2c4346875e
--- /dev/null
+++ b/src/main/java/org/caosdb/server/utils/UseCacheResource.java
@@ -0,0 +1,16 @@
+package org.caosdb.server.utils;
+
+public interface UseCacheResource {
+
+  public default boolean useCache() {
+    return getUseCacheResourceDelegate().useCache();
+  }
+
+  public default void setUseCache(boolean useCache) {
+    getUseCacheResourceDelegate().setUseCache(useCache);
+  }
+
+  public void setUseCacheResourceDelegate(UseCacheResource delegate);
+
+  public UseCacheResource getUseCacheResourceDelegate();
+}
diff --git a/src/main/java/org/caosdb/server/utils/UseCacheResourceDelegate.java b/src/main/java/org/caosdb/server/utils/UseCacheResourceDelegate.java
new file mode 100644
index 0000000000000000000000000000000000000000..81d862b07c9c6e1cf1309e085213fe9ffeb0b780
--- /dev/null
+++ b/src/main/java/org/caosdb/server/utils/UseCacheResourceDelegate.java
@@ -0,0 +1,42 @@
+package org.caosdb.server.utils;
+
+import org.caosdb.server.CaosDBServer;
+
+public class UseCacheResourceDelegate implements UseCacheResource {
+  private boolean useCache = CaosDBServer.useCache();
+  private UseCacheResource delegate = null;
+
+  @Override
+  public void setUseCache(boolean useCache) {
+    if (this.delegate != null) {
+      this.delegate.setUseCache(useCache);
+    } else {
+      this.useCache = useCache;
+    }
+  }
+
+  @Override
+  public boolean useCache() {
+    if (delegate != null) {
+      return delegate.useCache();
+    }
+    return CaosDBServer.useCache() && useCache;
+  }
+
+  @Override
+  public void setUseCacheResourceDelegate(UseCacheResource delegate) {
+    if (delegate == this) {
+      this.delegate = null;
+    } else {
+      this.delegate = delegate;
+    }
+  }
+
+  @Override
+  public UseCacheResource getUseCacheResourceDelegate() {
+    if (this.delegate != null) {
+      return this.delegate;
+    }
+    return this;
+  }
+}
diff --git a/src/test/java/org/caosdb/server/database/backend/implementation/MySQL/InsertTest.java b/src/test/java/org/caosdb/server/database/backend/implementation/MySQL/InsertTest.java
index 94febb12a91bc4db8f8878bb5a670f856b17edf5..648880fcd018d36bc73f2b2e8d1b4ea2c41e364d 100644
--- a/src/test/java/org/caosdb/server/database/backend/implementation/MySQL/InsertTest.java
+++ b/src/test/java/org/caosdb/server/database/backend/implementation/MySQL/InsertTest.java
@@ -50,7 +50,7 @@ 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));
+      replacementIds.add(new EntityID(Integer.toString(-i)));
     }
     return replacementIds;
   }
@@ -63,70 +63,70 @@ public class InsertTest {
   @Test
   public void testTransformation1() throws Exception {
     final Entity r = new InsertEntity("Test", Role.Record);
-    final Property p1 = new Property(new RetrieveEntity(new EntityID(1)));
+    final Property p1 = new Property(new RetrieveEntity(new EntityID("1")));
     p1.setRole("Property");
     p1.setValue(new GenericValue("V1"));
     p1.setDatatype("TEXT");
     p1.setStatementStatus(StatementStatus.FIX);
     r.addProperty(p1);
 
-    final Property p2 = new Property(new RetrieveEntity(new EntityID(2)));
+    final Property p2 = new Property(new RetrieveEntity(new EntityID("2")));
     p2.setRole("Property");
     p2.setValue(new GenericValue("V2"));
     p2.setDatatype("TEXT");
     p2.setStatementStatus(StatementStatus.RECOMMENDED);
     r.addProperty(p2);
 
-    final Property p3 = new Property(new RetrieveEntity(new EntityID(3)));
+    final Property p3 = new Property(new RetrieveEntity(new EntityID("3")));
     p3.setRole("Property");
     p3.setValue(new GenericValue("V3"));
     p3.setDatatype("TEXT");
     p3.setStatementStatus(StatementStatus.OBLIGATORY);
     p2.addProperty(p3);
 
-    final Property p4 = new Property(new RetrieveEntity(new EntityID(4)));
+    final Property p4 = new Property(new RetrieveEntity(new EntityID("4")));
     p4.setRole("Property");
     p4.setValue(new GenericValue("V4"));
     p4.setDatatype("TEXT");
     p4.setStatementStatus(StatementStatus.OBLIGATORY);
     r.addProperty(p4);
 
-    final Property p5 = new Property(new RetrieveEntity(new EntityID(5)));
+    final Property p5 = new Property(new RetrieveEntity(new EntityID("5")));
     p5.setRole("Property");
     p5.setValue(new GenericValue("V5"));
     p5.setDatatype("TEXT");
     p5.setStatementStatus(StatementStatus.OBLIGATORY);
     p4.addProperty(p5);
 
-    final Property p6 = new Property(new RetrieveEntity(new EntityID(6)));
+    final Property p6 = new Property(new RetrieveEntity(new EntityID("6")));
     p6.setRole("Property");
     p6.setValue(new GenericValue("V6"));
     p6.setDatatype("TEXT");
     p6.setStatementStatus(StatementStatus.OBLIGATORY);
     p5.addProperty(p6);
 
-    final Property p7 = new Property(new RetrieveEntity(new EntityID(7)));
+    final Property p7 = new Property(new RetrieveEntity(new EntityID("7")));
     p7.setRole("Property");
     p7.setValue(new GenericValue("V7"));
     p7.setDatatype("TEXT");
     p7.setStatementStatus(StatementStatus.OBLIGATORY);
     r.addProperty(p7);
 
-    final Property p8 = new Property(new RetrieveEntity(new EntityID(8)));
+    final Property p8 = new Property(new RetrieveEntity(new EntityID("8")));
     p8.setRole("Property");
     p8.setValue(new GenericValue("V8"));
     p8.setDatatype("TEXT");
     p8.setStatementStatus(StatementStatus.OBLIGATORY);
     p7.addProperty(p8);
 
-    final Property p9 = new Property(new RetrieveEntity(new EntityID(9)));
+    final Property p9 = new Property(new RetrieveEntity(new EntityID("9")));
     p9.setRole("Property");
     p9.setValue(new GenericValue("V9"));
     p9.setDatatype("TEXT");
     p9.setStatementStatus(StatementStatus.OBLIGATORY);
     p8.addProperty(p9);
 
-    final Property p10 = new Property(new RetrieveEntity(new EntityID(10)));
+    final Property p10 = new Property(new RetrieveEntity(new EntityID("10")));
     p10.setRole("Property");
     p10.setValue(new GenericValue("V10"));
     p10.setDatatype("TEXT");
@@ -171,29 +171,29 @@ public class InsertTest {
     assertEquals("V9", ((SingleValue) stage1Inserts.get(6).getValue()).toDatabaseString());
 
     assertEquals(6, stage2Inserts.size());
-    assertEquals(new EntityID(3), stage2Inserts.get(0).getId());
+    assertEquals(new EntityID("3"), stage2Inserts.get(0).getId());
     assertEquals("V3", ((SingleValue) stage2Inserts.get(0).getValue()).toDatabaseString());
-    assertEquals(new EntityID(2), stage2Inserts.get(0).getDomain());
+    assertEquals(new EntityID("2"), stage2Inserts.get(0).getDomain());
 
-    assertEquals(new EntityID(5), stage2Inserts.get(1).getId());
+    assertEquals(new EntityID("5"), stage2Inserts.get(1).getId());
     assertEquals("V5", ((SingleValue) stage2Inserts.get(1).getValue()).toDatabaseString());
-    assertEquals(new EntityID(4), stage2Inserts.get(1).getDomain());
+    assertEquals(new EntityID("4"), stage2Inserts.get(1).getDomain());
 
-    assertEquals(new EntityID(6), stage2Inserts.get(2).getId());
+    assertEquals(new EntityID("6"), stage2Inserts.get(2).getId());
     assertEquals("V6", ((SingleValue) stage2Inserts.get(2).getValue()).toDatabaseString());
-    assertEquals(new EntityID(-1), stage2Inserts.get(2).getDomain());
+    assertEquals(new EntityID("-1"), stage2Inserts.get(2).getDomain());
 
-    assertEquals(new EntityID(8), stage2Inserts.get(3).getId());
+    assertEquals(new EntityID("8"), stage2Inserts.get(3).getId());
     assertEquals("V8", ((SingleValue) stage2Inserts.get(3).getValue()).toDatabaseString());
-    assertEquals(new EntityID(7), stage2Inserts.get(3).getDomain());
+    assertEquals(new EntityID("7"), stage2Inserts.get(3).getDomain());
 
-    assertEquals(new EntityID(9), stage2Inserts.get(4).getId());
+    assertEquals(new EntityID("9"), stage2Inserts.get(4).getId());
     assertEquals("V9", ((SingleValue) stage2Inserts.get(4).getValue()).toDatabaseString());
-    assertEquals(new EntityID(-2), stage2Inserts.get(4).getDomain());
+    assertEquals(new EntityID("-2"), stage2Inserts.get(4).getDomain());
 
-    assertEquals(new EntityID(10), stage2Inserts.get(5).getId());
+    assertEquals(new EntityID("10"), stage2Inserts.get(5).getId());
     assertEquals("V10", ((SingleValue) stage2Inserts.get(5).getValue()).toDatabaseString());
-    assertEquals(new EntityID(-3), stage2Inserts.get(5).getDomain());
+    assertEquals(new EntityID("-3"), stage2Inserts.get(5).getDomain());
   }
 
   /**
@@ -205,21 +205,21 @@ public class InsertTest {
   @Test
   public void testTransformation2() throws Exception {
     final Entity r = new InsertEntity("Test", Role.Record);
-    final Property p1 = new Property(new RetrieveEntity(new EntityID(1)));
+    final Property p1 = new Property(new RetrieveEntity(new EntityID("1")));
     p1.setRole("Property");
     p1.setValue(new GenericValue("V1-1"));
     p1.setDatatype("TEXT");
     p1.setStatementStatus(StatementStatus.FIX);
     r.addProperty(p1);
 
-    final Property p2 = new Property(new RetrieveEntity(new EntityID(1)));
+    final Property p2 = new Property(new RetrieveEntity(new EntityID("1")));
     p2.setRole("Property");
     p2.setValue(new GenericValue("V1-2"));
     p2.setDatatype("TEXT");
     p2.setStatementStatus(StatementStatus.FIX);
     r.addProperty(p2);
 
-    final Property subp = new Property(new RetrieveEntity(new EntityID(2)));
+    final Property subp = new Property(new RetrieveEntity(new EntityID("2")));
     subp.setRole("Property");
     subp.setValue(new GenericValue("V2"));
     subp.setDatatype("TEXT");
@@ -235,21 +235,21 @@ public class InsertTest {
     assertEquals(3, stage1Inserts.size());
 
     assertFalse(stage1Inserts.get(0) instanceof Replacement);
-    assertEquals(new EntityID(1), stage1Inserts.get(0).getId());
+    assertEquals(new EntityID("1"), stage1Inserts.get(0).getId());
     assertEquals("V1-1", ((SingleValue) stage1Inserts.get(0).getValue()).toDatabaseString());
 
     assertTrue(stage1Inserts.get(1) instanceof Replacement);
     assertEquals("V1-2", ((SingleValue) stage1Inserts.get(1).getValue()).toDatabaseString());
-    assertEquals(new EntityID(-1), stage1Inserts.get(1).getId());
+    assertEquals(new EntityID("-1"), stage1Inserts.get(1).getId());
 
     assertFalse(stage1Inserts.get(2) instanceof Replacement);
-    assertEquals(new EntityID(-1), stage1Inserts.get(2).getId());
+    assertEquals(new EntityID("-1"), stage1Inserts.get(2).getId());
     assertEquals("1", ((SingleValue) stage1Inserts.get(2).getValue()).toDatabaseString());
 
     assertEquals(1, stage2Inserts.size());
 
     assertFalse(stage2Inserts.get(0) instanceof Replacement);
-    assertEquals(new EntityID(2), stage2Inserts.get(0).getId());
+    assertEquals(new EntityID("2"), stage2Inserts.get(0).getId());
     assertEquals("V2", ((SingleValue) stage2Inserts.get(0).getValue()).toDatabaseString());
   }
 
@@ -262,25 +262,25 @@ public class InsertTest {
   @Test
   public void testTransformation3() throws Exception {
     final Entity r = new InsertEntity("Test", Role.Record);
-    final Property p1 = new Property(new RetrieveEntity(new EntityID(1)));
+    final Property p1 = new Property(new RetrieveEntity(new EntityID("1")));
     p1.setRole("Property");
     p1.setDatatype("TEXT");
     p1.setStatementStatus(StatementStatus.FIX);
     r.addProperty(p1);
 
-    final Property p2 = new Property(new RetrieveEntity(new EntityID(1)));
+    final Property p2 = new Property(new RetrieveEntity(new EntityID("1")));
     p2.setRole("Property");
     p2.setDatatype("TEXT");
     p2.setStatementStatus(StatementStatus.FIX);
     r.addProperty(p2);
 
-    final Property p3 = new Property(new RetrieveEntity(new EntityID(1)));
+    final Property p3 = new Property(new RetrieveEntity(new EntityID("1")));
     p3.setRole("Property");
     p3.setDatatype("TEXT");
     p3.setStatementStatus(StatementStatus.FIX);
     r.addProperty(p3);
 
-    final Property sub1 = new Property(new RetrieveEntity(new EntityID(2)));
+    final Property sub1 = new Property(new RetrieveEntity(new EntityID("2")));
     sub1.setRole("Property");
     sub1.setDatatype("TEXT");
     sub1.setValue(new GenericValue("V1"));
@@ -295,25 +295,25 @@ public class InsertTest {
 
     assertEquals(4, stage1Inserts.size());
     assertTrue(stage1Inserts.get(0) instanceof Replacement);
-    assertEquals(new EntityID(-1), stage1Inserts.get(0).getId());
+    assertEquals(new EntityID("-1"), stage1Inserts.get(0).getId());
     assertEquals(null, stage1Inserts.get(0).getValue());
 
     assertFalse(stage1Inserts.get(1) instanceof Replacement);
-    assertEquals(new EntityID(-1), stage1Inserts.get(1).getId());
+    assertEquals(new EntityID("-1"), stage1Inserts.get(1).getId());
     assertEquals("1", ((ReferenceValue) stage1Inserts.get(1).getValue()).getId().toString());
 
     assertFalse(stage1Inserts.get(2) instanceof Replacement);
-    assertEquals(new EntityID(1), stage1Inserts.get(2).getId());
+    assertEquals(new EntityID("1"), stage1Inserts.get(2).getId());
     assertEquals(null, stage1Inserts.get(2).getValue());
 
     assertFalse(stage1Inserts.get(3) instanceof Replacement);
-    assertEquals(new EntityID(1), stage1Inserts.get(3).getId());
+    assertEquals(new EntityID("1"), stage1Inserts.get(3).getId());
     assertEquals(null, stage1Inserts.get(3).getValue());
 
     assertEquals(1, stage2Inserts.size());
-    assertEquals(new EntityID(2), stage2Inserts.get(0).getId());
+    assertEquals(new EntityID("2"), stage2Inserts.get(0).getId());
     assertEquals("V1", ((SingleValue) stage2Inserts.get(0).getValue()).toDatabaseString());
-    assertEquals(new EntityID(-1), stage2Inserts.get(0).getDomain());
+    assertEquals(new EntityID("-1"), stage2Inserts.get(0).getDomain());
   }
 
   /**
@@ -325,14 +325,14 @@ public class InsertTest {
   public void testTransformation4() throws Exception {
 
     final Entity r = new InsertEntity("Test", Role.Record);
-    final Property p1 = new Property(new RetrieveEntity(new EntityID(1)));
+    final Property p1 = new Property(new RetrieveEntity(new EntityID("1")));
     p1.setRole("Property");
     p1.setDatatype("TEXT");
     p1.setValue(new GenericValue("V1"));
     p1.setStatementStatus(StatementStatus.FIX);
     r.addProperty(p1);
 
-    final Property p2 = new Property(new RetrieveEntity(new EntityID(2)));
+    final Property p2 = new Property(new RetrieveEntity(new EntityID("2")));
     p2.setRole("Property");
     p2.setDatatype("LIST<TEXT>");
     p2.setStatementStatus(StatementStatus.FIX);
@@ -343,7 +343,7 @@ public class InsertTest {
     p2.setValue(vals);
     r.addProperty(p2);
 
-    final Property p3 = new Property(new RetrieveEntity(new EntityID(3)));
+    final Property p3 = new Property(new RetrieveEntity(new EntityID("3")));
     p3.setRole("Property");
     p3.setDatatype("TEXT");
     p3.setValue(new GenericValue("V3"));
@@ -359,19 +359,19 @@ public class InsertTest {
     assertEquals(4, stage1Inserts.size());
 
     assertFalse(stage1Inserts.get(0) instanceof Replacement);
-    assertEquals(new EntityID(1), stage1Inserts.get(0).getId());
+    assertEquals(new EntityID("1"), stage1Inserts.get(0).getId());
     assertEquals("V1", ((SingleValue) stage1Inserts.get(0).getValue()).toDatabaseString());
 
     assertTrue(stage1Inserts.get(1) instanceof Replacement);
-    assertEquals(new EntityID(-1), stage1Inserts.get(1).getId());
+    assertEquals(new EntityID("-1"), stage1Inserts.get(1).getId());
     assertTrue(stage1Inserts.get(1).getValue() instanceof CollectionValue);
 
     assertFalse(stage1Inserts.get(2) instanceof Replacement);
-    assertEquals(new EntityID(-1), stage1Inserts.get(2).getId());
+    assertEquals(new EntityID("-1"), stage1Inserts.get(2).getId());
     assertEquals("2", ((ReferenceValue) stage1Inserts.get(2).getValue()).getId().toString());
 
     assertFalse(stage1Inserts.get(3) instanceof Replacement);
-    assertEquals(new EntityID(3), stage1Inserts.get(3).getId());
+    assertEquals(new EntityID("3"), stage1Inserts.get(3).getId());
     assertEquals("V3", ((SingleValue) stage1Inserts.get(3).getValue()).toDatabaseString());
 
     assertEquals(0, stage2Inserts.size());
@@ -381,7 +381,7 @@ public class InsertTest {
   @Test
   public void testTransformation5() {
     final Entity r = new InsertEntity("Test", Role.RecordType);
-    final Property p1 = new Property(new RetrieveEntity(new EntityID(1)));
+    final Property p1 = new Property(new RetrieveEntity(new EntityID("1")));
     p1.setRole("Property");
     p1.setDatatype("TEXT");
     p1.setDescription("desc1");
@@ -391,7 +391,7 @@ public class InsertTest {
     p1.setStatementStatus(StatementStatus.RECOMMENDED);
     r.addProperty(p1);
 
-    final Property p2 = new Property(new RetrieveEntity(new EntityID(2)));
+    final Property p2 = new Property(new RetrieveEntity(new EntityID("2")));
     p2.setRole("Property");
     p2.setDatatype("TEXT");
     p2.setDescription("desc2");
@@ -401,7 +401,7 @@ public class InsertTest {
     p2.setStatementStatus(StatementStatus.RECOMMENDED);
     r.addProperty(p2);
 
-    final Property p21 = new Property(new RetrieveEntity(new EntityID(1)));
+    final Property p21 = new Property(new RetrieveEntity(new EntityID("1")));
     p21.setRole("Property");
     p21.setDatatype("TEXT");
     p21.setDescription("desc21");
@@ -411,7 +411,7 @@ public class InsertTest {
     p21.setStatementStatus(StatementStatus.FIX);
     p2.addProperty(p21);
 
-    final Property p22 = new Property(new RetrieveEntity(new EntityID(2)));
+    final Property p22 = new Property(new RetrieveEntity(new EntityID("2")));
     p22.setRole("Property");
     p22.setDatatype("TEXT");
     p22.setDescription("desc22");
@@ -421,7 +421,7 @@ public class InsertTest {
     p22.setStatementStatus(StatementStatus.FIX);
     p2.addProperty(p22);
 
-    final Property p3 = new Property(new RetrieveEntity(new EntityID(3)));
+    final Property p3 = new Property(new RetrieveEntity(new EntityID("3")));
     p3.setRole("Property");
     p3.setDatatype("TEXT");
     p3.setDescription("desc3");
@@ -431,7 +431,7 @@ public class InsertTest {
     p3.setStatementStatus(StatementStatus.RECOMMENDED);
     r.addProperty(p3);
 
-    final Property p31 = new Property(new RetrieveEntity(new EntityID(1)));
+    final Property p31 = new Property(new RetrieveEntity(new EntityID("1")));
     p31.setRole("Property");
     p31.setDatatype("TEXT");
     p31.setDescription("desc31");
@@ -441,7 +441,7 @@ public class InsertTest {
     p31.setStatementStatus(StatementStatus.FIX);
     p3.addProperty(p31);
 
-    final Property p32 = new Property(new RetrieveEntity(new EntityID(2)));
+    final Property p32 = new Property(new RetrieveEntity(new EntityID("2")));
     p32.setRole("Property");
     p32.setDatatype("TEXT");
     p32.setDescription("desc32");
@@ -451,7 +451,7 @@ public class InsertTest {
     p32.setStatementStatus(StatementStatus.FIX);
     p3.addProperty(p32);
 
-    final Property p321 = new Property(new RetrieveEntity(new EntityID(1)));
+    final Property p321 = new Property(new RetrieveEntity(new EntityID("1")));
     p321.setRole("Property");
     p321.setDatatype("TEXT");
     p321.setDescription("desc321");
@@ -461,7 +461,7 @@ public class InsertTest {
     p321.setStatementStatus(StatementStatus.FIX);
     p32.addProperty(p321);
 
-    final Property p322 = new Property(new RetrieveEntity(new EntityID(2)));
+    final Property p322 = new Property(new RetrieveEntity(new EntityID("2")));
     p322.setRole("Property");
     p322.setDatatype("TEXT");
     p322.setDescription("desc322");
@@ -471,7 +471,7 @@ public class InsertTest {
     p322.setStatementStatus(StatementStatus.FIX);
     p32.addProperty(p322);
 
-    final Property p323 = new Property(new RetrieveEntity(new EntityID(3)));
+    final Property p323 = new Property(new RetrieveEntity(new EntityID("3")));
     p323.setRole("Property");
     p323.setDatatype("TEXT");
     p323.setDescription("desc323");
@@ -481,7 +481,7 @@ public class InsertTest {
     p323.setStatementStatus(StatementStatus.FIX);
     p32.addProperty(p323);
 
-    final Property p33 = new Property(new RetrieveEntity(new EntityID(3)));
+    final Property p33 = new Property(new RetrieveEntity(new EntityID("3")));
     p33.setRole("Property");
     p33.setDatatype("TEXT");
     p33.setDescription("desc33");
diff --git a/src/test/java/org/caosdb/server/database/backend/transaction/RetrieveFullEntityTest.java b/src/test/java/org/caosdb/server/database/backend/transaction/RetrieveFullEntityTest.java
index 72c84d1f7b262a854a257c8ae764d4e3da9b8e80..4ba5ce46023aa020b2939f1734e4cfe9ec65622d 100644
--- a/src/test/java/org/caosdb/server/database/backend/transaction/RetrieveFullEntityTest.java
+++ b/src/test/java/org/caosdb/server/database/backend/transaction/RetrieveFullEntityTest.java
@@ -43,14 +43,14 @@ public class RetrieveFullEntityTest {
   @Test
   public void testRetrieveSubEntities() {
     final RetrieveFullEntityTransaction r =
-        new RetrieveFullEntityTransaction(new EntityID(0)) {
+        new RetrieveFullEntityTransaction(new EntityID("0")) {
 
           /** Mock-up */
           @Override
           public void retrieveFullEntity(
               final EntityInterface e, final List<Selection> selections) {
             // The id of the referenced window
-            assertEquals(new EntityID(1234), e.getId());
+            assertEquals(new EntityID("1234"), e.getId());
 
             // The level of selectors has been reduced by 1
             assertEquals("description", selections.get(0).getSelector());
@@ -59,16 +59,16 @@ public class RetrieveFullEntityTest {
           };
         };
 
-    final Property window = new Property(new RetrieveEntity(new EntityID(2345)));
+    final Property window = new Property(new RetrieveEntity(new EntityID("2345")));
     window.setName("Window");
     window.setDatatype("Window");
-    window.setValue(new ReferenceValue(1234));
+    window.setValue(new ReferenceValue("1234"));
 
-    final Entity house = new RetrieveEntity(new EntityID(3456));
+    final Entity house = new RetrieveEntity(new EntityID("3456"));
     house.addProperty(window);
     final ReferenceValue value =
-        (ReferenceValue) house.getProperties().getEntityById(new EntityID(2345)).getValue();
-    assertEquals(new EntityID(1234), value.getId());
+        (ReferenceValue) house.getProperties().getEntityById(new EntityID("2345")).getValue();
+    assertEquals(new EntityID("1234"), value.getId());
     assertNull(value.getEntity());
 
     final List<Selection> selections = new ArrayList<>();
@@ -76,7 +76,7 @@ public class RetrieveFullEntityTest {
 
     r.retrieveSubEntities(house, selections);
 
-    assertEquals(new EntityID(1234), value.getId());
+    assertEquals(new EntityID("1234"), value.getId());
     assertNotNull(value.getEntity());
     assertEquals("A heart-shaped window.", value.getEntity().getDescription());
   }
diff --git a/src/test/java/org/caosdb/server/entity/container/PropertyContainerTest.java b/src/test/java/org/caosdb/server/entity/container/PropertyContainerTest.java
index a8ccdbdc9f7a9522020332e01cba96a1667d70b6..8220097ba2d4f814691bd493156b4abcbf2eb7b7 100644
--- a/src/test/java/org/caosdb/server/entity/container/PropertyContainerTest.java
+++ b/src/test/java/org/caosdb/server/entity/container/PropertyContainerTest.java
@@ -48,7 +48,7 @@ public class PropertyContainerTest {
 
   @BeforeAll
   public static void setup() {
-    window = new RetrieveEntity(new EntityID(1234));
+    window = new RetrieveEntity(new EntityID("1234"));
     windowHeight = new Property(new RetrieveEntity("window.height", Role.Property));
     window.addProperty(windowHeight);
     windowHeight.setValue(new GenericValue("windowHeight"));
@@ -59,7 +59,7 @@ public class PropertyContainerTest {
     houseHeight = new Property(new RetrieveEntity("height", Role.Property));
     houseHeight.setValue(new GenericValue("houseHeight"));
     house.addProperty(houseHeight);
-    windowProperty = new Property(new RetrieveEntity(new EntityID(2345)));
+    windowProperty = new Property(new RetrieveEntity(new EntityID("2345")));
     windowProperty.setName("window");
     windowProperty.setValue(new ReferenceValue(window.getId()));
     house.addProperty(windowProperty);
diff --git a/src/test/java/org/caosdb/server/entity/xml/PropertyToElementStrategyTest.java b/src/test/java/org/caosdb/server/entity/xml/PropertyToElementStrategyTest.java
index a2c9676b9759fc55fb0d1e089808ab50d016288e..ab658722c77983d86d5611808adea8302b0933cc 100644
--- a/src/test/java/org/caosdb/server/entity/xml/PropertyToElementStrategyTest.java
+++ b/src/test/java/org/caosdb/server/entity/xml/PropertyToElementStrategyTest.java
@@ -66,7 +66,7 @@ public class PropertyToElementStrategyTest {
 
   @BeforeEach
   public void setup() {
-    window = new RetrieveEntity(new EntityID(1234), Role.Record);
+    window = new RetrieveEntity(new EntityID("1234"), Role.Record);
     windowHeight = new Property(new RetrieveEntity("height", Role.Property));
     window.addProperty(windowHeight);
     windowHeight.setValue(new GenericValue("windowHeight"));
@@ -77,7 +77,7 @@ public class PropertyToElementStrategyTest {
     houseHeight = new Property(new RetrieveEntity("height", Role.Property));
     houseHeight.setValue(new GenericValue("houseHeight"));
     house.addProperty(houseHeight);
-    windowProperty = new Property(new RetrieveEntity(new EntityID(2345)));
+    windowProperty = new Property(new RetrieveEntity(new EntityID("2345")));
     windowProperty.setName("window");
     windowProperty.setDatatype("window");
     windowProperty.setValue(new ReferenceValue(window.getId()));
diff --git a/src/test/java/org/caosdb/server/grpc/CaosDBToGrpcConvertersTest.java b/src/test/java/org/caosdb/server/grpc/CaosDBToGrpcConvertersTest.java
index d46c187324b76e179ef8d562cd5a150ab7968a45..b5bdb3802d4338dc093b385a54716dcbaf0df604 100644
--- a/src/test/java/org/caosdb/server/grpc/CaosDBToGrpcConvertersTest.java
+++ b/src/test/java/org/caosdb/server/grpc/CaosDBToGrpcConvertersTest.java
@@ -74,7 +74,7 @@ public class CaosDBToGrpcConvertersTest {
     RetrieveEntity entity = new RetrieveEntity();
 
     // must be printed
-    entity.setId(new EntityID(1234));
+    entity.setId(new EntityID("1234"));
     entity.addInfo("info");
     entity.addWarning(new Message("warning"));
     entity.addError(new Message("error"));
@@ -136,7 +136,7 @@ public class CaosDBToGrpcConvertersTest {
 
     RetrieveEntity person1 = new RetrieveEntity();
     person1.addProperty(fullName1);
-    ReferenceValue val1 = new ReferenceValue(new EntityID(1234));
+    ReferenceValue val1 = new ReferenceValue(new EntityID("1234"));
     val1.setEntity(person1, false);
     col.add(val1);
 
@@ -147,7 +147,7 @@ public class CaosDBToGrpcConvertersTest {
 
     RetrieveEntity person2 = new RetrieveEntity();
     person2.addProperty(fullName2);
-    ReferenceValue val2 = new ReferenceValue(new EntityID(1234));
+    ReferenceValue val2 = new ReferenceValue(new EntityID("1234"));
     val2.setEntity(person2, false);
     col.add(val2);
     p.setValue(col);
diff --git a/src/test/java/org/caosdb/server/jobs/JobConfigTest.java b/src/test/java/org/caosdb/server/jobs/JobConfigTest.java
index e176c2111189fb52ca9946e10ae5ec705549b6c8..1134a55c9d3c08a4981807f2cbb66bb7c174744c 100644
--- a/src/test/java/org/caosdb/server/jobs/JobConfigTest.java
+++ b/src/test/java/org/caosdb/server/jobs/JobConfigTest.java
@@ -26,7 +26,7 @@ public class JobConfigTest {
     final JobConfig jobConfig = JobConfig.getInstance();
     assertEquals("Retrieve", jobConfig.getTransactionType(new RetrieveEntity("test")));
     assertEquals("Insert", jobConfig.getTransactionType(new InsertEntity("test", Role.Record)));
-    assertEquals("Delete", jobConfig.getTransactionType(new DeleteEntity(new EntityID(1234))));
+    assertEquals("Delete", jobConfig.getTransactionType(new DeleteEntity(new EntityID("1234"))));
     assertEquals("Update", jobConfig.getTransactionType(new UpdateEntity(new Element("Record"))));
   }
 }
diff --git a/src/test/java/org/caosdb/server/transaction/RetrieveTest.java b/src/test/java/org/caosdb/server/transaction/RetrieveTest.java
index a3ac40e1bf1e0fe6489a74f45d6c253b903b4478..00c23d2362495bd1c7a871de7bd84ddab2f0e1c2 100644
--- a/src/test/java/org/caosdb/server/transaction/RetrieveTest.java
+++ b/src/test/java/org/caosdb/server/transaction/RetrieveTest.java
@@ -62,7 +62,7 @@ public class RetrieveTest {
   public void testMissingRetrievePermission() {
     Subject subject = SecurityUtils.getSubject();
     subject.login(AnonymousAuthenticationToken.getInstance());
-    EntityInterface entity = new RetrieveEntity(new EntityID(1234));
+    EntityInterface entity = new RetrieveEntity(new EntityID("1234"));
     EntityACLFactory fac = new EntityACLFactory();
     fac.deny(AnonymousAuthenticationToken.PRINCIPAL, "RETRIEVE:ENTITY");
     entity.setEntityACL(fac.create());
diff --git a/src/test/java/org/caosdb/server/transaction/UpdateTest.java b/src/test/java/org/caosdb/server/transaction/UpdateTest.java
index a0891a3eb34e1759100c78916d0fb250de149ef8..fd064ba0882912a44f3282e9aa412b6a560287ca 100644
--- a/src/test/java/org/caosdb/server/transaction/UpdateTest.java
+++ b/src/test/java/org/caosdb/server/transaction/UpdateTest.java
@@ -75,11 +75,11 @@ public class UpdateTest {
   @Test
   public void testDeriveUpdate_SameProperty()
       throws NoSuchAlgorithmException, IOException, CaosDBException {
-    final Entity newEntity = new RetrieveEntity(new EntityID(1234));
-    final Property newProperty = new Property(new RetrieveEntity(new EntityID(1)));
+    final Entity newEntity = new RetrieveEntity(new EntityID("1234"));
+    final Property newProperty = new Property(new RetrieveEntity(new EntityID("1")));
     newEntity.addProperty(newProperty);
-    final Property oldProperty = new Property(new RetrieveEntity(new EntityID(1)));
-    final Entity oldEntity = new RetrieveEntity(new EntityID(1234));
+    final Property oldProperty = new Property(new RetrieveEntity(new EntityID("1")));
+    final Entity oldEntity = new RetrieveEntity(new EntityID("1234"));
     oldEntity.addProperty(oldProperty);
 
     new WriteTransaction(null).deriveUpdate(newEntity, oldEntity);
@@ -89,13 +89,13 @@ public class UpdateTest {
   @Test
   public void testDeriveUpdate_AnotherProperty()
       throws NoSuchAlgorithmException, IOException, CaosDBException {
-    final Entity newEntity = new RetrieveEntity(new EntityID(1234));
-    final Property newProperty = new Property(new RetrieveEntity(new EntityID(1)));
-    final Property newProperty2 = new Property(new RetrieveEntity(new EntityID(2)));
+    final Entity newEntity = new RetrieveEntity(new EntityID("1234"));
+    final Property newProperty = new Property(new RetrieveEntity(new EntityID("1")));
+    final Property newProperty2 = new Property(new RetrieveEntity(new EntityID("2")));
     newEntity.addProperty(newProperty);
     newEntity.addProperty(newProperty2);
-    final Property oldProperty = new Property(new RetrieveEntity(new EntityID(1)));
-    final Entity oldEntity = new RetrieveEntity(new EntityID(1234));
+    final Property oldProperty = new Property(new RetrieveEntity(new EntityID("1")));
+    final Entity oldEntity = new RetrieveEntity(new EntityID("1234"));
     oldEntity.addProperty(oldProperty);
 
     new WriteTransaction(null).deriveUpdate(newEntity, oldEntity);
@@ -107,15 +107,15 @@ public class UpdateTest {
   @Test
   public void testDeriveUpdate_SameUnit()
       throws NoSuchAlgorithmException, IOException, CaosDBException {
-    final EntityInterface magicUnit = new RetrieveEntity(new EntityID(1234));
+    final EntityInterface magicUnit = new RetrieveEntity(new EntityID("1234"));
     magicUnit.setName("Unit");
-    magicUnit.setId(new EntityID(24));
+    magicUnit.setId(new EntityID("24"));
     magicUnit.setDatatype("TEXT");
 
-    final Entity newEntity = new RetrieveEntity(new EntityID(1234));
-    final Property newProperty = new Property(new RetrieveEntity(new EntityID(1)));
+    final Entity newEntity = new RetrieveEntity(new EntityID("1234"));
+    final Property newProperty = new Property(new RetrieveEntity(new EntityID("1")));
 
-    final Property newUnit = new Property(new RetrieveEntity(new EntityID(5)));
+    final Property newUnit = new Property(new RetrieveEntity(new EntityID("5")));
     newUnit.setName(magicUnit.getName());
     newUnit.setId(magicUnit.getId());
     newUnit.setDatatype(magicUnit.getDatatype());
@@ -126,10 +126,10 @@ public class UpdateTest {
 
     newEntity.addProperty(newProperty);
 
-    final Entity oldEntity = new RetrieveEntity(new EntityID(1234));
-    final Property oldProperty = new Property(new RetrieveEntity(new EntityID(1)));
+    final Entity oldEntity = new RetrieveEntity(new EntityID("1234"));
+    final Property oldProperty = new Property(new RetrieveEntity(new EntityID("1")));
 
-    final Property oldUnit = new Property(new RetrieveEntity(new EntityID(5)));
+    final Property oldUnit = new Property(new RetrieveEntity(new EntityID("5")));
     oldUnit.setName(magicUnit.getName());
     oldUnit.setId(magicUnit.getId());
     oldUnit.setDatatype(magicUnit.getDatatype());
@@ -149,15 +149,15 @@ public class UpdateTest {
   @Test
   public void testDeriveUpdate_DifferentUnit()
       throws NoSuchAlgorithmException, IOException, CaosDBException {
-    final EntityInterface magicUnit = new RetrieveEntity(new EntityID(1234));
+    final EntityInterface magicUnit = new RetrieveEntity(new EntityID("1234"));
     magicUnit.setName("Unit");
-    magicUnit.setId(new EntityID(24));
+    magicUnit.setId(new EntityID("24"));
     magicUnit.setDatatype("TEXT");
 
-    final Entity newEntity = new RetrieveEntity(new EntityID(1234));
-    final Property newProperty = new Property(new RetrieveEntity(new EntityID(1)));
+    final Entity newEntity = new RetrieveEntity(new EntityID("1234"));
+    final Property newProperty = new Property(new RetrieveEntity(new EntityID("1")));
 
-    final Property newUnit = new Property(new RetrieveEntity(new EntityID(5)));
+    final Property newUnit = new Property(new RetrieveEntity(new EntityID("5")));
     newUnit.setName(magicUnit.getName());
     newUnit.setId(magicUnit.getId());
     newUnit.setDatatype(magicUnit.getDatatype());
@@ -168,10 +168,10 @@ public class UpdateTest {
 
     newEntity.addProperty(newProperty);
 
-    final Entity oldEntity = new RetrieveEntity(new EntityID(1234));
-    final Property oldProperty = new Property(new RetrieveEntity(new EntityID(1)));
+    final Entity oldEntity = new RetrieveEntity(new EntityID("1234"));
+    final Property oldProperty = new Property(new RetrieveEntity(new EntityID("1")));
 
-    final Property oldUnit = new Property(new RetrieveEntity(new EntityID(5)));
+    final Property oldUnit = new Property(new RetrieveEntity(new EntityID("5")));
     oldUnit.setName(magicUnit.getName());
     oldUnit.setId(magicUnit.getId());
     oldUnit.setDatatype(magicUnit.getDatatype());
@@ -192,10 +192,10 @@ public class UpdateTest {
       throws NoSuchAlgorithmException, CaosDBException, IOException {
 
     final Entity newEntity = new UpdateEntity();
-    final Property newProperty = new Property(new UpdateEntity(new EntityID(1)));
+    final Property newProperty = new Property(new UpdateEntity(new EntityID("1")));
     newProperty.setDatatype("List<Person>");
     CollectionValue newValue = new CollectionValue();
-    newValue.add(new ReferenceValue(1234));
+    newValue.add(new ReferenceValue("1234"));
     newValue.add(null);
     newValue.add(new GenericValue(2345));
     newValue.add(new GenericValue(3465));
@@ -206,14 +206,14 @@ public class UpdateTest {
 
     // old entity represents the stored entity.
     final Entity oldEntity = new UpdateEntity();
-    final Property oldProperty = new Property(new UpdateEntity(new EntityID(1)));
+    final Property oldProperty = new Property(new UpdateEntity(new EntityID("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));
+    oldValue.add(2, new ReferenceValue("2345"));
+    oldValue.add(0, new ReferenceValue("1234"));
     oldProperty.setValue(oldValue);
     oldEntity.addProperty(oldProperty);
 
@@ -245,8 +245,8 @@ public class UpdateTest {
     // 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(2, new ReferenceValue("2345"));
+    oldValue2.add(3, new ReferenceValue("1234"));
     oldValue2.add(4, null);
     oldProperty.setValue(oldValue2);
 
@@ -266,8 +266,8 @@ public class UpdateTest {
   public void testDeriveUpdate_UpdateList()
       throws NoSuchAlgorithmException, CaosDBException, IOException {
     // @review Florian Spreckelsen 2022-03-15
-    final Property oldProperty = new Property(new UpdateEntity(new EntityID(1)));
-    final Property newProperty = new Property(new UpdateEntity(new EntityID(1)));
+    final Property oldProperty = new Property(new UpdateEntity(new EntityID("1")));
+    final Property newProperty = new Property(new UpdateEntity(new EntityID("1")));
     oldProperty.setDatatype("List<Person>");
     newProperty.setDatatype("List<Person>");
     final Entity oldEntity = new UpdateEntity();