This is an automated email from the ASF dual-hosted git repository.

liuxun pushed a commit to branch fix-cache
in repository https://gitbox.apache.org/repos/asf/gravitino.git

commit 37c885afab7764c793ac8b9e214f1d7be06109ad
Author: Xun <[email protected]>
AuthorDate: Tue Aug 19 18:08:41 2025 +0800

    Fix(cache): cache relation remove
---
 .../gravitino/cache/TestCacheIndexCoherence.java   |  64 +-
 .../gravitino/cache/CaffeineEntityCache.java       | 112 +++-
 .../org/apache/gravitino/cache/EntityCacheKey.java |  42 +-
 ...tyCacheKey.java => EntityCacheRelationKey.java} |  65 +-
 .../org/apache/gravitino/cache/TestCacheIndex.java | 179 +++---
 .../gravitino/cache/TestCaffeineEntityCache.java   | 662 +++++++++++++--------
 .../apache/gravitino/cache/TestEntityCacheKey.java |  49 +-
 .../java/org/apache/gravitino/utils/TestUtil.java  |   4 +-
 8 files changed, 673 insertions(+), 504 deletions(-)

diff --git 
a/core/src/jcstress/java/org/apache/gravitino/cache/TestCacheIndexCoherence.java
 
b/core/src/jcstress/java/org/apache/gravitino/cache/TestCacheIndexCoherence.java
index ffeb04bcf8..d74f32b22c 100644
--- 
a/core/src/jcstress/java/org/apache/gravitino/cache/TestCacheIndexCoherence.java
+++ 
b/core/src/jcstress/java/org/apache/gravitino/cache/TestCacheIndexCoherence.java
@@ -78,13 +78,13 @@ public class TestCacheIndexCoherence {
           + "atomicity or thread-safety guarantees.")
   @State
   public static class InsertSameKeyCoherenceTest {
-    private final RadixTree<EntityCacheKey> indexTree =
+    private final RadixTree<EntityCacheRelationKey> indexTree =
         new ConcurrentRadixTree<>(new DefaultCharArrayNodeFactory());
 
     private final NameIdentifier ident = NameIdentifier.of("metalake1", 
"catalog1", "schema1");
     private final Entity entity =
         getTestSchemaEntity(123L, "schema1", Namespace.of("metalake1", 
"catalog1"), "ident1");
-    private final EntityCacheKey key = EntityCacheKey.of(ident, entity.type());
+    private final EntityCacheRelationKey key = 
EntityCacheRelationKey.of(ident, entity.type());
     private final String keyStr = key.toString();
 
     @Actor
@@ -99,7 +99,7 @@ public class TestCacheIndexCoherence {
 
     @Arbiter
     public void arbiter(I_Result r) {
-      EntityCacheKey valueForExactKey = indexTree.getValueForExactKey(keyStr);
+      EntityCacheRelationKey valueForExactKey = 
indexTree.getValueForExactKey(keyStr);
       r.r1 =
           (valueForExactKey != null
                   && Objects.equals(valueForExactKey, key)
@@ -121,12 +121,12 @@ public class TestCacheIndexCoherence {
           + "forbidden result indicates incorrect key handling or data loss 
under concurrency.")
   @State
   public static class InsertSameKeyWithRelationTypeCoherenceTest {
-    private final RadixTree<EntityCacheKey> indexTree =
+    private final RadixTree<EntityCacheRelationKey> indexTree =
         new ConcurrentRadixTree<>(new DefaultCharArrayNodeFactory());
 
     private final NameIdentifier ident = NameIdentifierUtil.ofRole("metalake", 
"role");
-    private final EntityCacheKey key =
-        EntityCacheKey.of(
+    private final EntityCacheRelationKey key =
+        EntityCacheRelationKey.of(
             ident, Entity.EntityType.ROLE, 
SupportsRelationOperations.Type.ROLE_USER_REL);
     private final String keyStr = key.toString();
 
@@ -142,7 +142,7 @@ public class TestCacheIndexCoherence {
 
     @Arbiter
     public void arbiter(I_Result r) {
-      EntityCacheKey valueForExactKey = indexTree.getValueForExactKey(keyStr);
+      EntityCacheRelationKey valueForExactKey = 
indexTree.getValueForExactKey(keyStr);
       r.r1 =
           (valueForExactKey != null
                   && Objects.equals(valueForExactKey, key)
@@ -164,7 +164,7 @@ public class TestCacheIndexCoherence {
           + "indicates data loss or broken concurrency guarantees.")
   @State
   public static class InsertMultipleKeyCoherenceTest {
-    private final RadixTree<EntityCacheKey> indexTree =
+    private final RadixTree<EntityCacheRelationKey> indexTree =
         new ConcurrentRadixTree<>(new DefaultCharArrayNodeFactory());
 
     private final NameIdentifier ident1 = NameIdentifier.of("metalake1", 
"catalog1", "schema1");
@@ -173,8 +173,8 @@ public class TestCacheIndexCoherence {
     private final NameIdentifier ident2 = NameIdentifier.of("metalake1", 
"catalog1", "schema2");
     private final Entity entity2 =
         getTestSchemaEntity(456L, "schema2", Namespace.of("metalake1", 
"catalog1"), "ident2");
-    private final EntityCacheKey key1 = EntityCacheKey.of(ident1, 
entity1.type());
-    private final EntityCacheKey key2 = EntityCacheKey.of(ident2, 
entity2.type());
+    private final EntityCacheRelationKey key1 = 
EntityCacheRelationKey.of(ident1, entity1.type());
+    private final EntityCacheRelationKey key2 = 
EntityCacheRelationKey.of(ident2, entity2.type());
     private final String key1Str = key1.toString();
     private final String key2Str = key2.toString();
 
@@ -190,8 +190,8 @@ public class TestCacheIndexCoherence {
 
     @Arbiter
     public void arbiter(I_Result r) {
-      EntityCacheKey valueForExactKey1 = 
indexTree.getValueForExactKey(key1Str);
-      EntityCacheKey valueForExactKey2 = 
indexTree.getValueForExactKey(key2Str);
+      EntityCacheRelationKey valueForExactKey1 = 
indexTree.getValueForExactKey(key1Str);
+      EntityCacheRelationKey valueForExactKey2 = 
indexTree.getValueForExactKey(key2Str);
       r.r1 =
           (valueForExactKey1 != null
                   && valueForExactKey2 != null
@@ -215,17 +215,17 @@ public class TestCacheIndexCoherence {
           + "both entries. A forbidden result indicates relation type is not 
correctly distinguished.")
   @State
   public static class InsertMultipleKeyWithRelationTypeCoherenceTest {
-    private final RadixTree<EntityCacheKey> indexTree =
+    private final RadixTree<EntityCacheRelationKey> indexTree =
         new ConcurrentRadixTree<>(new DefaultCharArrayNodeFactory());
 
     private final NameIdentifier ident1 = 
NameIdentifierUtil.ofRole("metalake", "role1");
     private final NameIdentifier ident2 = 
NameIdentifierUtil.ofRole("metalake", "role1");
 
-    private final EntityCacheKey key1 =
-        EntityCacheKey.of(
+    private final EntityCacheRelationKey key1 =
+        EntityCacheRelationKey.of(
             ident1, Entity.EntityType.ROLE, 
SupportsRelationOperations.Type.ROLE_USER_REL);
-    private final EntityCacheKey key2 =
-        EntityCacheKey.of(
+    private final EntityCacheRelationKey key2 =
+        EntityCacheRelationKey.of(
             ident2, Entity.EntityType.ROLE, 
SupportsRelationOperations.Type.ROLE_GROUP_REL);
     private final String key1Str = key1.toString();
     private final String key2Str = key2.toString();
@@ -242,8 +242,8 @@ public class TestCacheIndexCoherence {
 
     @Arbiter
     public void arbiter(I_Result r) {
-      EntityCacheKey valueForExactKey1 = 
indexTree.getValueForExactKey(key1Str);
-      EntityCacheKey valueForExactKey2 = 
indexTree.getValueForExactKey(key2Str);
+      EntityCacheRelationKey valueForExactKey1 = 
indexTree.getValueForExactKey(key1Str);
+      EntityCacheRelationKey valueForExactKey2 = 
indexTree.getValueForExactKey(key2Str);
       r.r1 =
           (valueForExactKey1 != null
                   && valueForExactKey2 != null
@@ -309,12 +309,12 @@ public class TestCacheIndexCoherence {
   @State
   public static class PutRemoveSameKeyWithRelationTypeCoherenceTest {
 
-    private final RadixTree<EntityCacheKey> indexTree =
+    private final RadixTree<EntityCacheRelationKey> indexTree =
         new ConcurrentRadixTree<>(new DefaultCharArrayNodeFactory());
 
     private final NameIdentifier ident = NameIdentifierUtil.ofRole("metalake", 
"role");
-    private final EntityCacheKey key =
-        EntityCacheKey.of(
+    private final EntityCacheRelationKey key =
+        EntityCacheRelationKey.of(
             ident, Entity.EntityType.ROLE, 
SupportsRelationOperations.Type.ROLE_USER_REL);
     private final String keyStr = key.toString();
 
@@ -330,7 +330,7 @@ public class TestCacheIndexCoherence {
 
     @Arbiter
     public void arbiter(I_Result r) {
-      EntityCacheKey value = indexTree.getValueForExactKey(keyStr);
+      EntityCacheRelationKey value = indexTree.getValueForExactKey(keyStr);
       r.r1 = (value == null) ? 1 : 0;
     }
   }
@@ -416,17 +416,17 @@ public class TestCacheIndexCoherence {
   @State
   public static class PutAndPrefixScanWithRelationTypeCoherenceTest {
 
-    private final RadixTree<EntityCacheKey> indexTree =
+    private final RadixTree<EntityCacheRelationKey> indexTree =
         new ConcurrentRadixTree<>(new DefaultCharArrayNodeFactory());
 
     private final NameIdentifier ident1 = 
NameIdentifierUtil.ofRole("metalake", "role1");
     private final NameIdentifier ident2 = 
NameIdentifierUtil.ofRole("metalake", "role2");
 
-    private final EntityCacheKey key1 =
-        EntityCacheKey.of(
+    private final EntityCacheRelationKey key1 =
+        EntityCacheRelationKey.of(
             ident1, Entity.EntityType.ROLE, 
SupportsRelationOperations.Type.ROLE_USER_REL);
-    private final EntityCacheKey key2 =
-        EntityCacheKey.of(
+    private final EntityCacheRelationKey key2 =
+        EntityCacheRelationKey.of(
             ident2, Entity.EntityType.ROLE, 
SupportsRelationOperations.Type.ROLE_GROUP_REL);
     private final String key1Str = key1.toString();
     private final String key2Str = key2.toString();
@@ -443,7 +443,7 @@ public class TestCacheIndexCoherence {
 
     @Arbiter
     public void arbiter(II_Result r) {
-      ImmutableList<EntityCacheKey> values =
+      ImmutableList<EntityCacheRelationKey> values =
           
ImmutableList.copyOf(indexTree.getValuesForKeysStartingWith("metalake"));
       r.r1 = values.contains(key1) ? 1 : 0;
       r.r2 = values.contains(key2) ? 1 : 0;
@@ -495,11 +495,11 @@ public class TestCacheIndexCoherence {
           + "Missing value is interesting but not forbidden, depending on 
execution timing.")
   @State
   public static class PutAndGetWithRelationTypeCoherenceTest {
-    private final RadixTree<EntityCacheKey> indexTree =
+    private final RadixTree<EntityCacheRelationKey> indexTree =
         new ConcurrentRadixTree<>(new DefaultCharArrayNodeFactory());
     private final NameIdentifier ident = NameIdentifierUtil.ofRole("metalake", 
"role");
-    private final EntityCacheKey key =
-        EntityCacheKey.of(
+    private final EntityCacheRelationKey key =
+        EntityCacheRelationKey.of(
             ident, Entity.EntityType.ROLE, 
SupportsRelationOperations.Type.ROLE_USER_REL);
     private final String keyStr = key.toString();
 
diff --git 
a/core/src/main/java/org/apache/gravitino/cache/CaffeineEntityCache.java 
b/core/src/main/java/org/apache/gravitino/cache/CaffeineEntityCache.java
index c572427fd1..ad0fc4ebc9 100644
--- a/core/src/main/java/org/apache/gravitino/cache/CaffeineEntityCache.java
+++ b/core/src/main/java/org/apache/gravitino/cache/CaffeineEntityCache.java
@@ -32,6 +32,7 @@ import 
com.googlecode.concurrenttrees.radix.node.concrete.DefaultCharArrayNodeFa
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
@@ -78,11 +79,21 @@ public class CaffeineEntityCache extends BaseEntityCache {
   private static final Logger LOG = 
LoggerFactory.getLogger(CaffeineEntityCache.class.getName());
   private final ReentrantLock opLock = new ReentrantLock();
 
-  /** Cache part */
-  private final Cache<EntityCacheKey, List<Entity>> cacheData;
+  /** Cache data structure. cacheData[0] = Role1-KEY -> [catalog1, catalog2] */
+  private final Cache<EntityCacheRelationKey, List<Entity>> cacheData;
 
-  /** Index part */
-  private RadixTree<EntityCacheKey> cacheIndex;
+  /**
+   * Cache reverse index structure. cacheData[0] = Role1 -> [catalog1, 
catalog2] cacheData[1] =
+   * catalog1 -> [tab1, tab2] reverseIndex[0] = catalog1-KEY -> Role1 
reverseIndex[1] = catalog2-KEY
+   * -> Role1 reverseIndex[3] = tab1-KEY -> catalog1 reverseIndex[4] = 
tab2-KEY -> catalog1
+   */
+  private RadixTree<EntityCacheKey> reverseIndex;
+
+  /**
+   * Cache Index structure. cacheData[0] = Role1 -> [catalog1, catalog2] 
cacheData[1] = catalog1 ->
+   * [tab1, tab2] cacheIndex[0] = Role1-KEY -> Role1 cacheIndex[1] = Role1-KEY 
-> Role1
+   */
+  private RadixTree<EntityCacheRelationKey> cacheIndex;
 
   private ScheduledExecutorService scheduler;
 
@@ -94,6 +105,7 @@ public class CaffeineEntityCache extends BaseEntityCache {
   public CaffeineEntityCache(Config cacheConfig) {
     super(cacheConfig);
     this.cacheIndex = new ConcurrentRadixTree<>(new 
DefaultCharArrayNodeFactory());
+    this.reverseIndex = new ConcurrentRadixTree<>(new 
DefaultCharArrayNodeFactory());
 
     Caffeine<EntityCacheKey, List<Entity>> cacheDataBuilder = 
newBaseBuilder(cacheConfig);
 
@@ -133,7 +145,7 @@ public class CaffeineEntityCache extends BaseEntityCache {
     checkArguments(nameIdentifier, identType, relType);
 
     List<Entity> entitiesFromCache =
-        cacheData.getIfPresent(EntityCacheKey.of(nameIdentifier, identType, 
relType));
+        cacheData.getIfPresent(EntityCacheRelationKey.of(nameIdentifier, 
identType, relType));
     return 
Optional.ofNullable(entitiesFromCache).map(BaseEntityCache::convertEntities);
   }
 
@@ -143,7 +155,7 @@ public class CaffeineEntityCache extends BaseEntityCache {
       NameIdentifier ident, Entity.EntityType type) {
     checkArguments(ident, type);
 
-    List<Entity> entitiesFromCache = 
cacheData.getIfPresent(EntityCacheKey.of(ident, type));
+    List<Entity> entitiesFromCache = 
cacheData.getIfPresent(EntityCacheRelationKey.of(ident, type));
 
     return Optional.ofNullable(entitiesFromCache)
         .filter(l -> !l.isEmpty())
@@ -172,14 +184,14 @@ public class CaffeineEntityCache extends BaseEntityCache {
   public boolean contains(
       NameIdentifier ident, Entity.EntityType type, 
SupportsRelationOperations.Type relType) {
     checkArguments(ident, type, relType);
-    return cacheData.getIfPresent(EntityCacheKey.of(ident, type, relType)) != 
null;
+    return cacheData.getIfPresent(EntityCacheRelationKey.of(ident, type, 
relType)) != null;
   }
 
   /** {@inheritDoc} */
   @Override
   public boolean contains(NameIdentifier ident, Entity.EntityType type) {
     checkArguments(ident, type);
-    return cacheData.getIfPresent(EntityCacheKey.of(ident, type)) != null;
+    return cacheData.getIfPresent(EntityCacheRelationKey.of(ident, type)) != 
null;
   }
 
   /** {@inheritDoc} */
@@ -194,6 +206,7 @@ public class CaffeineEntityCache extends BaseEntityCache {
     withLock(
         () -> {
           cacheData.invalidateAll();
+          reverseIndex = new ConcurrentRadixTree<>(new 
DefaultCharArrayNodeFactory());
           cacheIndex = new ConcurrentRadixTree<>(new 
DefaultCharArrayNodeFactory());
         });
   }
@@ -214,7 +227,7 @@ public class CaffeineEntityCache extends BaseEntityCache {
           }
 
           syncEntitiesToCache(
-              EntityCacheKey.of(ident, type, relType),
+              EntityCacheRelationKey.of(ident, type, relType),
               entities.stream().map(e -> (Entity) 
e).collect(Collectors.toList()));
         });
   }
@@ -228,7 +241,8 @@ public class CaffeineEntityCache extends BaseEntityCache {
         () -> {
           invalidateOnKeyChange(entity);
           NameIdentifier identifier = getIdentFromEntity(entity);
-          EntityCacheKey entityCacheKey = EntityCacheKey.of(identifier, 
entity.type());
+          EntityCacheRelationKey entityCacheKey =
+              EntityCacheRelationKey.of(identifier, entity.type());
 
           syncEntitiesToCache(entityCacheKey, Lists.newArrayList(entity));
         });
@@ -272,6 +286,7 @@ public class CaffeineEntityCache extends BaseEntityCache {
   protected void invalidateExpiredItem(EntityCacheKey key) {
     withLock(
         () -> {
+          reverseIndex.remove(key.toString());
           cacheIndex.remove(key.toString());
         });
   }
@@ -283,7 +298,7 @@ public class CaffeineEntityCache extends BaseEntityCache {
    * @param key The key of the entities.
    * @param newEntities The new entities to sync to the cache.
    */
-  private void syncEntitiesToCache(EntityCacheKey key, List<Entity> 
newEntities) {
+  private void syncEntitiesToCache(EntityCacheRelationKey key, List<Entity> 
newEntities) {
     List<Entity> existingEntities = cacheData.getIfPresent(key);
 
     if (existingEntities != null && key.relationType() != null) {
@@ -294,6 +309,10 @@ public class CaffeineEntityCache extends BaseEntityCache {
 
     cacheData.put(key, newEntities);
 
+    for (Entity entity : newEntities) {
+      putReverseIndex(entity, key);
+    }
+
     if (cacheData.policy().getIfPresentQuietly(key) != null) {
       cacheIndex.put(key.toString(), key);
     }
@@ -330,6 +349,32 @@ public class CaffeineEntityCache extends BaseEntityCache {
     return (Caffeine<KEY, VALUE>) builder;
   }
 
+  private NameIdentifier getNameIdentifier(Entity entity) {
+    NameIdentifier nameIdent =
+        NameIdentifier.of(((HasIdentifier) entity).namespace(), 
((HasIdentifier) entity).name());
+    return nameIdent;
+  }
+
+  private EntityCacheKey makeEntityCacheKey(Entity entity) {
+    NameIdentifier nameIdent = getNameIdentifier(entity);
+    EntityCacheKey entityCacheKey = EntityCacheKey.of(nameIdent, 
entity.type());
+    return entityCacheKey;
+  }
+
+  public void putReverseIndex(Entity entity, EntityCacheRelationKey key) {
+    Preconditions.checkArgument(entity != null, "EntityCacheRelationKey cannot 
be null");
+
+    if (entity instanceof HasIdentifier) {
+      EntityCacheKey entityCacheKey = makeEntityCacheKey(entity);
+      String strEntityCacheKey = entityCacheKey.toString();
+      List<EntityCacheKey> entityKeysToRemove =
+          
Lists.newArrayList(reverseIndex.getValuesForKeysStartingWith(strEntityCacheKey));
+      String strEntityCacheKeyNo =
+          String.format("%s-%d", strEntityCacheKey, entityKeysToRemove.size());
+      reverseIndex.put(strEntityCacheKeyNo, key);
+    }
+  }
+
   /**
    * Invalidates the entities by the given cache key.
    *
@@ -339,8 +384,51 @@ public class CaffeineEntityCache extends BaseEntityCache {
     List<EntityCacheKey> entityKeysToRemove =
         
Lists.newArrayList(cacheIndex.getValuesForKeysStartingWith(identifier.toString()));
 
+    Map<EntityCacheRelationKey, List<Entity>> relationEnitiesMap =
+        cacheData.getAllPresent(entityKeysToRemove);
+    // SCENE[1]
+    // RECORD1 = Role1 -> [catalog1, catalog2]
+    // RECORD2 = catalog1 -> [tab1, tab2]
+    // INVALIDATE Role1, then need to remove RECORD1 and RECORD2
+    relationEnitiesMap.forEach(
+        (key, entities) -> {
+          entities.forEach(
+              entity -> {
+                NameIdentifier child = getNameIdentifier(entity);
+                if (!child.equals(identifier)) {
+                  invalidateEntities(child);
+                }
+              });
+        });
+
+    // SCENE[2]
+    // RECORD1 = Role1 -> [catalog1, catalog2]
+    // RECORD2 = catalog1 -> [tab1, tab2]
+    // INVALIDATE catalog1, then need to remove RECORD1 and RECORD2
+    //
+    // SCENE[3]
+    // RECORD1 = Metadata1 -> []
+    // RECORD2 = Metadata1.Catalog1.tab1 -> []
+    // INVALIDATE Metadata1, then need to remove RECORD1 and RECORD2
+    List<EntityCacheKey> reverseKeysToRemove =
+        
Lists.newArrayList(reverseIndex.getValuesForKeysStartingWith(identifier.toString()));
+    reverseKeysToRemove.forEach(
+        key -> {
+          // If the key is the same as the entity key, we can remove it from 
the cache.
+          cacheData.invalidate(key);
+          cacheIndex.remove(key.toString());
+          // Remove from reverse index
+          // Convert EntityCacheRelationKey to EntityCacheKey
+          EntityCacheKey reverseKey = EntityCacheKey.of(key.identifier(), 
key.entityType());
+          reverseIndex
+              .getKeysStartingWith(reverseKey.toString())
+              .forEach(
+                  reverseIndexKey -> {
+                    reverseIndex.remove(reverseIndexKey.toString());
+                  });
+        });
+
     cacheData.invalidateAll(entityKeysToRemove);
-    entityKeysToRemove.forEach(key -> cacheIndex.remove(key.toString()));
 
     return !entityKeysToRemove.isEmpty();
   }
diff --git a/core/src/main/java/org/apache/gravitino/cache/EntityCacheKey.java 
b/core/src/main/java/org/apache/gravitino/cache/EntityCacheKey.java
index c59dc68af0..229715e184 100644
--- a/core/src/main/java/org/apache/gravitino/cache/EntityCacheKey.java
+++ b/core/src/main/java/org/apache/gravitino/cache/EntityCacheKey.java
@@ -23,26 +23,11 @@ import com.google.common.base.Preconditions;
 import java.util.Objects;
 import org.apache.gravitino.Entity;
 import org.apache.gravitino.NameIdentifier;
-import org.apache.gravitino.SupportsRelationOperations;
 
 /** Key for Entity cache. */
 public class EntityCacheKey {
   private final NameIdentifier identifier;
   private final Entity.EntityType type;
-  private final SupportsRelationOperations.Type relationType;
-
-  /**
-   * Creates a new instance of {@link EntityCacheKey} with the given arguments.
-   *
-   * @param ident The identifier of the entity.
-   * @param type The type of the entity.
-   * @param relationType The type of the relation, it can be null.
-   * @return A new instance of {@link EntityCacheKey}.
-   */
-  public static EntityCacheKey of(
-      NameIdentifier ident, Entity.EntityType type, 
SupportsRelationOperations.Type relationType) {
-    return new EntityCacheKey(ident, type, relationType);
-  }
 
   /**
    * Creates a new instance of {@link EntityCacheKey} with the given arguments.
@@ -52,7 +37,7 @@ public class EntityCacheKey {
    * @return A new instance of {@link EntityCacheKey}.
    */
   public static EntityCacheKey of(NameIdentifier ident, Entity.EntityType 
type) {
-    return new EntityCacheKey(ident, type, null);
+    return new EntityCacheKey(ident, type);
   }
 
   /**
@@ -60,18 +45,13 @@ public class EntityCacheKey {
    *
    * @param identifier The identifier of the entity.
    * @param type The type of the entity.
-   * @param relationType The type of the relation.
    */
-  private EntityCacheKey(
-      NameIdentifier identifier,
-      Entity.EntityType type,
-      SupportsRelationOperations.Type relationType) {
+  EntityCacheKey(NameIdentifier identifier, Entity.EntityType type) {
     Preconditions.checkArgument(identifier != null, "identifier cannot be 
null");
     Preconditions.checkArgument(type != null, "type cannot be null");
 
     this.identifier = identifier;
     this.type = type;
-    this.relationType = relationType;
   }
 
   /**
@@ -92,15 +72,6 @@ public class EntityCacheKey {
     return type;
   }
 
-  /**
-   * Returns the type of the relation.
-   *
-   * @return The type of the relation.
-   */
-  public SupportsRelationOperations.Type relationType() {
-    return relationType;
-  }
-
   /**
    * Compares two instances of {@link EntityCacheKey} for equality. The 
comparison is done by
    * comparing the identifier, type, and relationType of the instances.
@@ -114,9 +85,7 @@ public class EntityCacheKey {
     if (!(obj instanceof EntityCacheKey)) return false;
     EntityCacheKey other = (EntityCacheKey) obj;
 
-    return Objects.equals(identifier, other.identifier)
-        && Objects.equals(type, other.type)
-        && Objects.equals(relationType, other.relationType);
+    return Objects.equals(identifier, other.identifier) && 
Objects.equals(type, other.type);
   }
 
   /**
@@ -127,7 +96,7 @@ public class EntityCacheKey {
    */
   @Override
   public int hashCode() {
-    return Objects.hash(identifier, type, relationType);
+    return Objects.hash(identifier, type);
   }
 
   /**
@@ -139,9 +108,6 @@ public class EntityCacheKey {
   @Override
   public String toString() {
     String stringExpr = identifier.toString() + ":" + type.toString();
-    if (relationType != null) {
-      stringExpr += ":" + relationType.name();
-    }
 
     return stringExpr;
   }
diff --git a/core/src/main/java/org/apache/gravitino/cache/EntityCacheKey.java 
b/core/src/main/java/org/apache/gravitino/cache/EntityCacheRelationKey.java
similarity index 61%
copy from core/src/main/java/org/apache/gravitino/cache/EntityCacheKey.java
copy to 
core/src/main/java/org/apache/gravitino/cache/EntityCacheRelationKey.java
index c59dc68af0..8db9937aff 100644
--- a/core/src/main/java/org/apache/gravitino/cache/EntityCacheKey.java
+++ b/core/src/main/java/org/apache/gravitino/cache/EntityCacheRelationKey.java
@@ -19,79 +19,54 @@
 
 package org.apache.gravitino.cache;
 
-import com.google.common.base.Preconditions;
 import java.util.Objects;
 import org.apache.gravitino.Entity;
 import org.apache.gravitino.NameIdentifier;
 import org.apache.gravitino.SupportsRelationOperations;
 
 /** Key for Entity cache. */
-public class EntityCacheKey {
-  private final NameIdentifier identifier;
-  private final Entity.EntityType type;
+public class EntityCacheRelationKey extends EntityCacheKey {
   private final SupportsRelationOperations.Type relationType;
 
   /**
-   * Creates a new instance of {@link EntityCacheKey} with the given arguments.
+   * Creates a new instance of {@link EntityCacheRelationKey} with the given 
arguments.
    *
    * @param ident The identifier of the entity.
    * @param type The type of the entity.
    * @param relationType The type of the relation, it can be null.
-   * @return A new instance of {@link EntityCacheKey}.
+   * @return A new instance of {@link EntityCacheRelationKey}.
    */
-  public static EntityCacheKey of(
+  public static EntityCacheRelationKey of(
       NameIdentifier ident, Entity.EntityType type, 
SupportsRelationOperations.Type relationType) {
-    return new EntityCacheKey(ident, type, relationType);
+    return new EntityCacheRelationKey(ident, type, relationType);
   }
 
   /**
-   * Creates a new instance of {@link EntityCacheKey} with the given arguments.
+   * Creates a new instance of {@link EntityCacheRelationKey} with the given 
arguments.
    *
    * @param ident The identifier of the entity.
    * @param type The type of the entity.
-   * @return A new instance of {@link EntityCacheKey}.
+   * @return A new instance of {@link EntityCacheRelationKey}.
    */
-  public static EntityCacheKey of(NameIdentifier ident, Entity.EntityType 
type) {
-    return new EntityCacheKey(ident, type, null);
+  public static EntityCacheRelationKey of(NameIdentifier ident, 
Entity.EntityType type) {
+    return new EntityCacheRelationKey(ident, type, null);
   }
 
   /**
-   * Creates a new instance of {@link EntityCacheKey} with the given 
parameters.
+   * Creates a new instance of {@link EntityCacheRelationKey} with the given 
parameters.
    *
    * @param identifier The identifier of the entity.
    * @param type The type of the entity.
    * @param relationType The type of the relation.
    */
-  private EntityCacheKey(
+  private EntityCacheRelationKey(
       NameIdentifier identifier,
       Entity.EntityType type,
       SupportsRelationOperations.Type relationType) {
-    Preconditions.checkArgument(identifier != null, "identifier cannot be 
null");
-    Preconditions.checkArgument(type != null, "type cannot be null");
-
-    this.identifier = identifier;
-    this.type = type;
+    super(identifier, type);
     this.relationType = relationType;
   }
 
-  /**
-   * Returns the identifier of the entity.
-   *
-   * @return The identifier of the entity.
-   */
-  public NameIdentifier identifier() {
-    return identifier;
-  }
-
-  /**
-   * Returns the type of the entity.
-   *
-   * @return The type of the entity.
-   */
-  public Entity.EntityType entityType() {
-    return type;
-  }
-
   /**
    * Returns the type of the relation.
    *
@@ -102,8 +77,8 @@ public class EntityCacheKey {
   }
 
   /**
-   * Compares two instances of {@link EntityCacheKey} for equality. The 
comparison is done by
-   * comparing the identifier, type, and relationType of the instances.
+   * Compares two instances of {@link EntityCacheRelationKey} for equality. 
The comparison is done
+   * by comparing the identifier, type, and relationType of the instances.
    *
    * @param obj The object to compare to.
    * @return {@code true} if the objects are equal, {@code false} otherwise.
@@ -111,11 +86,11 @@ public class EntityCacheKey {
   @Override
   public boolean equals(Object obj) {
     if (obj == this) return true;
-    if (!(obj instanceof EntityCacheKey)) return false;
-    EntityCacheKey other = (EntityCacheKey) obj;
+    if (!(obj instanceof EntityCacheRelationKey)) return false;
+    EntityCacheRelationKey other = (EntityCacheRelationKey) obj;
 
-    return Objects.equals(identifier, other.identifier)
-        && Objects.equals(type, other.type)
+    return Objects.equals(super.identifier(), other.identifier())
+        && Objects.equals(super.entityType(), other.entityType())
         && Objects.equals(relationType, other.relationType);
   }
 
@@ -127,7 +102,7 @@ public class EntityCacheKey {
    */
   @Override
   public int hashCode() {
-    return Objects.hash(identifier, type, relationType);
+    return Objects.hash(super.identifier(), super.entityType(), relationType);
   }
 
   /**
@@ -138,7 +113,7 @@ public class EntityCacheKey {
    */
   @Override
   public String toString() {
-    String stringExpr = identifier.toString() + ":" + type.toString();
+    String stringExpr = super.identifier().toString() + ":" + 
super.entityType().toString();
     if (relationType != null) {
       stringExpr += ":" + relationType.name();
     }
diff --git a/core/src/test/java/org/apache/gravitino/cache/TestCacheIndex.java 
b/core/src/test/java/org/apache/gravitino/cache/TestCacheIndex.java
index d87995fdea..cea1f2867a 100644
--- a/core/src/test/java/org/apache/gravitino/cache/TestCacheIndex.java
+++ b/core/src/test/java/org/apache/gravitino/cache/TestCacheIndex.java
@@ -33,7 +33,7 @@ import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
 public class TestCacheIndex {
-  private RadixTree<EntityCacheKey> indexTree;
+  private RadixTree<EntityCacheRelationKey> indexTree;
 
   private NameIdentifier ident1;
   private NameIdentifier ident2;
@@ -48,18 +48,18 @@ public class TestCacheIndex {
   private NameIdentifier ident11;
   private NameIdentifier ident12;
 
-  private EntityCacheKey key1;
-  private EntityCacheKey key2;
-  private EntityCacheKey key3;
-  private EntityCacheKey key4;
-  private EntityCacheKey key5;
-  private EntityCacheKey key6;
-  private EntityCacheKey key7;
-  private EntityCacheKey key8;
-  private EntityCacheKey key9;
-  private EntityCacheKey key10;
-  private EntityCacheKey key11;
-  private EntityCacheKey key12;
+  private EntityCacheRelationKey key1;
+  private EntityCacheRelationKey key2;
+  private EntityCacheRelationKey key3;
+  private EntityCacheRelationKey key4;
+  private EntityCacheRelationKey key5;
+  private EntityCacheRelationKey key6;
+  private EntityCacheRelationKey key7;
+  private EntityCacheRelationKey key8;
+  private EntityCacheRelationKey key9;
+  private EntityCacheRelationKey key10;
+  private EntityCacheRelationKey key11;
+  private EntityCacheRelationKey key12;
 
   @BeforeEach
   void setUp() {
@@ -80,24 +80,24 @@ public class TestCacheIndex {
     ident11 = NameIdentifierUtil.ofUser("metalake2", "user1");
     ident12 = NameIdentifierUtil.ofUser("metalake2", "user2");
 
-    key1 = EntityCacheKey.of(ident1, Entity.EntityType.SCHEMA);
-    key2 = EntityCacheKey.of(ident2, Entity.EntityType.SCHEMA);
-    key3 = EntityCacheKey.of(ident3, Entity.EntityType.TABLE);
-    key4 = EntityCacheKey.of(ident4, Entity.EntityType.TOPIC);
-    key5 = EntityCacheKey.of(ident5, Entity.EntityType.TABLE);
-    key6 = EntityCacheKey.of(ident6, Entity.EntityType.TABLE);
+    key1 = EntityCacheRelationKey.of(ident1, Entity.EntityType.SCHEMA);
+    key2 = EntityCacheRelationKey.of(ident2, Entity.EntityType.SCHEMA);
+    key3 = EntityCacheRelationKey.of(ident3, Entity.EntityType.TABLE);
+    key4 = EntityCacheRelationKey.of(ident4, Entity.EntityType.TOPIC);
+    key5 = EntityCacheRelationKey.of(ident5, Entity.EntityType.TABLE);
+    key6 = EntityCacheRelationKey.of(ident6, Entity.EntityType.TABLE);
 
     key7 =
-        EntityCacheKey.of(
+        EntityCacheRelationKey.of(
             ident7, Entity.EntityType.ROLE, 
SupportsRelationOperations.Type.ROLE_GROUP_REL);
     key8 =
-        EntityCacheKey.of(
+        EntityCacheRelationKey.of(
             ident8, Entity.EntityType.ROLE, 
SupportsRelationOperations.Type.ROLE_USER_REL);
 
-    key9 = EntityCacheKey.of(ident9, Entity.EntityType.GROUP);
-    key10 = EntityCacheKey.of(ident10, Entity.EntityType.GROUP);
-    key11 = EntityCacheKey.of(ident11, Entity.EntityType.USER);
-    key12 = EntityCacheKey.of(ident12, Entity.EntityType.USER);
+    key9 = EntityCacheRelationKey.of(ident9, Entity.EntityType.GROUP);
+    key10 = EntityCacheRelationKey.of(ident10, Entity.EntityType.GROUP);
+    key11 = EntityCacheRelationKey.of(ident11, Entity.EntityType.USER);
+    key12 = EntityCacheRelationKey.of(ident12, Entity.EntityType.USER);
 
     addIndex(indexTree, key12);
     addIndex(indexTree, key11);
@@ -120,107 +120,110 @@ public class TestCacheIndex {
 
   @Test
   void testGetFromByMetalakePrefix() {
-    List<EntityCacheKey> storeEntityCacheKeys =
+    List<EntityCacheRelationKey> storeEntityCacheRelationKeys =
         
ImmutableList.copyOf(indexTree.getValuesForKeysStartingWith("metalake1"));
 
-    Assertions.assertEquals(8, storeEntityCacheKeys.size());
-    Assertions.assertTrue(storeEntityCacheKeys.contains(key1));
-    Assertions.assertTrue(storeEntityCacheKeys.contains(key3));
-    Assertions.assertTrue(storeEntityCacheKeys.contains(key4));
-    Assertions.assertTrue(storeEntityCacheKeys.contains(key5));
-    Assertions.assertTrue(storeEntityCacheKeys.contains(key6));
-    Assertions.assertTrue(storeEntityCacheKeys.contains(key7));
-    Assertions.assertTrue(storeEntityCacheKeys.contains(key9));
-    Assertions.assertTrue(storeEntityCacheKeys.contains(key10));
-
-    List<EntityCacheKey> storeEntityCacheKeys2 =
+    Assertions.assertEquals(8, storeEntityCacheRelationKeys.size());
+    Assertions.assertTrue(storeEntityCacheRelationKeys.contains(key1));
+    Assertions.assertTrue(storeEntityCacheRelationKeys.contains(key3));
+    Assertions.assertTrue(storeEntityCacheRelationKeys.contains(key4));
+    Assertions.assertTrue(storeEntityCacheRelationKeys.contains(key5));
+    Assertions.assertTrue(storeEntityCacheRelationKeys.contains(key6));
+    Assertions.assertTrue(storeEntityCacheRelationKeys.contains(key7));
+    Assertions.assertTrue(storeEntityCacheRelationKeys.contains(key9));
+    Assertions.assertTrue(storeEntityCacheRelationKeys.contains(key10));
+
+    List<EntityCacheRelationKey> storeEntityCacheRelationKeys2 =
         
ImmutableList.copyOf(indexTree.getValuesForKeysStartingWith("metalake2"));
 
-    Assertions.assertEquals(4, storeEntityCacheKeys2.size());
-    Assertions.assertTrue(storeEntityCacheKeys2.contains(key2));
-    Assertions.assertTrue(storeEntityCacheKeys2.contains(key8));
-    Assertions.assertTrue(storeEntityCacheKeys2.contains(key11));
-    Assertions.assertTrue(storeEntityCacheKeys2.contains(key12));
+    Assertions.assertEquals(4, storeEntityCacheRelationKeys2.size());
+    Assertions.assertTrue(storeEntityCacheRelationKeys2.contains(key2));
+    Assertions.assertTrue(storeEntityCacheRelationKeys2.contains(key8));
+    Assertions.assertTrue(storeEntityCacheRelationKeys2.contains(key11));
+    Assertions.assertTrue(storeEntityCacheRelationKeys2.contains(key12));
   }
 
   @Test
   void testGetByCatalogPrefix() {
-    List<EntityCacheKey> storeEntityCacheKeys =
+    List<EntityCacheRelationKey> storeEntityCacheRelationKeys =
         
ImmutableList.copyOf(indexTree.getValuesForKeysStartingWith("metalake1.catalog1"));
 
-    Assertions.assertEquals(4, storeEntityCacheKeys.size());
-    Assertions.assertTrue(storeEntityCacheKeys.contains(key1));
-    Assertions.assertTrue(storeEntityCacheKeys.contains(key3));
-    Assertions.assertTrue(storeEntityCacheKeys.contains(key4));
-    Assertions.assertTrue(storeEntityCacheKeys.contains(key6));
+    Assertions.assertEquals(4, storeEntityCacheRelationKeys.size());
+    Assertions.assertTrue(storeEntityCacheRelationKeys.contains(key1));
+    Assertions.assertTrue(storeEntityCacheRelationKeys.contains(key3));
+    Assertions.assertTrue(storeEntityCacheRelationKeys.contains(key4));
+    Assertions.assertTrue(storeEntityCacheRelationKeys.contains(key6));
 
-    storeEntityCacheKeys =
+    storeEntityCacheRelationKeys =
         
ImmutableList.copyOf(indexTree.getValuesForKeysStartingWith("metalake1.catalog2"));
-    Assertions.assertEquals(1, storeEntityCacheKeys.size());
-    Assertions.assertTrue(storeEntityCacheKeys.contains(key5));
+    Assertions.assertEquals(1, storeEntityCacheRelationKeys.size());
+    Assertions.assertTrue(storeEntityCacheRelationKeys.contains(key5));
   }
 
   @Test
   void testGetBySchemaPrefix() {
-    List<EntityCacheKey> storeEntityCacheKeys =
+    List<EntityCacheRelationKey> storeEntityCacheRelationKeys =
         
ImmutableList.copyOf(indexTree.getValuesForKeysStartingWith("metalake1.catalog1.schema1"));
 
-    Assertions.assertEquals(3, storeEntityCacheKeys.size());
-    Assertions.assertTrue(storeEntityCacheKeys.contains(key1));
-    Assertions.assertTrue(storeEntityCacheKeys.contains(key3));
-    Assertions.assertTrue(storeEntityCacheKeys.contains(key4));
+    Assertions.assertEquals(3, storeEntityCacheRelationKeys.size());
+    Assertions.assertTrue(storeEntityCacheRelationKeys.contains(key1));
+    Assertions.assertTrue(storeEntityCacheRelationKeys.contains(key3));
+    Assertions.assertTrue(storeEntityCacheRelationKeys.contains(key4));
 
-    storeEntityCacheKeys =
+    storeEntityCacheRelationKeys =
         
ImmutableList.copyOf(indexTree.getValuesForKeysStartingWith("metalake1.catalog1.schema2"));
-    Assertions.assertEquals(1, storeEntityCacheKeys.size());
-    Assertions.assertTrue(storeEntityCacheKeys.contains(key6));
+    Assertions.assertEquals(1, storeEntityCacheRelationKeys.size());
+    Assertions.assertTrue(storeEntityCacheRelationKeys.contains(key6));
 
-    storeEntityCacheKeys =
+    storeEntityCacheRelationKeys =
         
ImmutableList.copyOf(indexTree.getValuesForKeysStartingWith("metalake1.catalog2.schema1"));
-    Assertions.assertEquals(1, storeEntityCacheKeys.size());
-    Assertions.assertTrue(storeEntityCacheKeys.contains(key5));
+    Assertions.assertEquals(1, storeEntityCacheRelationKeys.size());
+    Assertions.assertTrue(storeEntityCacheRelationKeys.contains(key5));
   }
 
   @Test
   void testGetByExactKey() {
-    EntityCacheKey storeEntityCacheKey = 
indexTree.getValueForExactKey(key1.toString());
-    Assertions.assertEquals(key1, storeEntityCacheKey);
+    EntityCacheRelationKey storeEntityCacheRelationKey =
+        indexTree.getValueForExactKey(key1.toString());
+    Assertions.assertEquals(key1, storeEntityCacheRelationKey);
 
-    storeEntityCacheKey = indexTree.getValueForExactKey(key2.toString());
-    Assertions.assertEquals(key2, storeEntityCacheKey);
+    storeEntityCacheRelationKey = 
indexTree.getValueForExactKey(key2.toString());
+    Assertions.assertEquals(key2, storeEntityCacheRelationKey);
 
-    storeEntityCacheKey = indexTree.getValueForExactKey(key3.toString());
-    Assertions.assertEquals(key3, storeEntityCacheKey);
+    storeEntityCacheRelationKey = 
indexTree.getValueForExactKey(key3.toString());
+    Assertions.assertEquals(key3, storeEntityCacheRelationKey);
 
-    storeEntityCacheKey = indexTree.getValueForExactKey(key4.toString());
-    Assertions.assertEquals(key4, storeEntityCacheKey);
+    storeEntityCacheRelationKey = 
indexTree.getValueForExactKey(key4.toString());
+    Assertions.assertEquals(key4, storeEntityCacheRelationKey);
 
-    storeEntityCacheKey = indexTree.getValueForExactKey(key5.toString());
-    Assertions.assertEquals(key5, storeEntityCacheKey);
+    storeEntityCacheRelationKey = 
indexTree.getValueForExactKey(key5.toString());
+    Assertions.assertEquals(key5, storeEntityCacheRelationKey);
 
-    storeEntityCacheKey = indexTree.getValueForExactKey(key6.toString());
-    Assertions.assertEquals(key6, storeEntityCacheKey);
+    storeEntityCacheRelationKey = 
indexTree.getValueForExactKey(key6.toString());
+    Assertions.assertEquals(key6, storeEntityCacheRelationKey);
 
-    storeEntityCacheKey = indexTree.getValueForExactKey(key7.toString());
-    Assertions.assertEquals(key7, storeEntityCacheKey);
+    storeEntityCacheRelationKey = 
indexTree.getValueForExactKey(key7.toString());
+    Assertions.assertEquals(key7, storeEntityCacheRelationKey);
 
-    storeEntityCacheKey = indexTree.getValueForExactKey(key8.toString());
-    Assertions.assertEquals(key8, storeEntityCacheKey);
+    storeEntityCacheRelationKey = 
indexTree.getValueForExactKey(key8.toString());
+    Assertions.assertEquals(key8, storeEntityCacheRelationKey);
 
-    storeEntityCacheKey = indexTree.getValueForExactKey(key9.toString());
-    Assertions.assertEquals(key9, storeEntityCacheKey);
+    storeEntityCacheRelationKey = 
indexTree.getValueForExactKey(key9.toString());
+    Assertions.assertEquals(key9, storeEntityCacheRelationKey);
 
-    storeEntityCacheKey = indexTree.getValueForExactKey(key10.toString());
-    Assertions.assertEquals(key10, storeEntityCacheKey);
+    storeEntityCacheRelationKey = 
indexTree.getValueForExactKey(key10.toString());
+    Assertions.assertEquals(key10, storeEntityCacheRelationKey);
 
-    storeEntityCacheKey = indexTree.getValueForExactKey(key11.toString());
-    Assertions.assertEquals(key11, storeEntityCacheKey);
+    storeEntityCacheRelationKey = 
indexTree.getValueForExactKey(key11.toString());
+    Assertions.assertEquals(key11, storeEntityCacheRelationKey);
 
-    storeEntityCacheKey = indexTree.getValueForExactKey(key12.toString());
-    Assertions.assertEquals(key12, storeEntityCacheKey);
+    storeEntityCacheRelationKey = 
indexTree.getValueForExactKey(key12.toString());
+    Assertions.assertEquals(key12, storeEntityCacheRelationKey);
   }
 
-  private void addIndex(RadixTree<EntityCacheKey> indexTree, EntityCacheKey 
storeEntityCacheKey) {
-    indexTree.put(storeEntityCacheKey.toString(), storeEntityCacheKey);
+  private void addIndex(
+      RadixTree<EntityCacheRelationKey> indexTree,
+      EntityCacheRelationKey storeEntityCacheRelationKey) {
+    indexTree.put(storeEntityCacheRelationKey.toString(), 
storeEntityCacheRelationKey);
   }
 }
diff --git 
a/core/src/test/java/org/apache/gravitino/cache/TestCaffeineEntityCache.java 
b/core/src/test/java/org/apache/gravitino/cache/TestCaffeineEntityCache.java
index 2b9e29146e..f40bde83ce 100644
--- a/core/src/test/java/org/apache/gravitino/cache/TestCaffeineEntityCache.java
+++ b/core/src/test/java/org/apache/gravitino/cache/TestCaffeineEntityCache.java
@@ -58,19 +58,19 @@ import org.mockito.MockedStatic;
 @TestInstance(TestInstance.Lifecycle.PER_METHOD)
 public class TestCaffeineEntityCache {
   // Test Entities.
-  private static SchemaEntity entity1;
-  private static SchemaEntity entity2;
-  private static TableEntity entity3;
-  private static TableEntity entity4;
-  private static TableEntity entity5;
-  private static CatalogEntity entity6;
-  private static BaseMetalake entity7;
-  private static UserEntity entity8;
-  private static UserEntity entity9;
-  private static GroupEntity entity10;
-  private static GroupEntity entity11;
-  private static RoleEntity entity12;
-  private static RoleEntity entity13;
+  private static SchemaEntity entity_m1c1s1;
+  private static SchemaEntity entity_m2c2s2;
+  private static TableEntity entity_m1c1s1t1;
+  private static TableEntity entity_m1c2s1t2;
+  private static TableEntity entity_m1c1s2t3;
+  private static CatalogEntity entity_m1c1;
+  private static BaseMetalake entity_m1;
+  private static UserEntity entity_m1u1;
+  private static UserEntity entity_m1u2;
+  private static GroupEntity entity_m2g1;
+  private static GroupEntity entity_m2g2;
+  private static RoleEntity entity_m1r1;
+  private static RoleEntity entity_m2r2;
 
   private static Object getCacheDataFrom(EntityCache cache) {
     try {
@@ -87,31 +87,33 @@ public class TestCaffeineEntityCache {
 
   @BeforeAll
   static void initTestEntities() {
-    entity1 =
+    entity_m1c1s1 =
         TestUtil.getTestSchemaEntity(
             1L, "schema1", Namespace.of("metalake1", "catalog1"), 
"test_schema1");
-    entity2 =
+    entity_m2c2s2 =
         TestUtil.getTestSchemaEntity(
             2L, "schema2", Namespace.of("metalake2", "catalog2"), 
"test_schema2");
-    entity3 =
+    entity_m1c1s1t1 =
         TestUtil.getTestTableEntity(3L, "table1", Namespace.of("metalake1", 
"catalog1", "schema1"));
-    entity4 =
+    entity_m1c2s1t2 =
         TestUtil.getTestTableEntity(4L, "table2", Namespace.of("metalake1", 
"catalog2", "schema1"));
-    entity5 =
+    entity_m1c1s2t3 =
         TestUtil.getTestTableEntity(5L, "table3", Namespace.of("metalake1", 
"catalog1", "schema2"));
-    entity6 =
+    entity_m1c1 =
         TestUtil.getTestCatalogEntity(
             6L, "catalog1", Namespace.of("metalake1"), "hive", "test_catalog");
-    entity7 = TestUtil.getTestMetalake(7L, "metalake1", "test_metalake1");
+    entity_m1 = TestUtil.getTestMetalake(7L, "metalake1", "test_metalake1");
 
-    entity8 = TestUtil.getTestUserEntity(8L, "user1", "metalake1", 
ImmutableList.of(12L));
-    entity9 = TestUtil.getTestUserEntity(9L, "user2", "metalake1", 
ImmutableList.of(12L));
+    entity_m1u1 = TestUtil.getTestUserEntity(8L, "user1", "metalake1", 
ImmutableList.of(12L));
+    entity_m1u2 = TestUtil.getTestUserEntity(9L, "user2", "metalake1", 
ImmutableList.of(12L));
 
-    entity10 = TestUtil.getTestGroupEntity(10L, "group1", "metalake2", 
ImmutableList.of("role2"));
-    entity11 = TestUtil.getTestGroupEntity(11L, "group2", "metalake2", 
ImmutableList.of("role2"));
+    entity_m2g1 =
+        TestUtil.getTestGroupEntity(10L, "group1", "metalake2", 
ImmutableList.of("role2"));
+    entity_m2g2 =
+        TestUtil.getTestGroupEntity(11L, "group2", "metalake2", 
ImmutableList.of("role2"));
 
-    entity12 = TestUtil.getTestRoleEntity(12L, "role1", "metalake1");
-    entity13 = TestUtil.getTestRoleEntity(13L, "role2", "metalake2");
+    entity_m1r1 = TestUtil.getTestRoleEntity(12L, "role1", "metalake1");
+    entity_m2r2 = TestUtil.getTestRoleEntity(13L, "role2", "metalake2");
   }
 
   @Test
@@ -120,7 +122,109 @@ public class TestCaffeineEntityCache {
     config.set(Configs.CACHE_STATS_ENABLED, true);
     EntityCache cache = new CaffeineEntityCache(config);
 
-    Assertions.assertDoesNotThrow(() -> cache.put(entity1));
+    Assertions.assertDoesNotThrow(() -> cache.put(entity_m1c1s1));
+  }
+
+  @Test
+  /**
+   * SCENE[0] CACHE1 = Role1 -> [catalog1, catalog2] ACTIVE: INVALIDATE Role1, 
then need to remove
+   * RECORD1 and RECORD2
+   */
+  void testRemoveCacheRelation0() {
+    EntityCache cache = getNormalCache();
+
+    UserEntity testUserEntity = TestUtil.getTestUserEntity();
+    GroupEntity testGroupEntity = TestUtil.getTestGroupEntity();
+    RoleEntity testRoleEntity = TestUtil.getTestRoleEntity();
+
+    cache.put(
+        testRoleEntity.nameIdentifier(),
+        Entity.EntityType.ROLE,
+        SupportsRelationOperations.Type.ROLE_GROUP_REL,
+        ImmutableList.of(testGroupEntity));
+    cache.put(
+        testRoleEntity.nameIdentifier(),
+        Entity.EntityType.ROLE,
+        SupportsRelationOperations.Type.ROLE_USER_REL,
+        ImmutableList.of(testUserEntity));
+
+    cache.invalidate(testRoleEntity.nameIdentifier(), Entity.EntityType.ROLE);
+
+    Assertions.assertEquals(0, cache.size());
+  }
+
+  @Test
+  /**
+   * SCENE[1] CACHE1 = Role1 -> [catalog1, catalog2] CACHE2 = catalog1 -> 
[tab1, tab2] ACTIVE:
+   * INVALIDATE Role1, then need to remove RECORD1 and RECORD2
+   */
+  void testRemoveCacheRelation1() {
+    EntityCache cache = getNormalCache();
+
+    UserEntity testUserEntity = TestUtil.getTestUserEntity();
+    GroupEntity testGroupEntity = TestUtil.getTestGroupEntity();
+    RoleEntity testRoleEntity = TestUtil.getTestRoleEntity();
+
+    cache.put(testGroupEntity);
+    cache.put(testUserEntity);
+
+    cache.put(
+        testRoleEntity.nameIdentifier(),
+        Entity.EntityType.ROLE,
+        SupportsRelationOperations.Type.ROLE_GROUP_REL,
+        ImmutableList.of(testGroupEntity));
+    cache.put(
+        testRoleEntity.nameIdentifier(),
+        Entity.EntityType.ROLE,
+        SupportsRelationOperations.Type.ROLE_USER_REL,
+        ImmutableList.of(testUserEntity));
+
+    cache.invalidate(testRoleEntity.nameIdentifier(), Entity.EntityType.ROLE);
+
+    Assertions.assertEquals(0, cache.size());
+  }
+
+  @Test
+  /**
+   * SCENE[2] CACHE1 = Role1 -> [catalog1, catalog2] CACHE2 = catalog1 -> 
[tab1, tab2] ACTIVE:
+   * INVALIDATE catalog1, then need to remove RECORD1 and RECORD2
+   */
+  void testRemoveCacheRelation2() {
+    EntityCache cache = getNormalCache();
+
+    GroupEntity testGroupEntity = TestUtil.getTestGroupEntity();
+    RoleEntity testRoleEntity = TestUtil.getTestRoleEntity();
+
+    cache.put(testGroupEntity);
+
+    cache.put(
+        testRoleEntity.nameIdentifier(),
+        Entity.EntityType.ROLE,
+        SupportsRelationOperations.Type.ROLE_GROUP_REL,
+        ImmutableList.of(testGroupEntity));
+
+    cache.invalidate(testGroupEntity.nameIdentifier(), 
Entity.EntityType.GROUP);
+
+    Assertions.assertEquals(0, cache.size());
+  }
+
+  @Test
+  /**
+   * SCENE[3] CACHE1 = Metadata1 -> [] CACHE2 = Metadata1.Catalog1.tab1 -> [] 
ACTIVE: INVALIDATE
+   * Metadata1, then need to remove RECORD1 and RECORD2
+   */
+  void testRemoveCacheRelation3() {
+    EntityCache cache = getNormalCache();
+
+    BaseMetalake testMetalake = TestUtil.getTestMetalake();
+    TableEntity testTableEntity = TestUtil.getTestTableEntity();
+
+    cache.put(testMetalake);
+    cache.put(testTableEntity);
+
+    cache.invalidate(testMetalake.nameIdentifier(), Entity.EntityType.CATALOG);
+
+    Assertions.assertEquals(0, cache.size());
   }
 
   @Test
@@ -236,51 +340,51 @@ public class TestCaffeineEntityCache {
   void testPutAndGet() {
     EntityCache cache = getNormalCache();
 
-    cache.put(entity1);
-    cache.put(entity2);
-    cache.put(entity3);
-    cache.put(entity4);
-    cache.put(entity5);
-    cache.put(entity6);
-    cache.put(entity7);
-    cache.put(entity8);
-    cache.put(entity9);
-    cache.put(entity10);
-    cache.put(entity11);
+    cache.put(entity_m1);
+    cache.put(entity_m1c1);
+    cache.put(entity_m1c1s1);
+    cache.put(entity_m1c1s1t1);
+    cache.put(entity_m1c2s1t2);
+    cache.put(entity_m1c1s2t3);
+    cache.put(entity_m2c2s2);
+    cache.put(entity_m1u1);
+    cache.put(entity_m1u2);
+    cache.put(entity_m2g1);
+    cache.put(entity_m2g2);
 
     cache.put(
-        entity12.nameIdentifier(),
+        entity_m1r1.nameIdentifier(),
         Entity.EntityType.ROLE,
         SupportsRelationOperations.Type.ROLE_USER_REL,
-        ImmutableList.of(entity8, entity9));
+        ImmutableList.of(entity_m1u1, entity_m1u2));
     cache.put(
-        entity13.nameIdentifier(),
+        entity_m2r2.nameIdentifier(),
         Entity.EntityType.ROLE,
         SupportsRelationOperations.Type.ROLE_GROUP_REL,
-        ImmutableList.of(entity10, entity11));
+        ImmutableList.of(entity_m2g1, entity_m2g2));
 
-    Assertions.assertTrue(cache.contains(entity1.nameIdentifier(), 
entity1.type()));
-    Assertions.assertTrue(cache.contains(entity2.nameIdentifier(), 
entity2.type()));
-    Assertions.assertTrue(cache.contains(entity3.nameIdentifier(), 
entity3.type()));
-    Assertions.assertTrue(cache.contains(entity4.nameIdentifier(), 
entity4.type()));
-    Assertions.assertTrue(cache.contains(entity5.nameIdentifier(), 
entity5.type()));
-    Assertions.assertTrue(cache.contains(entity6.nameIdentifier(), 
entity6.type()));
-    Assertions.assertTrue(cache.contains(entity7.nameIdentifier(), 
entity7.type()));
+    Assertions.assertTrue(cache.contains(entity_m1c1s1.nameIdentifier(), 
entity_m1c1s1.type()));
+    Assertions.assertTrue(cache.contains(entity_m2c2s2.nameIdentifier(), 
entity_m2c2s2.type()));
+    Assertions.assertTrue(cache.contains(entity_m1c1s1t1.nameIdentifier(), 
entity_m1c1s1t1.type()));
+    Assertions.assertTrue(cache.contains(entity_m1c2s1t2.nameIdentifier(), 
entity_m1c2s1t2.type()));
+    Assertions.assertTrue(cache.contains(entity_m1c1s2t3.nameIdentifier(), 
entity_m1c1s2t3.type()));
+    Assertions.assertTrue(cache.contains(entity_m1c1.nameIdentifier(), 
entity_m1c1.type()));
+    Assertions.assertTrue(cache.contains(entity_m1.nameIdentifier(), 
entity_m1.type()));
 
-    Assertions.assertTrue(cache.contains(entity8.nameIdentifier(), 
entity8.type()));
-    Assertions.assertTrue(cache.contains(entity9.nameIdentifier(), 
entity9.type()));
-    Assertions.assertTrue(cache.contains(entity10.nameIdentifier(), 
entity10.type()));
-    Assertions.assertTrue(cache.contains(entity11.nameIdentifier(), 
entity11.type()));
+    Assertions.assertTrue(cache.contains(entity_m1u1.nameIdentifier(), 
entity_m1u1.type()));
+    Assertions.assertTrue(cache.contains(entity_m1u2.nameIdentifier(), 
entity_m1u2.type()));
+    Assertions.assertTrue(cache.contains(entity_m2g1.nameIdentifier(), 
entity_m2g1.type()));
+    Assertions.assertTrue(cache.contains(entity_m2g2.nameIdentifier(), 
entity_m2g2.type()));
 
     Assertions.assertTrue(
         cache.contains(
-            entity12.nameIdentifier(),
-            entity12.type(),
+            entity_m1r1.nameIdentifier(),
+            entity_m1r1.type(),
             SupportsRelationOperations.Type.ROLE_USER_REL));
     Assertions.assertTrue(
         cache.contains(
-            entity13.nameIdentifier(),
-            entity13.type(),
+            entity_m2r2.nameIdentifier(),
+            entity_m2r2.type(),
             SupportsRelationOperations.Type.ROLE_GROUP_REL));
   }
 
@@ -288,61 +392,66 @@ public class TestCaffeineEntityCache {
   void testGetIfPresent() {
     EntityCache cache = getNormalCache();
 
-    cache.put(entity1);
-    cache.put(entity2);
-    cache.put(entity3);
+    cache.put(entity_m1c1s1);
+    cache.put(entity_m1c1s1t1);
+    cache.put(entity_m2c2s2);
     cache.put(
-        entity12.nameIdentifier(),
+        entity_m1r1.nameIdentifier(),
         Entity.EntityType.ROLE,
         SupportsRelationOperations.Type.ROLE_USER_REL,
-        ImmutableList.of(entity8, entity9));
+        ImmutableList.of(entity_m1u1, entity_m1u2));
 
-    Assertions.assertTrue(cache.getIfPresent(entity1.nameIdentifier(), 
entity1.type()).isPresent());
-    Assertions.assertTrue(cache.getIfPresent(entity2.nameIdentifier(), 
entity2.type()).isPresent());
-    Assertions.assertTrue(cache.getIfPresent(entity3.nameIdentifier(), 
entity3.type()).isPresent());
+    Assertions.assertTrue(
+        cache.getIfPresent(entity_m1c1s1.nameIdentifier(), 
entity_m1c1s1.type()).isPresent());
+    Assertions.assertTrue(
+        cache.getIfPresent(entity_m2c2s2.nameIdentifier(), 
entity_m2c2s2.type()).isPresent());
+    Assertions.assertTrue(
+        cache.getIfPresent(entity_m1c1s1t1.nameIdentifier(), 
entity_m1c1s1t1.type()).isPresent());
     Assertions.assertTrue(
         cache
             .getIfPresent(
                 SupportsRelationOperations.Type.ROLE_USER_REL,
-                entity12.nameIdentifier(),
-                entity12.type())
+                entity_m1r1.nameIdentifier(),
+                entity_m1r1.type())
             .isPresent());
     Assertions.assertEquals(cache.size(), 4);
 
     Assertions.assertFalse(
-        cache.getIfPresent(entity4.nameIdentifier(), 
entity4.type()).isPresent());
+        cache.getIfPresent(entity_m1c2s1t2.nameIdentifier(), 
entity_m1c2s1t2.type()).isPresent());
     Assertions.assertFalse(
-        cache.getIfPresent(entity5.nameIdentifier(), 
entity5.type()).isPresent());
+        cache.getIfPresent(entity_m1c1s2t3.nameIdentifier(), 
entity_m1c1s2t3.type()).isPresent());
     Assertions.assertFalse(
-        cache.getIfPresent(entity6.nameIdentifier(), 
entity6.type()).isPresent());
+        cache.getIfPresent(entity_m1c1.nameIdentifier(), 
entity_m1c1.type()).isPresent());
     Assertions.assertFalse(
-        cache.getIfPresent(entity7.nameIdentifier(), 
entity7.type()).isPresent());
+        cache.getIfPresent(entity_m1.nameIdentifier(), 
entity_m1.type()).isPresent());
   }
 
   @Test
   void testContains() {
     EntityCache cache = getNormalCache();
 
-    cache.put(entity1);
-    cache.put(entity2);
-    cache.put(entity3);
-
-    Assertions.assertTrue(cache.contains(entity1.nameIdentifier(), 
entity1.type()));
-    Assertions.assertTrue(cache.contains(entity2.nameIdentifier(), 
entity2.type()));
-    Assertions.assertTrue(cache.contains(entity3.nameIdentifier(), 
entity3.type()));
-    Assertions.assertFalse(cache.contains(entity4.nameIdentifier(), 
entity4.type()));
-    Assertions.assertFalse(cache.contains(entity5.nameIdentifier(), 
entity5.type()));
-    Assertions.assertFalse(cache.contains(entity6.nameIdentifier(), 
entity6.type()));
-    Assertions.assertFalse(cache.contains(entity7.nameIdentifier(), 
entity7.type()));
+    cache.put(entity_m1c1s1);
+    cache.put(entity_m1c1s1t1);
+    cache.put(entity_m2c2s2);
+
+    Assertions.assertTrue(cache.contains(entity_m1c1s1.nameIdentifier(), 
entity_m1c1s1.type()));
+    Assertions.assertTrue(cache.contains(entity_m2c2s2.nameIdentifier(), 
entity_m2c2s2.type()));
+    Assertions.assertTrue(cache.contains(entity_m1c1s1t1.nameIdentifier(), 
entity_m1c1s1t1.type()));
+    Assertions.assertFalse(
+        cache.contains(entity_m1c2s1t2.nameIdentifier(), 
entity_m1c2s1t2.type()));
+    Assertions.assertFalse(
+        cache.contains(entity_m1c1s2t3.nameIdentifier(), 
entity_m1c1s2t3.type()));
+    Assertions.assertFalse(cache.contains(entity_m1c1.nameIdentifier(), 
entity_m1c1.type()));
+    Assertions.assertFalse(cache.contains(entity_m1.nameIdentifier(), 
entity_m1.type()));
   }
 
   @Test
   void testSize() {
     EntityCache cache = getNormalCache();
 
-    cache.put(entity1);
-    cache.put(entity2);
-    cache.put(entity3);
+    cache.put(entity_m1c1s1);
+    cache.put(entity_m1c1s1t1);
+    cache.put(entity_m2c2s2);
 
     Assertions.assertEquals(3, cache.size());
   }
@@ -352,23 +461,23 @@ public class TestCaffeineEntityCache {
     EntityCache cache = getNormalCache();
     Assertions.assertDoesNotThrow(cache::clear);
 
-    cache.put(entity1);
-    cache.put(entity2);
-    cache.put(entity3);
-    cache.put(entity4);
-    cache.put(entity5);
-    cache.put(entity6);
-    cache.put(entity7);
+    cache.put(entity_m1);
+    cache.put(entity_m1c1);
+    cache.put(entity_m1c1s1);
+    cache.put(entity_m1c1s1t1);
+    cache.put(entity_m1c2s1t2);
+    cache.put(entity_m1c1s2t3);
+    cache.put(entity_m2c2s2);
     cache.put(
-        entity12.nameIdentifier(),
+        entity_m1r1.nameIdentifier(),
         Entity.EntityType.ROLE,
         SupportsRelationOperations.Type.ROLE_USER_REL,
-        ImmutableList.of(entity8, entity9));
+        ImmutableList.of(entity_m1u1, entity_m1u2));
     cache.put(
-        entity13.nameIdentifier(),
+        entity_m2r2.nameIdentifier(),
         Entity.EntityType.ROLE,
         SupportsRelationOperations.Type.ROLE_GROUP_REL,
-        ImmutableList.of(entity10, entity11));
+        ImmutableList.of(entity_m2g1, entity_m2g2));
 
     Assertions.assertEquals(9, cache.size());
 
@@ -376,32 +485,32 @@ public class TestCaffeineEntityCache {
 
     Assertions.assertEquals(0, cache.size());
     Assertions.assertFalse(
-        cache.getIfPresent(entity1.nameIdentifier(), 
entity1.type()).isPresent());
+        cache.getIfPresent(entity_m1c1s1.nameIdentifier(), 
entity_m1c1s1.type()).isPresent());
     Assertions.assertFalse(
-        cache.getIfPresent(entity2.nameIdentifier(), 
entity2.type()).isPresent());
+        cache.getIfPresent(entity_m2c2s2.nameIdentifier(), 
entity_m2c2s2.type()).isPresent());
     Assertions.assertFalse(
-        cache.getIfPresent(entity3.nameIdentifier(), 
entity3.type()).isPresent());
+        cache.getIfPresent(entity_m1c1s1t1.nameIdentifier(), 
entity_m1c1s1t1.type()).isPresent());
     Assertions.assertFalse(
-        cache.getIfPresent(entity4.nameIdentifier(), 
entity4.type()).isPresent());
+        cache.getIfPresent(entity_m1c2s1t2.nameIdentifier(), 
entity_m1c2s1t2.type()).isPresent());
     Assertions.assertFalse(
-        cache.getIfPresent(entity5.nameIdentifier(), 
entity5.type()).isPresent());
+        cache.getIfPresent(entity_m1c1s2t3.nameIdentifier(), 
entity_m1c1s2t3.type()).isPresent());
     Assertions.assertFalse(
-        cache.getIfPresent(entity6.nameIdentifier(), 
entity6.type()).isPresent());
+        cache.getIfPresent(entity_m1c1.nameIdentifier(), 
entity_m1c1.type()).isPresent());
     Assertions.assertFalse(
-        cache.getIfPresent(entity7.nameIdentifier(), 
entity7.type()).isPresent());
+        cache.getIfPresent(entity_m1.nameIdentifier(), 
entity_m1.type()).isPresent());
     Assertions.assertFalse(
         cache
             .getIfPresent(
                 SupportsRelationOperations.Type.ROLE_USER_REL,
-                entity12.nameIdentifier(),
-                entity12.type())
+                entity_m1r1.nameIdentifier(),
+                entity_m1r1.type())
             .isPresent());
     Assertions.assertFalse(
         cache
             .getIfPresent(
                 SupportsRelationOperations.Type.ROLE_GROUP_REL,
-                entity13.nameIdentifier(),
-                entity13.type())
+                entity_m2r2.nameIdentifier(),
+                entity_m2r2.type())
             .isPresent());
   }
 
@@ -409,158 +518,177 @@ public class TestCaffeineEntityCache {
   void testInvalidateMetalake() {
     EntityCache cache = getNormalCache();
 
-    cache.put(entity1);
-    cache.put(entity2);
-    cache.put(entity3);
-    cache.put(entity4);
-    cache.put(entity5);
-    cache.put(entity6);
-    cache.put(entity7);
-    cache.put(entity8);
-    cache.put(entity9);
-    cache.put(entity10);
-    cache.put(entity11);
+    cache.put(entity_m1);
+    cache.put(entity_m1c1);
+    cache.put(entity_m1c1s1);
+    cache.put(entity_m1c1s1t1);
+    cache.put(entity_m1c1s2t3);
+    cache.put(entity_m1c2s1t2);
+    cache.put(entity_m2c2s2);
+    cache.put(entity_m2g1);
+    cache.put(entity_m2g2);
+    cache.put(entity_m1u1);
+    cache.put(entity_m1u2);
 
     cache.put(
-        entity12.nameIdentifier(),
+        entity_m1r1.nameIdentifier(),
         Entity.EntityType.ROLE,
         SupportsRelationOperations.Type.ROLE_USER_REL,
-        ImmutableList.of(entity8, entity9));
+        ImmutableList.of(entity_m1u1, entity_m1u2));
     cache.put(
-        entity13.nameIdentifier(),
+        entity_m2r2.nameIdentifier(),
         Entity.EntityType.ROLE,
         SupportsRelationOperations.Type.ROLE_GROUP_REL,
-        ImmutableList.of(entity10, entity11));
+        ImmutableList.of(entity_m2g1, entity_m2g2));
 
     Assertions.assertEquals(13, cache.size());
 
-    cache.invalidate(entity7.nameIdentifier(), entity7.type());
+    cache.invalidate(entity_m1.nameIdentifier(), entity_m1.type());
 
     Assertions.assertEquals(4, cache.size());
-    Assertions.assertTrue(cache.contains(entity10.nameIdentifier(), 
entity10.type()));
-    Assertions.assertTrue(cache.contains(entity11.nameIdentifier(), 
entity11.type()));
+    Assertions.assertTrue(cache.contains(entity_m2g1.nameIdentifier(), 
entity_m2g1.type()));
+    Assertions.assertTrue(cache.contains(entity_m2g2.nameIdentifier(), 
entity_m2g2.type()));
     Assertions.assertTrue(
         cache.contains(
-            entity13.nameIdentifier(),
-            entity13.type(),
+            entity_m2r2.nameIdentifier(),
+            entity_m2r2.type(),
             SupportsRelationOperations.Type.ROLE_GROUP_REL));
-    Assertions.assertTrue(cache.getIfPresent(entity2.nameIdentifier(), 
entity2.type()).isPresent());
-
-    Assertions.assertFalse(cache.contains(entity1.nameIdentifier(), 
entity1.type()));
-    Assertions.assertFalse(cache.contains(entity3.nameIdentifier(), 
entity3.type()));
-    Assertions.assertFalse(cache.contains(entity4.nameIdentifier(), 
entity4.type()));
-    Assertions.assertFalse(cache.contains(entity5.nameIdentifier(), 
entity5.type()));
-    Assertions.assertFalse(cache.contains(entity6.nameIdentifier(), 
entity6.type()));
-    Assertions.assertFalse(cache.contains(entity7.nameIdentifier(), 
entity7.type()));
+    Assertions.assertTrue(
+        cache.getIfPresent(entity_m2c2s2.nameIdentifier(), 
entity_m2c2s2.type()).isPresent());
+
+    Assertions.assertFalse(cache.contains(entity_m1c1s1.nameIdentifier(), 
entity_m1c1s1.type()));
+    Assertions.assertFalse(
+        cache.contains(entity_m1c1s1t1.nameIdentifier(), 
entity_m1c1s1t1.type()));
+    Assertions.assertFalse(
+        cache.contains(entity_m1c2s1t2.nameIdentifier(), 
entity_m1c2s1t2.type()));
+    Assertions.assertFalse(
+        cache.contains(entity_m1c1s2t3.nameIdentifier(), 
entity_m1c1s2t3.type()));
+    Assertions.assertFalse(cache.contains(entity_m1c1.nameIdentifier(), 
entity_m1c1.type()));
+    Assertions.assertFalse(cache.contains(entity_m1.nameIdentifier(), 
entity_m1.type()));
   }
 
   @Test
   void testInvalidateCatalog() {
     EntityCache cache = getNormalCache();
 
-    cache.put(entity1);
-    cache.put(entity2);
-    cache.put(entity3);
-    cache.put(entity4);
-    cache.put(entity5);
-    cache.put(entity6);
-    cache.put(entity7);
+    cache.put(entity_m1);
+    cache.put(entity_m1c1);
+    cache.put(entity_m1c1s1);
+    cache.put(entity_m1c1s1t1);
+    cache.put(entity_m1c1s2t3);
+    cache.put(entity_m1c2s1t2);
+    cache.put(entity_m2c2s2);
 
     Assertions.assertEquals(7, cache.size());
-    Assertions.assertTrue(cache.contains(entity1.nameIdentifier(), 
entity1.type()));
-    Assertions.assertTrue(cache.contains(entity2.nameIdentifier(), 
entity2.type()));
-    Assertions.assertTrue(cache.contains(entity3.nameIdentifier(), 
entity3.type()));
-    Assertions.assertTrue(cache.contains(entity4.nameIdentifier(), 
entity4.type()));
-    Assertions.assertTrue(cache.contains(entity5.nameIdentifier(), 
entity5.type()));
-    Assertions.assertTrue(cache.contains(entity6.nameIdentifier(), 
entity6.type()));
-    Assertions.assertTrue(cache.contains(entity7.nameIdentifier(), 
entity7.type()));
-
-    cache.invalidate(entity6.nameIdentifier(), entity6.type());
+    Assertions.assertTrue(cache.contains(entity_m1c1s1.nameIdentifier(), 
entity_m1c1s1.type()));
+    Assertions.assertTrue(cache.contains(entity_m2c2s2.nameIdentifier(), 
entity_m2c2s2.type()));
+    Assertions.assertTrue(cache.contains(entity_m1c1s1t1.nameIdentifier(), 
entity_m1c1s1t1.type()));
+    Assertions.assertTrue(cache.contains(entity_m1c2s1t2.nameIdentifier(), 
entity_m1c2s1t2.type()));
+    Assertions.assertTrue(cache.contains(entity_m1c1s2t3.nameIdentifier(), 
entity_m1c1s2t3.type()));
+    Assertions.assertTrue(cache.contains(entity_m1c1.nameIdentifier(), 
entity_m1c1.type()));
+    Assertions.assertTrue(cache.contains(entity_m1.nameIdentifier(), 
entity_m1.type()));
+
+    cache.invalidate(entity_m1c1.nameIdentifier(), entity_m1c1.type());
     Assertions.assertEquals(3, cache.size());
 
-    Assertions.assertTrue(cache.getIfPresent(entity7.nameIdentifier(), 
entity7.type()).isPresent());
-    Assertions.assertTrue(cache.getIfPresent(entity4.nameIdentifier(), 
entity4.type()).isPresent());
-    Assertions.assertTrue(cache.getIfPresent(entity2.nameIdentifier(), 
entity2.type()).isPresent());
+    Assertions.assertTrue(
+        cache.getIfPresent(entity_m1.nameIdentifier(), 
entity_m1.type()).isPresent());
+    Assertions.assertTrue(
+        cache.getIfPresent(entity_m1c2s1t2.nameIdentifier(), 
entity_m1c2s1t2.type()).isPresent());
+    Assertions.assertTrue(
+        cache.getIfPresent(entity_m2c2s2.nameIdentifier(), 
entity_m2c2s2.type()).isPresent());
 
     Assertions.assertFalse(
-        cache.getIfPresent(entity1.nameIdentifier(), 
entity1.type()).isPresent());
+        cache.getIfPresent(entity_m1c1s1.nameIdentifier(), 
entity_m1c1s1.type()).isPresent());
     Assertions.assertFalse(
-        cache.getIfPresent(entity3.nameIdentifier(), 
entity3.type()).isPresent());
+        cache.getIfPresent(entity_m1c1s1t1.nameIdentifier(), 
entity_m1c1s1t1.type()).isPresent());
     Assertions.assertFalse(
-        cache.getIfPresent(entity5.nameIdentifier(), 
entity5.type()).isPresent());
+        cache.getIfPresent(entity_m1c1s2t3.nameIdentifier(), 
entity_m1c1s2t3.type()).isPresent());
     Assertions.assertFalse(
-        cache.getIfPresent(entity6.nameIdentifier(), 
entity6.type()).isPresent());
+        cache.getIfPresent(entity_m1c1.nameIdentifier(), 
entity_m1c1.type()).isPresent());
   }
 
   @Test
   void testInvalidateSchema() {
     EntityCache cache = getNormalCache();
 
-    cache.put(entity1);
-    cache.put(entity2);
-    cache.put(entity3);
-    cache.put(entity4);
-    cache.put(entity5);
-    cache.put(entity6);
-    cache.put(entity7);
+    cache.put(entity_m1);
+    cache.put(entity_m1c1);
+    cache.put(entity_m1c1s1);
+    cache.put(entity_m1c1s1t1);
+    cache.put(entity_m1c1s2t3);
+    cache.put(entity_m1c2s1t2);
+    cache.put(entity_m2c2s2);
 
     Assertions.assertEquals(7, cache.size());
-    Assertions.assertTrue(cache.contains(entity1.nameIdentifier(), 
entity1.type()));
-    Assertions.assertTrue(cache.contains(entity2.nameIdentifier(), 
entity2.type()));
-    Assertions.assertTrue(cache.contains(entity3.nameIdentifier(), 
entity3.type()));
-    Assertions.assertTrue(cache.contains(entity4.nameIdentifier(), 
entity4.type()));
-    Assertions.assertTrue(cache.contains(entity5.nameIdentifier(), 
entity5.type()));
-    Assertions.assertTrue(cache.contains(entity6.nameIdentifier(), 
entity6.type()));
-    Assertions.assertTrue(cache.contains(entity7.nameIdentifier(), 
entity7.type()));
+    Assertions.assertTrue(cache.contains(entity_m1c1s1.nameIdentifier(), 
entity_m1c1s1.type()));
+    Assertions.assertTrue(cache.contains(entity_m2c2s2.nameIdentifier(), 
entity_m2c2s2.type()));
+    Assertions.assertTrue(cache.contains(entity_m1c1s1t1.nameIdentifier(), 
entity_m1c1s1t1.type()));
+    Assertions.assertTrue(cache.contains(entity_m1c2s1t2.nameIdentifier(), 
entity_m1c2s1t2.type()));
+    Assertions.assertTrue(cache.contains(entity_m1c1s2t3.nameIdentifier(), 
entity_m1c1s2t3.type()));
+    Assertions.assertTrue(cache.contains(entity_m1c1.nameIdentifier(), 
entity_m1c1.type()));
+    Assertions.assertTrue(cache.contains(entity_m1.nameIdentifier(), 
entity_m1.type()));
 
-    cache.invalidate(entity1.nameIdentifier(), entity1.type());
+    cache.invalidate(entity_m1c1s1.nameIdentifier(), entity_m1c1s1.type());
 
     Assertions.assertEquals(5, cache.size());
 
-    Assertions.assertTrue(cache.getIfPresent(entity2.nameIdentifier(), 
entity2.type()).isPresent());
-    Assertions.assertTrue(cache.getIfPresent(entity4.nameIdentifier(), 
entity4.type()).isPresent());
-    Assertions.assertTrue(cache.getIfPresent(entity5.nameIdentifier(), 
entity5.type()).isPresent());
-    Assertions.assertTrue(cache.getIfPresent(entity6.nameIdentifier(), 
entity6.type()).isPresent());
-    Assertions.assertTrue(cache.getIfPresent(entity7.nameIdentifier(), 
entity7.type()).isPresent());
+    Assertions.assertTrue(
+        cache.getIfPresent(entity_m2c2s2.nameIdentifier(), 
entity_m2c2s2.type()).isPresent());
+    Assertions.assertTrue(
+        cache.getIfPresent(entity_m1c2s1t2.nameIdentifier(), 
entity_m1c2s1t2.type()).isPresent());
+    Assertions.assertTrue(
+        cache.getIfPresent(entity_m1c1s2t3.nameIdentifier(), 
entity_m1c1s2t3.type()).isPresent());
+    Assertions.assertTrue(
+        cache.getIfPresent(entity_m1c1.nameIdentifier(), 
entity_m1c1.type()).isPresent());
+    Assertions.assertTrue(
+        cache.getIfPresent(entity_m1.nameIdentifier(), 
entity_m1.type()).isPresent());
 
     Assertions.assertFalse(
-        cache.getIfPresent(entity1.nameIdentifier(), 
entity1.type()).isPresent());
+        cache.getIfPresent(entity_m1c1s1.nameIdentifier(), 
entity_m1c1s1.type()).isPresent());
     Assertions.assertFalse(
-        cache.getIfPresent(entity3.nameIdentifier(), 
entity3.type()).isPresent());
+        cache.getIfPresent(entity_m1c1s1t1.nameIdentifier(), 
entity_m1c1s1t1.type()).isPresent());
   }
 
   @Test
   void testInvalidateTable() {
     EntityCache cache = getNormalCache();
 
-    cache.put(entity1);
-    cache.put(entity2);
-    cache.put(entity3);
-    cache.put(entity4);
-    cache.put(entity5);
-    cache.put(entity6);
-    cache.put(entity7);
+    cache.put(entity_m1);
+    cache.put(entity_m1c1);
+    cache.put(entity_m1c1s1);
+    cache.put(entity_m1c1s1t1);
+    cache.put(entity_m1c2s1t2);
+    cache.put(entity_m1c1s2t3);
+    cache.put(entity_m2c2s2);
 
     Assertions.assertEquals(7, cache.size());
-    Assertions.assertTrue(cache.contains(entity1.nameIdentifier(), 
entity1.type()));
-    Assertions.assertTrue(cache.contains(entity2.nameIdentifier(), 
entity2.type()));
-    Assertions.assertTrue(cache.contains(entity3.nameIdentifier(), 
entity3.type()));
-    Assertions.assertTrue(cache.contains(entity4.nameIdentifier(), 
entity4.type()));
-    Assertions.assertTrue(cache.contains(entity5.nameIdentifier(), 
entity5.type()));
-    Assertions.assertTrue(cache.contains(entity6.nameIdentifier(), 
entity6.type()));
-    Assertions.assertTrue(cache.contains(entity7.nameIdentifier(), 
entity7.type()));
+    Assertions.assertTrue(cache.contains(entity_m1c1s1.nameIdentifier(), 
entity_m1c1s1.type()));
+    Assertions.assertTrue(cache.contains(entity_m2c2s2.nameIdentifier(), 
entity_m2c2s2.type()));
+    Assertions.assertTrue(cache.contains(entity_m1c1s1t1.nameIdentifier(), 
entity_m1c1s1t1.type()));
+    Assertions.assertTrue(cache.contains(entity_m1c2s1t2.nameIdentifier(), 
entity_m1c2s1t2.type()));
+    Assertions.assertTrue(cache.contains(entity_m1c1s2t3.nameIdentifier(), 
entity_m1c1s2t3.type()));
+    Assertions.assertTrue(cache.contains(entity_m1c1.nameIdentifier(), 
entity_m1c1.type()));
+    Assertions.assertTrue(cache.contains(entity_m1.nameIdentifier(), 
entity_m1.type()));
 
-    cache.invalidate(entity3.nameIdentifier(), entity3.type());
+    cache.invalidate(entity_m1c1s1t1.nameIdentifier(), entity_m1c1s1t1.type());
 
     Assertions.assertEquals(6, cache.size());
-    Assertions.assertTrue(cache.getIfPresent(entity1.nameIdentifier(), 
entity1.type()).isPresent());
-    Assertions.assertTrue(cache.getIfPresent(entity2.nameIdentifier(), 
entity2.type()).isPresent());
-    Assertions.assertTrue(cache.getIfPresent(entity4.nameIdentifier(), 
entity4.type()).isPresent());
-    Assertions.assertTrue(cache.getIfPresent(entity5.nameIdentifier(), 
entity5.type()).isPresent());
-    Assertions.assertTrue(cache.getIfPresent(entity6.nameIdentifier(), 
entity6.type()).isPresent());
-    Assertions.assertTrue(cache.getIfPresent(entity7.nameIdentifier(), 
entity7.type()).isPresent());
-
-    Assertions.assertFalse(cache.contains(entity3.nameIdentifier(), 
entity3.type()));
+    Assertions.assertTrue(
+        cache.getIfPresent(entity_m1c1s1.nameIdentifier(), 
entity_m1c1s1.type()).isPresent());
+    Assertions.assertTrue(
+        cache.getIfPresent(entity_m2c2s2.nameIdentifier(), 
entity_m2c2s2.type()).isPresent());
+    Assertions.assertTrue(
+        cache.getIfPresent(entity_m1c2s1t2.nameIdentifier(), 
entity_m1c2s1t2.type()).isPresent());
+    Assertions.assertTrue(
+        cache.getIfPresent(entity_m1c1s2t3.nameIdentifier(), 
entity_m1c1s2t3.type()).isPresent());
+    Assertions.assertTrue(
+        cache.getIfPresent(entity_m1c1.nameIdentifier(), 
entity_m1c1.type()).isPresent());
+    Assertions.assertTrue(
+        cache.getIfPresent(entity_m1.nameIdentifier(), 
entity_m1.type()).isPresent());
+
+    Assertions.assertFalse(
+        cache.contains(entity_m1c1s1t1.nameIdentifier(), 
entity_m1c1s1t1.type()));
   }
 
   @Test
@@ -769,16 +897,18 @@ public class TestCaffeineEntityCache {
   void testRemoveNonExistentEntity() {
     EntityCache cache = getNormalCache();
 
-    cache.put(entity1);
+    cache.put(entity_m1c1s1);
 
     Assertions.assertEquals(1, cache.size());
-    Assertions.assertTrue(cache.contains(entity1.nameIdentifier(), 
entity1.type()));
+    Assertions.assertTrue(cache.contains(entity_m1c1s1.nameIdentifier(), 
entity_m1c1s1.type()));
 
-    Assertions.assertDoesNotThrow(() -> 
cache.invalidate(entity2.nameIdentifier(), entity2.type()));
-    Assertions.assertFalse(cache.invalidate(entity2.nameIdentifier(), 
entity2.type()));
+    Assertions.assertDoesNotThrow(
+        () -> cache.invalidate(entity_m2c2s2.nameIdentifier(), 
entity_m2c2s2.type()));
+    Assertions.assertFalse(cache.invalidate(entity_m2c2s2.nameIdentifier(), 
entity_m2c2s2.type()));
 
-    Assertions.assertDoesNotThrow(() -> 
cache.invalidate(entity7.nameIdentifier(), entity7.type()));
-    Assertions.assertFalse(cache.invalidate(entity7.nameIdentifier(), 
entity7.type()));
+    Assertions.assertDoesNotThrow(
+        () -> cache.invalidate(entity_m1.nameIdentifier(), entity_m1.type()));
+    Assertions.assertFalse(cache.invalidate(entity_m1.nameIdentifier(), 
entity_m1.type()));
   }
 
   @Test
@@ -791,22 +921,23 @@ public class TestCaffeineEntityCache {
     config.set(Configs.CACHE_WEIGHER_ENABLED, false);
 
     EntityCache cache = new CaffeineEntityCache(config);
-    cache.put(entity1);
+    cache.put(entity_m1c1s1);
 
     await()
         .atMost(3_000, MILLISECONDS)
         .pollInterval(100, MILLISECONDS)
         .until(
             () -> {
-              cache.put(entity2);
-              Cache<EntityCacheKey, List<Entity>> internalCache =
-                  (Cache<EntityCacheKey, List<Entity>>) 
getCacheDataFrom(cache);
+              cache.put(entity_m2c2s2);
+              Cache<EntityCacheRelationKey, List<Entity>> internalCache =
+                  (Cache<EntityCacheRelationKey, List<Entity>>) 
getCacheDataFrom(cache);
               internalCache.cleanUp();
-              return !cache.contains(entity1.nameIdentifier(), 
Entity.EntityType.SCHEMA);
+              return !cache.contains(entity_m1c1s1.nameIdentifier(), 
Entity.EntityType.SCHEMA);
             });
 
-    Assertions.assertFalse(cache.contains(entity1.nameIdentifier(), 
Entity.EntityType.SCHEMA));
-    Assertions.assertTrue(cache.contains(entity2.nameIdentifier(), 
Entity.EntityType.SCHEMA));
+    Assertions.assertFalse(
+        cache.contains(entity_m1c1s1.nameIdentifier(), 
Entity.EntityType.SCHEMA));
+    Assertions.assertTrue(cache.contains(entity_m2c2s2.nameIdentifier(), 
Entity.EntityType.SCHEMA));
   }
 
   @Test
@@ -819,10 +950,10 @@ public class TestCaffeineEntityCache {
       mockedStatic.when(EntityCacheWeigher::getInstance).thenReturn(new 
EntityCacheWeigher());
 
       EntityCache cache = new CaffeineEntityCache(config);
-      cache.put(entity7);
+      cache.put(entity_m1);
 
-      Cache<EntityCacheKey, List<Entity>> caffeineObject =
-          (Cache<EntityCacheKey, List<Entity>>) getCacheDataFrom(cache);
+      Cache<EntityCacheRelationKey, List<Entity>> caffeineObject =
+          (Cache<EntityCacheRelationKey, List<Entity>>) 
getCacheDataFrom(cache);
 
       await()
           .atMost(1, TimeUnit.SECONDS)
@@ -830,11 +961,12 @@ public class TestCaffeineEntityCache {
           .until(
               () -> {
                 caffeineObject.cleanUp();
-                return !cache.contains(entity7.nameIdentifier(), 
Entity.EntityType.METALAKE);
+                return !cache.contains(entity_m1.nameIdentifier(), 
Entity.EntityType.METALAKE);
               });
 
       Assertions.assertEquals(0, cache.size());
-      Assertions.assertFalse(cache.contains(entity7.nameIdentifier(), 
Entity.EntityType.METALAKE));
+      Assertions.assertFalse(
+          cache.contains(entity_m1.nameIdentifier(), 
Entity.EntityType.METALAKE));
     }
   }
 
@@ -851,22 +983,22 @@ public class TestCaffeineEntityCache {
       config.set(Configs.CACHE_WEIGHER_ENABLED, true);
 
       EntityCache cache = new CaffeineEntityCache(config);
-      cache.put(entity7);
+      cache.put(entity_m1);
       Assertions.assertEquals(1, cache.size());
-      Assertions.assertTrue(cache.contains(entity7.nameIdentifier(), 
entity7.type()));
+      Assertions.assertTrue(cache.contains(entity_m1.nameIdentifier(), 
entity_m1.type()));
 
-      cache.put(entity1);
-      cache.put(entity2);
-      cache.getIfPresent(entity1.nameIdentifier(), entity1.type());
-      cache.getIfPresent(entity2.nameIdentifier(), entity2.type());
+      cache.put(entity_m1c1s1);
+      cache.put(entity_m2c2s2);
+      cache.getIfPresent(entity_m1c1s1.nameIdentifier(), entity_m1c1s1.type());
+      cache.getIfPresent(entity_m2c2s2.nameIdentifier(), entity_m2c2s2.type());
 
-      Cache<EntityCacheKey, List<Entity>> caffeineObject =
-          (Cache<EntityCacheKey, List<Entity>>) getCacheDataFrom(cache);
+      Cache<EntityCacheRelationKey, List<Entity>> caffeineObject =
+          (Cache<EntityCacheRelationKey, List<Entity>>) 
getCacheDataFrom(cache);
       caffeineObject.cleanUp();
       await()
           .atMost(1500, MILLISECONDS)
           .pollInterval(50, MILLISECONDS)
-          .until(() -> !cache.contains(entity7.nameIdentifier(), 
entity7.type()));
+          .until(() -> !cache.contains(entity_m1.nameIdentifier(), 
entity_m1.type()));
     }
   }
 
@@ -878,28 +1010,28 @@ public class TestCaffeineEntityCache {
     config.set(Configs.CACHE_MAX_ENTRIES, 1);
     EntityCache cache = new CaffeineEntityCache(config);
 
-    Cache<EntityCacheKey, List<Entity>> caffeineObject =
-        (Cache<EntityCacheKey, List<Entity>>) getCacheDataFrom(cache);
+    Cache<EntityCacheRelationKey, List<Entity>> caffeineObject =
+        (Cache<EntityCacheRelationKey, List<Entity>>) getCacheDataFrom(cache);
 
-    cache.put(entity1);
+    cache.put(entity_m1c1s1);
     caffeineObject.cleanUp();
     await()
         .atMost(500, MILLISECONDS)
-        .until(() -> cache.contains(entity1.nameIdentifier(), 
Entity.EntityType.SCHEMA));
+        .until(() -> cache.contains(entity_m1c1s1.nameIdentifier(), 
Entity.EntityType.SCHEMA));
     Assertions.assertEquals(1, cache.size());
 
-    cache.put(entity2);
+    cache.put(entity_m2c2s2);
     caffeineObject.cleanUp();
     await()
         .atMost(500, MILLISECONDS)
-        .until(() -> cache.contains(entity2.nameIdentifier(), entity2.type()));
+        .until(() -> cache.contains(entity_m2c2s2.nameIdentifier(), 
entity_m2c2s2.type()));
     Assertions.assertEquals(1, cache.size());
 
-    cache.put(entity3);
+    cache.put(entity_m1c1s1t1);
     caffeineObject.cleanUp();
     await()
         .atMost(500, MILLISECONDS)
-        .until(() -> cache.contains(entity3.nameIdentifier(), entity3.type()));
+        .until(() -> cache.contains(entity_m1c1s1t1.nameIdentifier(), 
entity_m1c1s1t1.type()));
     Assertions.assertEquals(1, cache.size());
   }
 
@@ -908,39 +1040,39 @@ public class TestCaffeineEntityCache {
     int metalakeWeight =
         EntityCacheWeigher.getInstance()
             .weigh(
-                EntityCacheKey.of(entity7.nameIdentifier(), entity7.type()),
-                ImmutableList.of(entity7));
+                EntityCacheRelationKey.of(entity_m1.nameIdentifier(), 
entity_m1.type()),
+                ImmutableList.of(entity_m1));
     Assertions.assertEquals(100, metalakeWeight);
 
     int catalogWeight =
         EntityCacheWeigher.getInstance()
             .weigh(
-                EntityCacheKey.of(entity6.nameIdentifier(), entity6.type()),
-                ImmutableList.of(entity6));
+                EntityCacheRelationKey.of(entity_m1c1.nameIdentifier(), 
entity_m1c1.type()),
+                ImmutableList.of(entity_m1c1));
     Assertions.assertEquals(75, catalogWeight);
 
     int schemaWeight =
         EntityCacheWeigher.getInstance()
             .weigh(
-                EntityCacheKey.of(entity1.nameIdentifier(), entity1.type()),
-                ImmutableList.of(entity1));
+                EntityCacheRelationKey.of(entity_m1c1s1.nameIdentifier(), 
entity_m1c1s1.type()),
+                ImmutableList.of(entity_m1c1s1));
     Assertions.assertEquals(50, schemaWeight);
 
     int tableWeight =
         EntityCacheWeigher.getInstance()
             .weigh(
-                EntityCacheKey.of(entity3.nameIdentifier(), entity3.type()),
-                ImmutableList.of(entity3));
+                EntityCacheRelationKey.of(entity_m1c1s1t1.nameIdentifier(), 
entity_m1c1s1t1.type()),
+                ImmutableList.of(entity_m1c1s1t1));
     Assertions.assertEquals(15, tableWeight);
 
     int multiUserWeight =
         EntityCacheWeigher.getInstance()
             .weigh(
-                EntityCacheKey.of(
-                    entity12.nameIdentifier(),
-                    entity12.type(),
+                EntityCacheRelationKey.of(
+                    entity_m1r1.nameIdentifier(),
+                    entity_m1r1.type(),
                     SupportsRelationOperations.Type.ROLE_USER_REL),
-                ImmutableList.of(entity8, entity9));
+                ImmutableList.of(entity_m1u1, entity_m1u2));
 
     Assertions.assertEquals(30, multiUserWeight);
   }
@@ -948,16 +1080,17 @@ public class TestCaffeineEntityCache {
   @Test
   void testGetIfPresentWithNull() {
     EntityCache cache = getNormalCache();
-    cache.put(entity1);
+    cache.put(entity_m1c1s1);
 
     Assertions.assertThrows(
         IllegalArgumentException.class, () -> cache.getIfPresent(null, 
Entity.EntityType.SCHEMA));
     Assertions.assertThrows(
-        IllegalArgumentException.class, () -> 
cache.getIfPresent(entity1.nameIdentifier(), null));
+        IllegalArgumentException.class,
+        () -> cache.getIfPresent(entity_m1c1s1.nameIdentifier(), null));
 
     Assertions.assertThrows(
         IllegalArgumentException.class,
-        () -> cache.getIfPresent(null, entity12.nameIdentifier(), 
entity12.type()));
+        () -> cache.getIfPresent(null, entity_m1r1.nameIdentifier(), 
entity_m1r1.type()));
     Assertions.assertThrows(
         IllegalArgumentException.class,
         () ->
@@ -967,12 +1100,12 @@ public class TestCaffeineEntityCache {
         IllegalArgumentException.class,
         () ->
             cache.getIfPresent(
-                SupportsRelationOperations.Type.ROLE_USER_REL, 
entity12.nameIdentifier(), null));
+                SupportsRelationOperations.Type.ROLE_USER_REL, 
entity_m1r1.nameIdentifier(), null));
     Assertions.assertThrows(
         IllegalArgumentException.class,
         () ->
             cache.getIfPresent(
-                SupportsRelationOperations.Type.ROLE_USER_REL, 
entity12.nameIdentifier(), null));
+                SupportsRelationOperations.Type.ROLE_USER_REL, 
entity_m1r1.nameIdentifier(), null));
   }
 
   @Test
@@ -982,7 +1115,7 @@ public class TestCaffeineEntityCache {
     Assertions.assertThrows(
         IllegalArgumentException.class, () -> cache.contains(null, 
Entity.EntityType.SCHEMA));
     Assertions.assertThrows(
-        IllegalArgumentException.class, () -> 
cache.contains(entity7.nameIdentifier(), null));
+        IllegalArgumentException.class, () -> 
cache.contains(entity_m1.nameIdentifier(), null));
 
     Assertions.assertThrows(
         IllegalArgumentException.class,
@@ -993,10 +1126,10 @@ public class TestCaffeineEntityCache {
         IllegalArgumentException.class,
         () ->
             cache.contains(
-                entity12.nameIdentifier(), null, 
SupportsRelationOperations.Type.ROLE_USER_REL));
+                entity_m1r1.nameIdentifier(), null, 
SupportsRelationOperations.Type.ROLE_USER_REL));
     Assertions.assertThrows(
         IllegalArgumentException.class,
-        () -> cache.contains(entity12.nameIdentifier(), entity12.type(), 
null));
+        () -> cache.contains(entity_m1r1.nameIdentifier(), entity_m1r1.type(), 
null));
   }
 
   @Test
@@ -1006,7 +1139,7 @@ public class TestCaffeineEntityCache {
     Assertions.assertThrows(
         IllegalArgumentException.class, () -> cache.invalidate(null, 
Entity.EntityType.CATALOG));
     Assertions.assertThrows(
-        IllegalArgumentException.class, () -> 
cache.invalidate(entity7.nameIdentifier(), null));
+        IllegalArgumentException.class, () -> 
cache.invalidate(entity_m1.nameIdentifier(), null));
 
     Assertions.assertThrows(
         IllegalArgumentException.class,
@@ -1017,10 +1150,10 @@ public class TestCaffeineEntityCache {
         IllegalArgumentException.class,
         () ->
             cache.invalidate(
-                entity12.nameIdentifier(), null, 
SupportsRelationOperations.Type.ROLE_USER_REL));
+                entity_m1r1.nameIdentifier(), null, 
SupportsRelationOperations.Type.ROLE_USER_REL));
     Assertions.assertThrows(
         IllegalArgumentException.class,
-        () -> cache.invalidate(entity12.nameIdentifier(), entity12.type(), 
null));
+        () -> cache.invalidate(entity_m1r1.nameIdentifier(), 
entity_m1r1.type(), null));
   }
 
   @Test
@@ -1041,18 +1174,19 @@ public class TestCaffeineEntityCache {
         IllegalArgumentException.class,
         () ->
             cache.put(
-                entity12.nameIdentifier(),
+                entity_m1r1.nameIdentifier(),
                 null,
                 SupportsRelationOperations.Type.ROLE_USER_REL,
                 ImmutableList.of()));
     Assertions.assertThrows(
         IllegalArgumentException.class,
-        () -> cache.put(entity12.nameIdentifier(), entity12.type(), null, 
ImmutableList.of()));
+        () ->
+            cache.put(entity_m1r1.nameIdentifier(), entity_m1r1.type(), null, 
ImmutableList.of()));
     Assertions.assertThrows(
         IllegalArgumentException.class,
         () ->
             cache.put(
-                entity12.nameIdentifier(),
+                entity_m1r1.nameIdentifier(),
                 Entity.EntityType.ROLE,
                 SupportsRelationOperations.Type.ROLE_USER_REL,
                 null));
diff --git 
a/core/src/test/java/org/apache/gravitino/cache/TestEntityCacheKey.java 
b/core/src/test/java/org/apache/gravitino/cache/TestEntityCacheKey.java
index 3624db1f6b..6fbfd08f24 100644
--- a/core/src/test/java/org/apache/gravitino/cache/TestEntityCacheKey.java
+++ b/core/src/test/java/org/apache/gravitino/cache/TestEntityCacheKey.java
@@ -29,11 +29,11 @@ import org.junit.jupiter.api.Test;
 public class TestEntityCacheKey {
 
   @Test
-  void testCreateRelationEntityCacheKeyUsingStaticMethod() {
+  void testCreateRelationEntityCacheRelationKeyUsingStaticMethod() {
     NameIdentifier ident = NameIdentifierUtil.ofRole("metalake", "role1");
     // test Relation Entity
-    EntityCacheKey key =
-        EntityCacheKey.of(
+    EntityCacheRelationKey key =
+        EntityCacheRelationKey.of(
             ident, Entity.EntityType.ROLE, 
SupportsRelationOperations.Type.ROLE_GROUP_REL);
     Assertions.assertEquals("metalake.system.role.role1:ROLE:ROLE_GROUP_REL", 
key.toString());
     Assertions.assertEquals(
@@ -42,7 +42,7 @@ public class TestEntityCacheKey {
     Assertions.assertEquals(SupportsRelationOperations.Type.ROLE_GROUP_REL, 
key.relationType());
 
     // test Store Entity
-    EntityCacheKey key2 = EntityCacheKey.of(ident, Entity.EntityType.ROLE, 
null);
+    EntityCacheRelationKey key2 = EntityCacheRelationKey.of(ident, 
Entity.EntityType.ROLE, null);
     Assertions.assertEquals("metalake.system.role.role1:ROLE", 
key2.toString());
     Assertions.assertEquals(
         NameIdentifier.of("metalake", "system", "role", "role1"), 
key2.identifier());
@@ -51,22 +51,22 @@ public class TestEntityCacheKey {
   }
 
   @Test
-  void testCreateRelationEntityCacheKeyWithNullArguments() {
+  void testCreateRelationEntityCacheRelationKeyWithNullArguments() {
     NameIdentifier ident = NameIdentifierUtil.ofRole("metalake", "role1");
     Assertions.assertThrows(
         IllegalArgumentException.class,
         () -> {
-          EntityCacheKey.of(
+          EntityCacheRelationKey.of(
               null, Entity.EntityType.ROLE, 
SupportsRelationOperations.Type.ROLE_GROUP_REL);
         });
     Assertions.assertThrows(
         IllegalArgumentException.class,
         () -> {
-          EntityCacheKey.of(ident, null, 
SupportsRelationOperations.Type.ROLE_GROUP_REL);
+          EntityCacheRelationKey.of(ident, null, 
SupportsRelationOperations.Type.ROLE_GROUP_REL);
         });
     Assertions.assertDoesNotThrow(
         () -> {
-          EntityCacheKey.of(ident, Entity.EntityType.ROLE, null);
+          EntityCacheRelationKey.of(ident, Entity.EntityType.ROLE, null);
         });
   }
 
@@ -75,8 +75,9 @@ public class TestEntityCacheKey {
     NameIdentifier ident1 = NameIdentifier.of("ns", "db", "tbl");
     Entity.EntityType type = Entity.EntityType.TABLE;
 
-    EntityCacheKey key1 = EntityCacheKey.of(ident1, type);
-    EntityCacheKey key2 = EntityCacheKey.of(NameIdentifier.of("ns", "db", 
"tbl"), type);
+    EntityCacheRelationKey key1 = EntityCacheRelationKey.of(ident1, type);
+    EntityCacheRelationKey key2 =
+        EntityCacheRelationKey.of(NameIdentifier.of("ns", "db", "tbl"), type);
 
     Assertions.assertEquals(key1, key2, "Keys with same ident and type should 
be equal");
     Assertions.assertEquals(
@@ -89,8 +90,9 @@ public class TestEntityCacheKey {
     Entity.EntityType type = Entity.EntityType.TABLE;
     SupportsRelationOperations.Type relType = 
SupportsRelationOperations.Type.OWNER_REL;
 
-    EntityCacheKey key1 = EntityCacheKey.of(ident, type, relType);
-    EntityCacheKey key2 = EntityCacheKey.of(NameIdentifier.of("ns", "db", 
"tbl"), type, relType);
+    EntityCacheRelationKey key1 = EntityCacheRelationKey.of(ident, type, 
relType);
+    EntityCacheRelationKey key2 =
+        EntityCacheRelationKey.of(NameIdentifier.of("ns", "db", "tbl"), type, 
relType);
 
     Assertions.assertEquals(
         key1, key2, "Keys with same ident, type, and relationType should be 
equal");
@@ -100,10 +102,10 @@ public class TestEntityCacheKey {
 
   @Test
   public void testInequalityWithDifferentIdentifier() {
-    EntityCacheKey key1 =
-        EntityCacheKey.of(NameIdentifier.of("ns", "db", "tbl1"), 
Entity.EntityType.TABLE);
-    EntityCacheKey key2 =
-        EntityCacheKey.of(NameIdentifier.of("ns", "db", "tbl2"), 
Entity.EntityType.TABLE);
+    EntityCacheRelationKey key1 =
+        EntityCacheRelationKey.of(NameIdentifier.of("ns", "db", "tbl1"), 
Entity.EntityType.TABLE);
+    EntityCacheRelationKey key2 =
+        EntityCacheRelationKey.of(NameIdentifier.of("ns", "db", "tbl2"), 
Entity.EntityType.TABLE);
 
     Assertions.assertNotEquals(key1, key2, "Keys with different identifiers 
should not be equal");
   }
@@ -111,8 +113,8 @@ public class TestEntityCacheKey {
   @Test
   public void testInequalityWithDifferentEntityType() {
     NameIdentifier ident = NameIdentifier.of("ns", "db", "obj");
-    EntityCacheKey key1 = EntityCacheKey.of(ident, Entity.EntityType.TABLE);
-    EntityCacheKey key2 = EntityCacheKey.of(ident, Entity.EntityType.FILESET);
+    EntityCacheRelationKey key1 = EntityCacheRelationKey.of(ident, 
Entity.EntityType.TABLE);
+    EntityCacheRelationKey key2 = EntityCacheRelationKey.of(ident, 
Entity.EntityType.FILESET);
 
     Assertions.assertNotEquals(key1, key2, "Keys with different entity types 
should not be equal");
   }
@@ -122,9 +124,10 @@ public class TestEntityCacheKey {
     NameIdentifier ident = NameIdentifier.of("ns", "db", "obj");
     Entity.EntityType type = Entity.EntityType.TABLE;
 
-    EntityCacheKey key1 = EntityCacheKey.of(ident, type, 
SupportsRelationOperations.Type.OWNER_REL);
-    EntityCacheKey key2 =
-        EntityCacheKey.of(ident, type, 
SupportsRelationOperations.Type.ROLE_USER_REL);
+    EntityCacheRelationKey key1 =
+        EntityCacheRelationKey.of(ident, type, 
SupportsRelationOperations.Type.OWNER_REL);
+    EntityCacheRelationKey key2 =
+        EntityCacheRelationKey.of(ident, type, 
SupportsRelationOperations.Type.ROLE_USER_REL);
 
     Assertions.assertNotEquals(
         key1, key2, "Keys with different relation types should not be equal");
@@ -135,7 +138,7 @@ public class TestEntityCacheKey {
     NameIdentifier ident = NameIdentifierUtil.ofUser("metalake", "user1");
     Entity.EntityType type = Entity.EntityType.USER;
 
-    EntityCacheKey key = EntityCacheKey.of(ident, type);
+    EntityCacheRelationKey key = EntityCacheRelationKey.of(ident, type);
 
     Assertions.assertEquals("metalake.system.user.user1:USER", key.toString());
   }
@@ -146,7 +149,7 @@ public class TestEntityCacheKey {
     Entity.EntityType type = Entity.EntityType.USER;
     SupportsRelationOperations.Type relationType = 
SupportsRelationOperations.Type.ROLE_USER_REL;
 
-    EntityCacheKey key = EntityCacheKey.of(ident, type, relationType);
+    EntityCacheRelationKey key = EntityCacheRelationKey.of(ident, type, 
relationType);
 
     Assertions.assertEquals("metalake.system.user.user1:USER:ROLE_USER_REL", 
key.toString());
   }
diff --git a/core/src/test/java/org/apache/gravitino/utils/TestUtil.java 
b/core/src/test/java/org/apache/gravitino/utils/TestUtil.java
index fc909dc6a1..f0e9e11c51 100644
--- a/core/src/test/java/org/apache/gravitino/utils/TestUtil.java
+++ b/core/src/test/java/org/apache/gravitino/utils/TestUtil.java
@@ -78,7 +78,7 @@ public class TestUtil {
    * @return The test {@link BaseMetalake} entity.
    */
   public static BaseMetalake getTestMetalake() {
-    return getTestMetalake(generator.nextId(), "test_metalake", "metalake 
entity test");
+    return getTestMetalake(generator.nextId(), "m1", "metalake entity test");
   }
 
   /**
@@ -107,7 +107,7 @@ public class TestUtil {
    */
   public static CatalogEntity getTestCatalogEntity() {
     return getTestCatalogEntity(
-        generator.nextId(), "test_catalog", Namespace.of("m1"), "hive", 
"catalog entity test");
+        generator.nextId(), "c2", Namespace.of("m1"), "hive", "catalog entity 
test");
   }
 
   /**

Reply via email to