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

jshao pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git


The following commit(s) were added to refs/heads/main by this push:
     new 1debca60b Revert "[#4608] feat(core): Supports to load fields lazily" 
(#4945)
1debca60b is described below

commit 1debca60ba52d6ec9dae7960cbe92903f296fa8f
Author: roryqi <[email protected]>
AuthorDate: Wed Sep 18 11:51:59 2024 +0800

    Revert "[#4608] feat(core): Supports to load fields lazily" (#4945)
    
    Reverts apache/gravitino#4690
---
 .../ranger/RangerAuthorizationPlugin.java          |   6 +-
 .../ranger/integration/test/RangerHiveIT.java      |  42 ++++---
 .../gravitino/authorization/PermissionManager.java |  82 +++++++------
 .../gravitino/authorization/UserGroupManager.java  |   4 +-
 .../org/apache/gravitino/meta/GroupEntity.java     |  58 +++++-----
 .../java/org/apache/gravitino/meta/RoleEntity.java |  41 +++----
 .../java/org/apache/gravitino/meta/UserEntity.java |  58 ++++++----
 .../apache/gravitino/proto/GroupEntitySerDe.java   |  69 +++++++++++
 .../apache/gravitino/proto/ProtoEntitySerDe.java   |  13 ++-
 .../apache/gravitino/proto/RoleEntitySerDe.java    | 115 +++++++++++++++++++
 .../apache/gravitino/proto/UserEntitySerDe.java    |  69 +++++++++++
 .../storage/kv/BinaryEntityKeyEncoder.java         |   9 ++
 .../relational/service/GroupMetaService.java       |  26 +++--
 .../relational/service/OwnerMetaService.java       |   6 +-
 .../relational/service/RoleMetaService.java        |  42 +++++--
 .../relational/service/UserMetaService.java        |  25 ++--
 .../storage/relational/utils/POConverters.java     |  63 +++++-----
 .../storage/relational/utils/SupplierUtils.java    | 114 ------------------
 .../TestAccessControlManagerForPermissions.java    |   2 +-
 .../gravitino/authorization/TestOwnerManager.java  |   6 +-
 .../java/org/apache/gravitino/meta/TestEntity.java |  98 ++--------------
 .../gravitino/proto/TestEntityProtoSerDe.java      | 113 ++++++++++++++++++
 .../gravitino/storage/TestEntityStorage.java       |   5 +-
 .../storage/memory/TestMemoryEntityStore.java      |   5 +-
 .../storage/relational/TestJDBCBackend.java        |  35 ++++--
 .../relational/service/TestGroupMetaService.java   | 126 +++++++++++---------
 .../relational/service/TestRoleMetaService.java    |  35 ++++--
 .../relational/service/TestUserMetaService.java    | 127 ++++++++++++---------
 .../server/web/rest/TestGroupOperations.java       |   2 +-
 .../server/web/rest/TestPermissionOperations.java  |  27 ++---
 .../server/web/rest/TestUserOperations.java        |   2 +-
 31 files changed, 870 insertions(+), 555 deletions(-)

diff --git 
a/authorizations/authorization-ranger/src/main/java/org/apache/gravitino/authorization/ranger/RangerAuthorizationPlugin.java
 
b/authorizations/authorization-ranger/src/main/java/org/apache/gravitino/authorization/ranger/RangerAuthorizationPlugin.java
index 03e18bef9..75692e987 100644
--- 
a/authorizations/authorization-ranger/src/main/java/org/apache/gravitino/authorization/ranger/RangerAuthorizationPlugin.java
+++ 
b/authorizations/authorization-ranger/src/main/java/org/apache/gravitino/authorization/ranger/RangerAuthorizationPlugin.java
@@ -194,7 +194,8 @@ public class RangerAuthorizationPlugin implements 
AuthorizationPlugin {
           UserEntity.builder()
               .withId(1L)
               .withName(newOwner.name())
-              .withRoles(Collections.emptyList())
+              .withRoleNames(Collections.emptyList())
+              .withRoleIds(Collections.emptyList())
               .withAuditInfo(auditInfo)
               .build();
       onUserAdded(userEntity);
@@ -203,7 +204,8 @@ public class RangerAuthorizationPlugin implements 
AuthorizationPlugin {
           GroupEntity.builder()
               .withId(1L)
               .withName(newOwner.name())
-              .withRoles(Collections.emptyList())
+              .withRoleNames(Collections.emptyList())
+              .withRoleIds(Collections.emptyList())
               .withAuditInfo(auditInfo)
               .build();
       onGroupAdded(groupEntity);
diff --git 
a/authorizations/authorization-ranger/src/test/java/org/apache/gravitino/authorization/ranger/integration/test/RangerHiveIT.java
 
b/authorizations/authorization-ranger/src/test/java/org/apache/gravitino/authorization/ranger/integration/test/RangerHiveIT.java
index 844b89b30..79f66ef28 100644
--- 
a/authorizations/authorization-ranger/src/test/java/org/apache/gravitino/authorization/ranger/integration/test/RangerHiveIT.java
+++ 
b/authorizations/authorization-ranger/src/test/java/org/apache/gravitino/authorization/ranger/integration/test/RangerHiveIT.java
@@ -483,7 +483,8 @@ public class RangerHiveIT {
         UserEntity.builder()
             .withId(1L)
             .withName(userName1)
-            .withRoles(Collections.emptyList())
+            .withRoleNames(Collections.emptyList())
+            .withRoleIds(Collections.emptyList())
             .withAuditInfo(auditInfo)
             .build();
     Assertions.assertTrue(
@@ -501,7 +502,8 @@ public class RangerHiveIT {
         UserEntity.builder()
             .withId(1L)
             .withName(userName2)
-            .withRoles(Collections.emptyList())
+            .withRoleNames(Collections.emptyList())
+            .withRoleIds(Collections.emptyList())
             .withAuditInfo(auditInfo)
             .build();
     Assertions.assertTrue(
@@ -523,7 +525,8 @@ public class RangerHiveIT {
         UserEntity.builder()
             .withId(1L)
             .withName(userName1)
-            .withRoles(Collections.emptyList())
+            .withRoleNames(Collections.emptyList())
+            .withRoleIds(Collections.emptyList())
             .withAuditInfo(auditInfo)
             .build();
     Assertions.assertTrue(
@@ -552,7 +555,8 @@ public class RangerHiveIT {
         GroupEntity.builder()
             .withId(1L)
             .withName(groupName1)
-            .withRoles(Collections.emptyList())
+            .withRoleNames(Collections.emptyList())
+            .withRoleIds(Collections.emptyList())
             .withAuditInfo(auditInfo)
             .build();
     Assertions.assertTrue(
@@ -570,7 +574,8 @@ public class RangerHiveIT {
         GroupEntity.builder()
             .withId(1L)
             .withName(groupName2)
-            .withRoles(Collections.emptyList())
+            .withRoleNames(Collections.emptyList())
+            .withRoleIds(Collections.emptyList())
             .withAuditInfo(auditInfo)
             .build();
     Assertions.assertTrue(
@@ -593,7 +598,8 @@ public class RangerHiveIT {
         GroupEntity.builder()
             .withId(1L)
             .withName(groupName1)
-            .withRoles(Collections.emptyList())
+            .withRoleNames(Collections.emptyList())
+            .withRoleIds(Collections.emptyList())
             .withAuditInfo(auditInfo)
             .build();
     Assertions.assertTrue(
@@ -674,7 +680,8 @@ public class RangerHiveIT {
             .withId(0L)
             .withName(currentFunName())
             .withAuditInfo(auditInfo)
-            .withRoles(Collections.emptyList())
+            .withRoleIds(null)
+            .withRoleNames(null)
             .build();
     Assertions.assertTrue(rangerAuthPlugin.onUserAdded(user));
     Assertions.assertTrue(rangerAuthPlugin.onUserAcquired(user));
@@ -689,7 +696,8 @@ public class RangerHiveIT {
             .withId(0L)
             .withName(currentFunName())
             .withAuditInfo(auditInfo)
-            .withRoles(Collections.emptyList())
+            .withRoleIds(null)
+            .withRoleNames(null)
             .build();
 
     Assertions.assertTrue(rangerAuthPlugin.onGroupAdded(group));
@@ -761,7 +769,8 @@ public class RangerHiveIT {
         UserEntity.builder()
             .withId(1L)
             .withName(userName1)
-            .withRoles(Collections.emptyList())
+            .withRoleNames(Collections.emptyList())
+            .withRoleIds(Collections.emptyList())
             .withAuditInfo(auditInfo)
             .build();
     Assertions.assertTrue(
@@ -777,7 +786,8 @@ public class RangerHiveIT {
         UserEntity.builder()
             .withId(1L)
             .withName(userName2)
-            .withRoles(Collections.emptyList())
+            .withRoleNames(Collections.emptyList())
+            .withRoleIds(Collections.emptyList())
             .withAuditInfo(auditInfo)
             .build();
     Assertions.assertTrue(
@@ -790,7 +800,8 @@ public class RangerHiveIT {
         UserEntity.builder()
             .withId(1L)
             .withName(userName3)
-            .withRoles(Collections.emptyList())
+            .withRoleNames(Collections.emptyList())
+            .withRoleIds(Collections.emptyList())
             .withAuditInfo(auditInfo)
             .build();
     Assertions.assertTrue(
@@ -822,7 +833,8 @@ public class RangerHiveIT {
         GroupEntity.builder()
             .withId(1L)
             .withName(groupName1)
-            .withRoles(Collections.emptyList())
+            .withRoleNames(Collections.emptyList())
+            .withRoleIds(Collections.emptyList())
             .withAuditInfo(auditInfo)
             .build();
     Assertions.assertTrue(
@@ -840,7 +852,8 @@ public class RangerHiveIT {
         GroupEntity.builder()
             .withId(1L)
             .withName(groupName2)
-            .withRoles(Collections.emptyList())
+            .withRoleNames(Collections.emptyList())
+            .withRoleIds(Collections.emptyList())
             .withAuditInfo(auditInfo)
             .build();
     Assertions.assertTrue(
@@ -858,7 +871,8 @@ public class RangerHiveIT {
         GroupEntity.builder()
             .withId(1L)
             .withName(groupName3)
-            .withRoles(Collections.emptyList())
+            .withRoleNames(Collections.emptyList())
+            .withRoleIds(Collections.emptyList())
             .withAuditInfo(auditInfo)
             .build();
     Assertions.assertTrue(
diff --git 
a/core/src/main/java/org/apache/gravitino/authorization/PermissionManager.java 
b/core/src/main/java/org/apache/gravitino/authorization/PermissionManager.java
index 479bb069e..edb02cdce 100644
--- 
a/core/src/main/java/org/apache/gravitino/authorization/PermissionManager.java
+++ 
b/core/src/main/java/org/apache/gravitino/authorization/PermissionManager.java
@@ -22,11 +22,9 @@ import static 
org.apache.gravitino.authorization.AuthorizationUtils.GROUP_DOES_N
 import static 
org.apache.gravitino.authorization.AuthorizationUtils.USER_DOES_NOT_EXIST_MSG;
 
 import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
 import java.io.IOException;
 import java.time.Instant;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
 import org.apache.commons.lang3.StringUtils;
@@ -72,10 +70,14 @@ class PermissionManager {
               UserEntity.class,
               Entity.EntityType.USER,
               userEntity -> {
-                List<RoleEntity> roleEntities = 
Lists.newArrayList(userEntity.roleEntities());
-
-                List<Long> roleIds =
-                    
roleEntities.stream().map(RoleEntity::id).collect(Collectors.toList());
+                List<RoleEntity> roleEntities = Lists.newArrayList();
+                if (userEntity.roleNames() != null) {
+                  for (String role : userEntity.roleNames()) {
+                    roleEntities.add(roleManager.getRole(metalake, role));
+                  }
+                }
+                List<String> roleNames = 
Lists.newArrayList(toRoleNames(roleEntities));
+                List<Long> roleIds = 
Lists.newArrayList(toRoleIds(roleEntities));
 
                 for (RoleEntity roleEntityToGrant : roleEntitiesToGrant) {
                   if (roleIds.contains(roleEntityToGrant.id())) {
@@ -85,8 +87,8 @@ class PermissionManager {
                         user,
                         metalake);
                   } else {
+                    roleNames.add(roleEntityToGrant.name());
                     roleIds.add(roleEntityToGrant.id());
-                    roleEntities.add(roleEntityToGrant);
                   }
                 }
 
@@ -102,7 +104,8 @@ class PermissionManager {
                     .withNamespace(userEntity.namespace())
                     .withId(userEntity.id())
                     .withName(userEntity.name())
-                    .withRoles(roleEntities)
+                    .withRoleNames(roleNames)
+                    .withRoleIds(roleIds)
                     .withAuditInfo(auditInfo)
                     .build();
               });
@@ -146,8 +149,13 @@ class PermissionManager {
               GroupEntity.class,
               Entity.EntityType.GROUP,
               groupEntity -> {
-                List<RoleEntity> roleEntities = 
Lists.newArrayList(groupEntity.roleEntities());
-
+                List<RoleEntity> roleEntities = Lists.newArrayList();
+                if (groupEntity.roleNames() != null) {
+                  for (String role : groupEntity.roleNames()) {
+                    roleEntities.add(roleManager.getRole(metalake, role));
+                  }
+                }
+                List<String> roleNames = 
Lists.newArrayList(toRoleNames(roleEntities));
                 List<Long> roleIds = 
Lists.newArrayList(toRoleIds(roleEntities));
 
                 for (RoleEntity roleEntityToGrant : roleEntitiesToGrant) {
@@ -158,8 +166,8 @@ class PermissionManager {
                         group,
                         metalake);
                   } else {
+                    roleNames.add(roleEntityToGrant.name());
                     roleIds.add(roleEntityToGrant.id());
-                    roleEntities.add(roleEntityToGrant);
                   }
                 }
 
@@ -175,7 +183,8 @@ class PermissionManager {
                     .withId(groupEntity.id())
                     .withNamespace(groupEntity.namespace())
                     .withName(groupEntity.name())
-                    .withRoles(roleEntities)
+                    .withRoleNames(roleNames)
+                    .withRoleIds(roleIds)
                     .withAuditInfo(auditInfo)
                     .build();
               });
@@ -219,18 +228,19 @@ class PermissionManager {
               GroupEntity.class,
               Entity.EntityType.GROUP,
               groupEntity -> {
-                List<RoleEntity> roleEntities = groupEntity.roleEntities();
-
-                // Avoid loading securable objects
-                Map<Long, RoleEntity> roleEntitiesMap = Maps.newHashMap();
-                for (RoleEntity entity : roleEntities) {
-                  roleEntitiesMap.put(entity.id(), entity);
+                List<RoleEntity> roleEntities = Lists.newArrayList();
+                if (groupEntity.roleNames() != null) {
+                  for (String role : groupEntity.roleNames()) {
+                    roleEntities.add(roleManager.getRole(metalake, role));
+                  }
                 }
+                List<String> roleNames = 
Lists.newArrayList(toRoleNames(roleEntities));
+                List<Long> roleIds = 
Lists.newArrayList(toRoleIds(roleEntities));
 
                 for (RoleEntity roleEntityToRevoke : roleEntitiesToRevoke) {
-                  if (roleEntitiesMap.containsKey(roleEntityToRevoke.id())) {
-                    roleEntitiesMap.remove(roleEntityToRevoke.id());
-                  } else {
+                  roleNames.remove(roleEntityToRevoke.name());
+                  boolean removed = roleIds.remove(roleEntityToRevoke.id());
+                  if (!removed) {
                     LOG.warn(
                         "Failed to revoke, role {} does not exist in the group 
{} of metalake {}",
                         roleEntityToRevoke.name(),
@@ -251,7 +261,8 @@ class PermissionManager {
                     .withNamespace(groupEntity.namespace())
                     .withId(groupEntity.id())
                     .withName(groupEntity.name())
-                    .withRoles(Lists.newArrayList(roleEntitiesMap.values()))
+                    .withRoleNames(roleNames)
+                    .withRoleIds(roleIds)
                     .withAuditInfo(auditInfo)
                     .build();
               });
@@ -297,18 +308,20 @@ class PermissionManager {
               UserEntity.class,
               Entity.EntityType.USER,
               userEntity -> {
-                List<RoleEntity> roleEntities = userEntity.roleEntities();
-
-                // Avoid loading securable objects
-                Map<Long, RoleEntity> roleEntitiesMap = Maps.newHashMap();
-                for (RoleEntity entity : roleEntities) {
-                  roleEntitiesMap.put(entity.id(), entity);
+                List<RoleEntity> roleEntities = Lists.newArrayList();
+                if (userEntity.roleNames() != null) {
+                  for (String role : userEntity.roleNames()) {
+                    roleEntities.add(roleManager.getRole(metalake, role));
+                  }
                 }
 
+                List<String> roleNames = 
Lists.newArrayList(toRoleNames(roleEntities));
+                List<Long> roleIds = 
Lists.newArrayList(toRoleIds(roleEntities));
+
                 for (RoleEntity roleEntityToRevoke : roleEntitiesToRevoke) {
-                  if (roleEntitiesMap.containsKey(roleEntityToRevoke.id())) {
-                    roleEntitiesMap.remove(roleEntityToRevoke.id());
-                  } else {
+                  roleNames.remove(roleEntityToRevoke.name());
+                  boolean removed = roleIds.remove(roleEntityToRevoke.id());
+                  if (!removed) {
                     LOG.warn(
                         "Failed to revoke, role {} doesn't exist in the user 
{} of metalake {}",
                         roleEntityToRevoke.name(),
@@ -328,7 +341,8 @@ class PermissionManager {
                     .withId(userEntity.id())
                     .withNamespace(userEntity.namespace())
                     .withName(userEntity.name())
-                    .withRoles(Lists.newArrayList(roleEntitiesMap.values()))
+                    .withRoleNames(roleNames)
+                    .withRoleIds(roleIds)
                     .withAuditInfo(auditInfo)
                     .build();
               });
@@ -359,6 +373,10 @@ class PermissionManager {
     }
   }
 
+  private List<String> toRoleNames(List<RoleEntity> roleEntities) {
+    return 
roleEntities.stream().map(RoleEntity::name).collect(Collectors.toList());
+  }
+
   private List<Long> toRoleIds(List<RoleEntity> roleEntities) {
     return 
roleEntities.stream().map(RoleEntity::id).collect(Collectors.toList());
   }
diff --git 
a/core/src/main/java/org/apache/gravitino/authorization/UserGroupManager.java 
b/core/src/main/java/org/apache/gravitino/authorization/UserGroupManager.java
index eef947f22..094276689 100644
--- 
a/core/src/main/java/org/apache/gravitino/authorization/UserGroupManager.java
+++ 
b/core/src/main/java/org/apache/gravitino/authorization/UserGroupManager.java
@@ -63,7 +63,7 @@ class UserGroupManager {
               .withId(idGenerator.nextId())
               .withName(name)
               .withNamespace(AuthorizationUtils.ofUserNamespace(metalake))
-              .withRoles(Lists.newArrayList())
+              .withRoleNames(Lists.newArrayList())
               .withAuditInfo(
                   AuditInfo.builder()
                       
.withCreator(PrincipalUtils.getCurrentPrincipal().getName())
@@ -117,7 +117,7 @@ class UserGroupManager {
               .withId(idGenerator.nextId())
               .withName(group)
               .withNamespace(AuthorizationUtils.ofGroupNamespace(metalake))
-              .withRoles(Collections.emptyList())
+              .withRoleNames(Collections.emptyList())
               .withAuditInfo(
                   AuditInfo.builder()
                       
.withCreator(PrincipalUtils.getCurrentPrincipal().getName())
diff --git a/core/src/main/java/org/apache/gravitino/meta/GroupEntity.java 
b/core/src/main/java/org/apache/gravitino/meta/GroupEntity.java
index 047c2bcce..d9e4b633d 100644
--- a/core/src/main/java/org/apache/gravitino/meta/GroupEntity.java
+++ b/core/src/main/java/org/apache/gravitino/meta/GroupEntity.java
@@ -23,8 +23,6 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
-import java.util.function.Supplier;
-import java.util.stream.Collectors;
 import org.apache.gravitino.Auditable;
 import org.apache.gravitino.Entity;
 import org.apache.gravitino.Field;
@@ -40,8 +38,11 @@ public class GroupEntity implements Group, Entity, 
Auditable, HasIdentifier {
   public static final Field NAME =
       Field.required("name", String.class, "The name of the group entity.");
 
-  public static final Field ROLES_SUPPLIER =
-      Field.required("roles_supplier", Supplier.class, "The roles supplier of 
the group entity.");
+  public static final Field ROLE_NAMES =
+      Field.optional("role_names", List.class, "The role names of the group 
entity.");
+
+  public static final Field ROLE_IDS =
+      Field.optional("role_ids", List.class, "The role names of the group 
entity.");
 
   public static final Field AUDIT_INFO =
       Field.required("audit_info", AuditInfo.class, "The audit details of the 
group entity.");
@@ -49,9 +50,9 @@ public class GroupEntity implements Group, Entity, Auditable, 
HasIdentifier {
   private Long id;
   private String name;
   private AuditInfo auditInfo;
+  private List<String> roleNames;
+  private List<Long> roleIds;
   private Namespace namespace;
-  // The roles is a lazy field to avoid unnecessary cost.
-  private Supplier<List<RoleEntity>> rolesSupplier = Collections::emptyList;
 
   private GroupEntity() {}
 
@@ -66,7 +67,8 @@ public class GroupEntity implements Group, Entity, Auditable, 
HasIdentifier {
     fields.put(ID, id);
     fields.put(NAME, name);
     fields.put(AUDIT_INFO, auditInfo);
-    fields.put(ROLES_SUPPLIER, rolesSupplier);
+    fields.put(ROLE_NAMES, roleNames);
+    fields.put(ROLE_IDS, roleIds);
 
     return Collections.unmodifiableMap(fields);
   }
@@ -128,20 +130,25 @@ public class GroupEntity implements Group, Entity, 
Auditable, HasIdentifier {
    */
   @Override
   public List<String> roles() {
-    if (roleEntities() == null) {
-      return null;
-    }
+    return roleNames;
+  }
 
-    return 
roleEntities().stream().map(RoleEntity::name).collect(Collectors.toList());
+  /**
+   * Returns the role names of the group entity.
+   *
+   * @return The role names of the group entity.
+   */
+  public List<String> roleNames() {
+    return roleNames;
   }
 
   /**
-   * Returns the role entities of the group entity.
+   * Returns the role ids of the group entity.
    *
-   * @return The role entities of the group entity.
+   * @return The role ids of the group entity.
    */
-  public List<RoleEntity> roleEntities() {
-    return rolesSupplier.get();
+  public List<Long> roleIds() {
+    return roleIds;
   }
 
   @Override
@@ -154,12 +161,13 @@ public class GroupEntity implements Group, Entity, 
Auditable, HasIdentifier {
         && Objects.equals(name, that.name)
         && Objects.equals(namespace, that.namespace)
         && Objects.equals(auditInfo, that.auditInfo)
-        && Objects.equals(roles(), that.roles());
+        && Objects.equals(roleNames, that.roleNames)
+        && Objects.equals(roleIds, that.roleIds);
   }
 
   @Override
   public int hashCode() {
-    return Objects.hash(id, name, auditInfo, roles());
+    return Objects.hash(id, name, auditInfo, roleNames, roleIds);
   }
 
   public static Builder builder() {
@@ -207,26 +215,24 @@ public class GroupEntity implements Group, Entity, 
Auditable, HasIdentifier {
     }
 
     /**
-     * Sets the roles of the group entity.
+     * Sets the role names of the group entity.
      *
      * @param roles The role names of the group entity.
      * @return The builder instance.
      */
-    public Builder withRoles(List<RoleEntity> roles) {
-      if (roles != null) {
-        groupEntity.rolesSupplier = () -> roles;
-      }
+    public Builder withRoleNames(List<String> roles) {
+      groupEntity.roleNames = roles;
       return this;
     }
 
     /**
-     * Sets the roles supplier of the group entity.
+     * Sets the role ids of the group entity.
      *
-     * @param supplier The roles supplier of the group entity.
+     * @param roleIds The role ids of the group entity.
      * @return The builder instance.
      */
-    public Builder withRolesSupplier(Supplier<List<RoleEntity>> supplier) {
-      groupEntity.rolesSupplier = supplier;
+    public Builder withRoleIds(List<Long> roleIds) {
+      groupEntity.roleIds = roleIds;
       return this;
     }
 
diff --git a/core/src/main/java/org/apache/gravitino/meta/RoleEntity.java 
b/core/src/main/java/org/apache/gravitino/meta/RoleEntity.java
index eda0bc899..d1b3bbfe9 100644
--- a/core/src/main/java/org/apache/gravitino/meta/RoleEntity.java
+++ b/core/src/main/java/org/apache/gravitino/meta/RoleEntity.java
@@ -24,7 +24,6 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
-import java.util.function.Supplier;
 import org.apache.gravitino.Auditable;
 import org.apache.gravitino.Entity;
 import org.apache.gravitino.Field;
@@ -47,18 +46,15 @@ public class RoleEntity implements Role, Entity, Auditable, 
HasIdentifier {
   public static final Field AUDIT_INFO =
       Field.required("audit_info", AuditInfo.class, "The audit details of the 
role entity.");
 
-  public static final Field SECURABLE_OBJECTS_SUPPLIER =
-      Field.required(
-          "securable_objects_supplier",
-          Supplier.class,
-          "The securable objects supplier of the role entity.");
+  public static final Field SECURABLE_OBJECT =
+      Field.required("securable_objects", List.class, "The securable objects 
of the role entity.");
 
   private Long id;
   private String name;
   private Map<String, String> properties;
   private AuditInfo auditInfo;
   private Namespace namespace;
-  private Supplier<List<SecurableObject>> securableObjectsSupplier = () -> 
null;
+  private List<SecurableObject> securableObjects;
 
   /**
    * The name of the role.
@@ -95,7 +91,16 @@ public class RoleEntity implements Role, Entity, Auditable, 
HasIdentifier {
    */
   @Override
   public List<SecurableObject> securableObjects() {
-    return securableObjectsSupplier.get();
+    // The securable object is a special kind of entities. Some entity types 
aren't the securable
+    // object, such as
+    // User, Role, etc.
+    // The securable object identifier must be unique.
+    // Gravitino assumes that the identifiers of the entities may be the same 
if they have different
+    // types.
+    // So one type of them can't be the securable object at least if there are 
the two same
+    // identifier
+    // entities .
+    return securableObjects;
   }
 
   /**
@@ -110,7 +115,7 @@ public class RoleEntity implements Role, Entity, Auditable, 
HasIdentifier {
     fields.put(NAME, name);
     fields.put(AUDIT_INFO, auditInfo);
     fields.put(PROPERTIES, properties);
-    fields.put(SECURABLE_OBJECTS_SUPPLIER, securableObjectsSupplier);
+    fields.put(SECURABLE_OBJECT, securableObjects);
 
     return Collections.unmodifiableMap(fields);
   }
@@ -146,12 +151,12 @@ public class RoleEntity implements Role, Entity, 
Auditable, HasIdentifier {
         && Objects.equals(namespace, that.namespace)
         && Objects.equals(auditInfo, that.auditInfo)
         && Objects.equals(properties, that.properties)
-        && Objects.equals(securableObjects(), that.securableObjects());
+        && Objects.equals(securableObjects, that.securableObjects);
   }
 
   @Override
   public int hashCode() {
-    return Objects.hash(id, name, properties, auditInfo, securableObjects(), 
namespace);
+    return Objects.hash(id, name, properties, auditInfo, securableObjects, 
namespace);
   }
 
   /**
@@ -226,19 +231,7 @@ public class RoleEntity implements Role, Entity, 
Auditable, HasIdentifier {
      * @return The builder instance.
      */
     public Builder withSecurableObjects(List<SecurableObject> 
securableObjects) {
-      roleEntity.securableObjectsSupplier = () -> 
ImmutableList.copyOf(securableObjects);
-      return this;
-    }
-
-    /**
-     * Sets the securable objects supplier of the role entity.
-     *
-     * @param securableObjectsSupplier The securable objects supplier of the 
role entity.
-     * @return The builder instance.
-     */
-    public Builder withSecurableObjectsSupplier(
-        Supplier<List<SecurableObject>> securableObjectsSupplier) {
-      roleEntity.securableObjectsSupplier = securableObjectsSupplier;
+      roleEntity.securableObjects = ImmutableList.copyOf(securableObjects);
       return this;
     }
 
diff --git a/core/src/main/java/org/apache/gravitino/meta/UserEntity.java 
b/core/src/main/java/org/apache/gravitino/meta/UserEntity.java
index 7e12bd2d6..c71d731a9 100644
--- a/core/src/main/java/org/apache/gravitino/meta/UserEntity.java
+++ b/core/src/main/java/org/apache/gravitino/meta/UserEntity.java
@@ -23,8 +23,6 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
-import java.util.function.Supplier;
-import java.util.stream.Collectors;
 import lombok.ToString;
 import org.apache.gravitino.Auditable;
 import org.apache.gravitino.Entity;
@@ -46,15 +44,18 @@ public class UserEntity implements User, Entity, Auditable, 
HasIdentifier {
   public static final Field AUDIT_INFO =
       Field.required("audit_info", AuditInfo.class, "The audit details of the 
user entity.");
 
-  public static final Field ROLES_SUPPLIER =
-      Field.required("roles_supplier", Supplier.class, "The roles supplier of 
the user entity");
+  public static final Field ROLE_NAMES =
+      Field.optional("role_names", List.class, "The role names of the user 
entity");
+
+  public static final Field ROLE_IDS =
+      Field.optional("role_ids", List.class, "The role ids of the user 
entity");
 
   private Long id;
   private String name;
   private AuditInfo auditInfo;
+  private List<String> roleNames;
+  private List<Long> roleIds;
   private Namespace namespace;
-  // The roles is a lazy field to avoid unnecessary cost.
-  private Supplier<List<RoleEntity>> rolesSupplier = Collections::emptyList;
 
   private UserEntity() {}
 
@@ -69,7 +70,8 @@ public class UserEntity implements User, Entity, Auditable, 
HasIdentifier {
     fields.put(ID, id);
     fields.put(NAME, name);
     fields.put(AUDIT_INFO, auditInfo);
-    fields.put(ROLES_SUPPLIER, rolesSupplier);
+    fields.put(ROLE_NAMES, roleNames);
+    fields.put(ROLE_IDS, roleIds);
 
     return Collections.unmodifiableMap(fields);
   }
@@ -131,16 +133,25 @@ public class UserEntity implements User, Entity, 
Auditable, HasIdentifier {
    */
   @Override
   public List<String> roles() {
-    return 
roleEntities().stream().map(RoleEntity::name).collect(Collectors.toList());
+    return roleNames;
+  }
+
+  /**
+   * Returns the role names of the user entity.
+   *
+   * @return The role names of the user entity.
+   */
+  public List<String> roleNames() {
+    return roleNames;
   }
 
   /**
-   * Returns the role entities of the user entity.
+   * Returns the role ids of the user entity.
    *
-   * @return The role entities of the user entity.
+   * @return The role ids of the user entity.
    */
-  public List<RoleEntity> roleEntities() {
-    return rolesSupplier.get();
+  public List<Long> roleIds() {
+    return roleIds;
   }
 
   @Override
@@ -153,12 +164,13 @@ public class UserEntity implements User, Entity, 
Auditable, HasIdentifier {
         && Objects.equals(name, that.name)
         && Objects.equals(namespace, that.namespace)
         && Objects.equals(auditInfo, that.auditInfo)
-        && Objects.equals(roles(), that.roles());
+        && Objects.equals(roleNames, that.roleNames)
+        && Objects.equals(roleIds, that.roleIds);
   }
 
   @Override
   public int hashCode() {
-    return Objects.hash(id, name, auditInfo, roles());
+    return Objects.hash(id, name, auditInfo, roleNames, roleIds);
   }
 
   public static Builder builder() {
@@ -206,26 +218,24 @@ public class UserEntity implements User, Entity, 
Auditable, HasIdentifier {
     }
 
     /**
-     * Sets the roles of the user entity.
+     * Sets the role names of the user entity.
      *
-     * @param roles The role entities of the user entity.
+     * @param roles The role names of the user entity.
      * @return The builder instance.
      */
-    public Builder withRoles(List<RoleEntity> roles) {
-      if (roles != null) {
-        userEntity.rolesSupplier = () -> roles;
-      }
+    public Builder withRoleNames(List<String> roles) {
+      userEntity.roleNames = roles;
       return this;
     }
 
     /**
-     * Sets the roles supplier of the user entity.
+     * Sets the role ids of the user entity.
      *
-     * @param supplier The roles supplier of the user entity.
+     * @param roleIds The role ids of the user entity.
      * @return The builder instance.
      */
-    public Builder withRolesSupplier(Supplier<List<RoleEntity>> supplier) {
-      userEntity.rolesSupplier = supplier;
+    public Builder withRoleIds(List<Long> roleIds) {
+      userEntity.roleIds = roleIds;
       return this;
     }
 
diff --git 
a/core/src/main/java/org/apache/gravitino/proto/GroupEntitySerDe.java 
b/core/src/main/java/org/apache/gravitino/proto/GroupEntitySerDe.java
new file mode 100644
index 000000000..46eb9c908
--- /dev/null
+++ b/core/src/main/java/org/apache/gravitino/proto/GroupEntitySerDe.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.gravitino.proto;
+
+import java.util.Collection;
+import org.apache.gravitino.Namespace;
+import org.apache.gravitino.meta.GroupEntity;
+
+public class GroupEntitySerDe implements ProtoSerDe<GroupEntity, Group> {
+
+  @Override
+  public Group serialize(GroupEntity groupEntity) {
+    Group.Builder builder =
+        Group.newBuilder()
+            .setId(groupEntity.id())
+            .setName(groupEntity.name())
+            .setAuditInfo(new 
AuditInfoSerDe().serialize(groupEntity.auditInfo()));
+
+    if (isCollectionNotEmpty(groupEntity.roles())) {
+      builder.addAllRoleNames(groupEntity.roles());
+    }
+
+    if (isCollectionNotEmpty(groupEntity.roleIds())) {
+      builder.addAllRoleIds(groupEntity.roleIds());
+    }
+
+    return builder.build();
+  }
+
+  @Override
+  public GroupEntity deserialize(Group group, Namespace namespace) {
+    GroupEntity.Builder builder =
+        GroupEntity.builder()
+            .withId(group.getId())
+            .withName(group.getName())
+            .withNamespace(namespace)
+            .withAuditInfo(new 
AuditInfoSerDe().deserialize(group.getAuditInfo(), namespace));
+
+    if (group.getRoleNamesCount() > 0) {
+      builder.withRoleNames(group.getRoleNamesList());
+    }
+
+    if (group.getRoleIdsCount() > 0) {
+      builder.withRoleIds(group.getRoleIdsList());
+    }
+
+    return builder.build();
+  }
+
+  private boolean isCollectionNotEmpty(Collection collection) {
+    return collection != null && !collection.isEmpty();
+  }
+}
diff --git 
a/core/src/main/java/org/apache/gravitino/proto/ProtoEntitySerDe.java 
b/core/src/main/java/org/apache/gravitino/proto/ProtoEntitySerDe.java
index a4b01a896..3dc5cb1c2 100644
--- a/core/src/main/java/org/apache/gravitino/proto/ProtoEntitySerDe.java
+++ b/core/src/main/java/org/apache/gravitino/proto/ProtoEntitySerDe.java
@@ -53,6 +53,11 @@ public class ProtoEntitySerDe implements EntitySerDe {
           .put(
               "org.apache.gravitino.meta.TopicEntity",
               "org.apache.gravitino.proto.TopicEntitySerDe")
+          .put("org.apache.gravitino.meta.UserEntity", 
"org.apache.gravitino.proto.UserEntitySerDe")
+          .put(
+              "org.apache.gravitino.meta.GroupEntity",
+              "org.apache.gravitino.proto.GroupEntitySerDe")
+          .put("org.apache.gravitino.meta.RoleEntity", 
"org.apache.gravitino.proto.RoleEntitySerDe")
           .build();
 
   private static final Map<String, String> ENTITY_TO_PROTO =
@@ -70,7 +75,13 @@ public class ProtoEntitySerDe implements EntitySerDe {
           "org.apache.gravitino.meta.FilesetEntity",
           "org.apache.gravitino.proto.Fileset",
           "org.apache.gravitino.meta.TopicEntity",
-          "org.apache.gravitino.proto.Topic");
+          "org.apache.gravitino.proto.Topic",
+          "org.apache.gravitino.meta.UserEntity",
+          "org.apache.gravitino.proto.User",
+          "org.apache.gravitino.meta.GroupEntity",
+          "org.apache.gravitino.proto.Group",
+          "org.apache.gravitino.meta.RoleEntity",
+          "org.apache.gravitino.proto.Role");
 
   private final Map<Class<? extends Entity>, ProtoSerDe<? extends Entity, ? 
extends Message>>
       entityToSerDe;
diff --git a/core/src/main/java/org/apache/gravitino/proto/RoleEntitySerDe.java 
b/core/src/main/java/org/apache/gravitino/proto/RoleEntitySerDe.java
new file mode 100644
index 000000000..a54f4505d
--- /dev/null
+++ b/core/src/main/java/org/apache/gravitino/proto/RoleEntitySerDe.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.gravitino.proto;
+
+import com.google.common.collect.Lists;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.apache.gravitino.MetadataObject;
+import org.apache.gravitino.Namespace;
+import org.apache.gravitino.authorization.Privilege;
+import org.apache.gravitino.authorization.Privileges;
+import org.apache.gravitino.authorization.SecurableObject;
+import org.apache.gravitino.authorization.SecurableObjects;
+import org.apache.gravitino.meta.RoleEntity;
+
+public class RoleEntitySerDe implements ProtoSerDe<RoleEntity, Role> {
+
+  /**
+   * Serializes the provided entity into its corresponding Protocol Buffer 
message representation.
+   *
+   * @param roleEntity The entity to be serialized.
+   * @return The Protocol Buffer message representing the serialized entity.
+   */
+  @Override
+  public Role serialize(RoleEntity roleEntity) {
+    Role.Builder builder =
+        Role.newBuilder()
+            .setId(roleEntity.id())
+            .setName(roleEntity.name())
+            .setAuditInfo(new 
AuditInfoSerDe().serialize(roleEntity.auditInfo()));
+
+    for (SecurableObject securableObject : roleEntity.securableObjects()) {
+      builder.addSecurableObjects(
+          org.apache.gravitino.proto.SecurableObject.newBuilder()
+              .setFullName(securableObject.fullName())
+              .setType(securableObject.type().name())
+              .addAllPrivilegeConditions(
+                  securableObject.privileges().stream()
+                      .map(Privilege::condition)
+                      .map(Privilege.Condition::name)
+                      .collect(Collectors.toList()))
+              .addAllPrivilegeNames(
+                  securableObject.privileges().stream()
+                      .map(Privilege::name)
+                      .map(Privilege.Name::name)
+                      .collect(Collectors.toList()))
+              .build());
+    }
+
+    if (roleEntity.properties() != null && !roleEntity.properties().isEmpty()) 
{
+      builder.putAllProperties(roleEntity.properties());
+    }
+
+    return builder.build();
+  }
+
+  /**
+   * Deserializes the provided Protocol Buffer message into its corresponding 
entity representation.
+   *
+   * @param role The Protocol Buffer message to be deserialized.
+   * @return The entity representing the deserialized Protocol Buffer message.
+   */
+  @Override
+  public RoleEntity deserialize(Role role, Namespace namespace) {
+    List<SecurableObject> securableObjects = Lists.newArrayList();
+
+    for (int index = 0; index < role.getSecurableObjectsCount(); index++) {
+      List<Privilege> privileges = Lists.newArrayList();
+      org.apache.gravitino.proto.SecurableObject object = 
role.getSecurableObjects(index);
+      for (int privIndex = 0; privIndex < 
object.getPrivilegeConditionsCount(); privIndex++) {
+        if 
(Privilege.Condition.ALLOW.name().equals(object.getPrivilegeConditions(privIndex)))
 {
+          
privileges.add(Privileges.allow(object.getPrivilegeNames(privIndex)));
+        } else {
+          privileges.add(Privileges.deny(object.getPrivilegeNames(privIndex)));
+        }
+      }
+
+      SecurableObject securableObject =
+          SecurableObjects.parse(
+              object.getFullName(), 
MetadataObject.Type.valueOf(object.getType()), privileges);
+
+      securableObjects.add(securableObject);
+    }
+
+    RoleEntity.Builder builder =
+        RoleEntity.builder()
+            .withId(role.getId())
+            .withName(role.getName())
+            .withNamespace(namespace)
+            .withSecurableObjects(securableObjects)
+            .withAuditInfo(new 
AuditInfoSerDe().deserialize(role.getAuditInfo(), namespace));
+
+    if (!role.getPropertiesMap().isEmpty()) {
+      builder.withProperties(role.getPropertiesMap());
+    }
+
+    return builder.build();
+  }
+}
diff --git a/core/src/main/java/org/apache/gravitino/proto/UserEntitySerDe.java 
b/core/src/main/java/org/apache/gravitino/proto/UserEntitySerDe.java
new file mode 100644
index 000000000..e859ee3b8
--- /dev/null
+++ b/core/src/main/java/org/apache/gravitino/proto/UserEntitySerDe.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.gravitino.proto;
+
+import java.util.Collection;
+import org.apache.gravitino.Namespace;
+import org.apache.gravitino.meta.UserEntity;
+
+public class UserEntitySerDe implements ProtoSerDe<UserEntity, User> {
+
+  @Override
+  public User serialize(UserEntity userEntity) {
+    User.Builder builder =
+        User.newBuilder()
+            .setId(userEntity.id())
+            .setName(userEntity.name())
+            .setAuditInfo(new 
AuditInfoSerDe().serialize(userEntity.auditInfo()));
+
+    if (isCollectionNotEmpty(userEntity.roles())) {
+      builder.addAllRoleNames(userEntity.roles());
+    }
+
+    if (isCollectionNotEmpty(userEntity.roleIds())) {
+      builder.addAllRoleIds(userEntity.roleIds());
+    }
+
+    return builder.build();
+  }
+
+  @Override
+  public UserEntity deserialize(User user, Namespace namespace) {
+    UserEntity.Builder builder =
+        UserEntity.builder()
+            .withId(user.getId())
+            .withName(user.getName())
+            .withNamespace(namespace)
+            .withAuditInfo(new 
AuditInfoSerDe().deserialize(user.getAuditInfo(), namespace));
+
+    if (user.getRoleNamesCount() > 0) {
+      builder.withRoleNames(user.getRoleNamesList());
+    }
+
+    if (user.getRoleIdsCount() > 0) {
+      builder.withRoleIds(user.getRoleIdsList());
+    }
+
+    return builder.build();
+  }
+
+  private boolean isCollectionNotEmpty(Collection collection) {
+    return collection != null && !collection.isEmpty();
+  }
+}
diff --git 
a/core/src/main/java/org/apache/gravitino/storage/kv/BinaryEntityKeyEncoder.java
 
b/core/src/main/java/org/apache/gravitino/storage/kv/BinaryEntityKeyEncoder.java
index 2dd0e00b0..fa6fb48c6 100644
--- 
a/core/src/main/java/org/apache/gravitino/storage/kv/BinaryEntityKeyEncoder.java
+++ 
b/core/src/main/java/org/apache/gravitino/storage/kv/BinaryEntityKeyEncoder.java
@@ -20,10 +20,13 @@ package org.apache.gravitino.storage.kv;
 
 import static org.apache.gravitino.Entity.EntityType.CATALOG;
 import static org.apache.gravitino.Entity.EntityType.FILESET;
+import static org.apache.gravitino.Entity.EntityType.GROUP;
 import static org.apache.gravitino.Entity.EntityType.METALAKE;
+import static org.apache.gravitino.Entity.EntityType.ROLE;
 import static org.apache.gravitino.Entity.EntityType.SCHEMA;
 import static org.apache.gravitino.Entity.EntityType.TABLE;
 import static org.apache.gravitino.Entity.EntityType.TOPIC;
+import static org.apache.gravitino.Entity.EntityType.USER;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
@@ -90,6 +93,12 @@ public class BinaryEntityKeyEncoder implements 
EntityKeyEncoder<byte[]> {
           new String[] {TABLE.getShortName() + "/", "/", "/", "/"},
           FILESET,
           new String[] {FILESET.getShortName() + "/", "/", "/", "/"},
+          USER,
+          new String[] {USER.getShortName() + "/", "/", "/", "/"},
+          GROUP,
+          new String[] {GROUP.getShortName() + "/", "/", "/", "/"},
+          ROLE,
+          new String[] {ROLE.getShortName() + "/", "/", "/", "/"},
           TOPIC,
           new String[] {TOPIC.getShortName() + "/", "/", "/", "/"});
 
diff --git 
a/core/src/main/java/org/apache/gravitino/storage/relational/service/GroupMetaService.java
 
b/core/src/main/java/org/apache/gravitino/storage/relational/service/GroupMetaService.java
index 2762d55a7..2ffc10dac 100644
--- 
a/core/src/main/java/org/apache/gravitino/storage/relational/service/GroupMetaService.java
+++ 
b/core/src/main/java/org/apache/gravitino/storage/relational/service/GroupMetaService.java
@@ -22,8 +22,10 @@ import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 import java.io.IOException;
+import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.Set;
 import java.util.function.Function;
 import java.util.stream.Collectors;
@@ -39,10 +41,10 @@ import 
org.apache.gravitino.storage.relational.mapper.GroupRoleRelMapper;
 import org.apache.gravitino.storage.relational.mapper.OwnerMetaMapper;
 import org.apache.gravitino.storage.relational.po.GroupPO;
 import org.apache.gravitino.storage.relational.po.GroupRoleRelPO;
+import org.apache.gravitino.storage.relational.po.RolePO;
 import org.apache.gravitino.storage.relational.utils.ExceptionUtils;
 import org.apache.gravitino.storage.relational.utils.POConverters;
 import org.apache.gravitino.storage.relational.utils.SessionUtils;
-import org.apache.gravitino.storage.relational.utils.SupplierUtils;
 
 /** The service class for group metadata. It provides the basic database 
operations for group. */
 public class GroupMetaService {
@@ -90,9 +92,9 @@ public class GroupMetaService {
     Long metalakeId =
         
MetalakeMetaService.getInstance().getMetalakeIdByName(identifier.namespace().level(0));
     GroupPO groupPO = getGroupPOByMetalakeIdAndName(metalakeId, 
identifier.name());
+    List<RolePO> rolePOs = 
RoleMetaService.getInstance().listRolesByGroupId(groupPO.getGroupId());
 
-    return POConverters.fromGroupPO(
-        groupPO, SupplierUtils.createRolePOsSupplier(groupPO), 
identifier.namespace());
+    return POConverters.fromGroupPO(groupPO, rolePOs, identifier.namespace());
   }
 
   public List<GroupEntity> listGroupsByRoleIdent(NameIdentifier roleIdent) {
@@ -105,7 +107,7 @@ public class GroupMetaService {
             po ->
                 POConverters.fromGroupPO(
                     po,
-                    SupplierUtils.createRolePOsSupplier(po),
+                    Collections.emptyList(),
                     
AuthorizationUtils.ofGroupNamespace(roleIdent.namespace().level(0))))
         .collect(Collectors.toList());
   }
@@ -119,8 +121,7 @@ public class GroupMetaService {
       GroupPO.Builder builder = GroupPO.builder().withMetalakeId(metalakeId);
       GroupPO GroupPO = POConverters.initializeGroupPOWithVersion(groupEntity, 
builder);
 
-      List<Long> roleIds =
-          
groupEntity.roleEntities().stream().map(RoleEntity::id).collect(Collectors.toList());
+      List<Long> roleIds = 
Optional.ofNullable(groupEntity.roleIds()).orElse(Lists.newArrayList());
       List<GroupRoleRelPO> groupRoleRelPOS =
           POConverters.initializeGroupRoleRelsPOWithVersion(groupEntity, 
roleIds);
 
@@ -185,10 +186,10 @@ public class GroupMetaService {
     Long metalakeId =
         
MetalakeMetaService.getInstance().getMetalakeIdByName(identifier.namespace().level(0));
     GroupPO oldGroupPO = getGroupPOByMetalakeIdAndName(metalakeId, 
identifier.name());
-
+    List<RolePO> rolePOs =
+        
RoleMetaService.getInstance().listRolesByGroupId(oldGroupPO.getGroupId());
     GroupEntity oldGroupEntity =
-        POConverters.fromGroupPO(
-            oldGroupPO, SupplierUtils.createRolePOsSupplier(oldGroupPO), 
identifier.namespace());
+        POConverters.fromGroupPO(oldGroupPO, rolePOs, identifier.namespace());
 
     GroupEntity newEntity = (GroupEntity) updater.apply((E) oldGroupEntity);
     Preconditions.checkArgument(
@@ -198,10 +199,11 @@ public class GroupMetaService {
         oldGroupEntity.id());
 
     Set<Long> oldRoleIds =
-        
oldGroupEntity.roleEntities().stream().map(RoleEntity::id).collect(Collectors.toSet());
-
+        oldGroupEntity.roleIds() == null
+            ? Sets.newHashSet()
+            : Sets.newHashSet(oldGroupEntity.roleIds());
     Set<Long> newRoleIds =
-        
newEntity.roleEntities().stream().map(RoleEntity::id).collect(Collectors.toSet());
+        newEntity.roleIds() == null ? Sets.newHashSet() : 
Sets.newHashSet(newEntity.roleIds());
 
     Set<Long> insertRoleIds = Sets.difference(newRoleIds, oldRoleIds);
     Set<Long> deleteRoleIds = Sets.difference(oldRoleIds, newRoleIds);
diff --git 
a/core/src/main/java/org/apache/gravitino/storage/relational/service/OwnerMetaService.java
 
b/core/src/main/java/org/apache/gravitino/storage/relational/service/OwnerMetaService.java
index 502b427f0..1118467b0 100644
--- 
a/core/src/main/java/org/apache/gravitino/storage/relational/service/OwnerMetaService.java
+++ 
b/core/src/main/java/org/apache/gravitino/storage/relational/service/OwnerMetaService.java
@@ -18,6 +18,7 @@
  */
 package org.apache.gravitino.storage.relational.service;
 
+import java.util.Collections;
 import java.util.Optional;
 import org.apache.gravitino.Entity;
 import org.apache.gravitino.MetadataObject;
@@ -29,7 +30,6 @@ import org.apache.gravitino.storage.relational.po.OwnerRelPO;
 import org.apache.gravitino.storage.relational.po.UserPO;
 import org.apache.gravitino.storage.relational.utils.POConverters;
 import org.apache.gravitino.storage.relational.utils.SessionUtils;
-import org.apache.gravitino.storage.relational.utils.SupplierUtils;
 import org.apache.gravitino.utils.NameIdentifierUtil;
 
 /** This class is an utilization class to retrieve owner relation. */
@@ -58,7 +58,7 @@ public class OwnerMetaService {
       return Optional.of(
           POConverters.fromUserPO(
               userPO,
-              SupplierUtils.createRolePOsSupplier(userPO),
+              Collections.emptyList(),
               
AuthorizationUtils.ofUserNamespace(NameIdentifierUtil.getMetalake(identifier))));
     }
 
@@ -71,7 +71,7 @@ public class OwnerMetaService {
       return Optional.of(
           POConverters.fromGroupPO(
               groupPO,
-              SupplierUtils.createRolePOsSupplier(groupPO),
+              Collections.emptyList(),
               
AuthorizationUtils.ofGroupNamespace(NameIdentifierUtil.getMetalake(identifier))));
     }
 
diff --git 
a/core/src/main/java/org/apache/gravitino/storage/relational/service/RoleMetaService.java
 
b/core/src/main/java/org/apache/gravitino/storage/relational/service/RoleMetaService.java
index 743eb6338..4560b74e0 100644
--- 
a/core/src/main/java/org/apache/gravitino/storage/relational/service/RoleMetaService.java
+++ 
b/core/src/main/java/org/apache/gravitino/storage/relational/service/RoleMetaService.java
@@ -39,12 +39,14 @@ import 
org.apache.gravitino.storage.relational.po.SecurableObjectPO;
 import org.apache.gravitino.storage.relational.utils.ExceptionUtils;
 import org.apache.gravitino.storage.relational.utils.POConverters;
 import org.apache.gravitino.storage.relational.utils.SessionUtils;
-import org.apache.gravitino.storage.relational.utils.SupplierUtils;
 import org.apache.gravitino.utils.NameIdentifierUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /** The service class for role metadata. It provides the basic database 
operations for role. */
 public class RoleMetaService {
 
+  private static final Logger LOG = 
LoggerFactory.getLogger(RoleMetaService.class);
   private static final RoleMetaService INSTANCE = new RoleMetaService();
 
   public static RoleMetaService getInstance() {
@@ -107,12 +109,33 @@ public class RoleMetaService {
         .map(
             po ->
                 POConverters.fromRolePO(
-                    po,
-                    SupplierUtils.createSecurableObjectsSupplier(po),
-                    AuthorizationUtils.ofRoleNamespace(metalake)))
+                    po, listSecurableObjects(po), 
AuthorizationUtils.ofRoleNamespace(metalake)))
         .collect(Collectors.toList());
   }
 
+  private List<SecurableObject> listSecurableObjects(RolePO po) {
+    List<SecurableObjectPO> securableObjectPOs = 
listSecurableObjectsByRoleId(po.getRoleId());
+    List<SecurableObject> securableObjects = Lists.newArrayList();
+
+    for (SecurableObjectPO securableObjectPO : securableObjectPOs) {
+      String fullName =
+          MetadataObjectService.getMetadataObjectFullName(
+              securableObjectPO.getType(), 
securableObjectPO.getMetadataObjectId());
+      if (fullName != null) {
+        securableObjects.add(
+            POConverters.fromSecurableObjectPO(
+                fullName, securableObjectPO, 
getType(securableObjectPO.getType())));
+      } else {
+        LOG.info(
+            "The securable object {} {} may be deleted",
+            securableObjectPO.getMetadataObjectId(),
+            securableObjectPO.getType());
+      }
+    }
+
+    return securableObjects;
+  }
+
   public List<RolePO> listRolesByGroupId(Long groupId) {
     return SessionUtils.getWithoutCommit(
         RoleMetaMapper.class, mapper -> mapper.listRolesByGroupId(groupId));
@@ -174,8 +197,9 @@ public class RoleMetaService {
         
MetalakeMetaService.getInstance().getMetalakeIdByName(identifier.namespace().level(0));
     RolePO rolePO = getRolePOByMetalakeIdAndName(metalakeId, 
identifier.name());
 
-    return POConverters.fromRolePO(
-        rolePO, SupplierUtils.createSecurableObjectsSupplier(rolePO), 
identifier.namespace());
+    List<SecurableObject> securableObjects = listSecurableObjects(rolePO);
+
+    return POConverters.fromRolePO(rolePO, securableObjects, 
identifier.namespace());
   }
 
   public boolean deleteRole(NameIdentifier identifier) {
@@ -208,7 +232,7 @@ public class RoleMetaService {
     return true;
   }
 
-  public List<SecurableObjectPO> listSecurableObjectsByRoleId(Long roleId) {
+  private List<SecurableObjectPO> listSecurableObjectsByRoleId(Long roleId) {
     return SessionUtils.getWithoutCommit(
         SecurableObjectMapper.class, mapper -> 
mapper.listSecurableObjectsByRoleId(roleId));
   }
@@ -249,6 +273,10 @@ public class RoleMetaService {
         + securableObjectsCount[0];
   }
 
+  private MetadataObject.Type getType(String type) {
+    return MetadataObject.Type.valueOf(type);
+  }
+
   private String getEntityType(SecurableObject securableObject) {
     return securableObject.type().name();
   }
diff --git 
a/core/src/main/java/org/apache/gravitino/storage/relational/service/UserMetaService.java
 
b/core/src/main/java/org/apache/gravitino/storage/relational/service/UserMetaService.java
index 67bbfbce3..e7d0a435a 100644
--- 
a/core/src/main/java/org/apache/gravitino/storage/relational/service/UserMetaService.java
+++ 
b/core/src/main/java/org/apache/gravitino/storage/relational/service/UserMetaService.java
@@ -22,8 +22,10 @@ import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 import java.io.IOException;
+import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.Set;
 import java.util.function.Function;
 import java.util.stream.Collectors;
@@ -37,12 +39,12 @@ import org.apache.gravitino.meta.UserEntity;
 import org.apache.gravitino.storage.relational.mapper.OwnerMetaMapper;
 import org.apache.gravitino.storage.relational.mapper.UserMetaMapper;
 import org.apache.gravitino.storage.relational.mapper.UserRoleRelMapper;
+import org.apache.gravitino.storage.relational.po.RolePO;
 import org.apache.gravitino.storage.relational.po.UserPO;
 import org.apache.gravitino.storage.relational.po.UserRoleRelPO;
 import org.apache.gravitino.storage.relational.utils.ExceptionUtils;
 import org.apache.gravitino.storage.relational.utils.POConverters;
 import org.apache.gravitino.storage.relational.utils.SessionUtils;
-import org.apache.gravitino.storage.relational.utils.SupplierUtils;
 
 /** The service class for user metadata. It provides the basic database 
operations for user. */
 public class UserMetaService {
@@ -90,9 +92,9 @@ public class UserMetaService {
     Long metalakeId =
         
MetalakeMetaService.getInstance().getMetalakeIdByName(identifier.namespace().level(0));
     UserPO userPO = getUserPOByMetalakeIdAndName(metalakeId, 
identifier.name());
+    List<RolePO> rolePOs = 
RoleMetaService.getInstance().listRolesByUserId(userPO.getUserId());
 
-    return POConverters.fromUserPO(
-        userPO, SupplierUtils.createRolePOsSupplier(userPO), 
identifier.namespace());
+    return POConverters.fromUserPO(userPO, rolePOs, identifier.namespace());
   }
 
   public List<UserEntity> listUsersByRoleIdent(NameIdentifier roleIdent) {
@@ -105,7 +107,7 @@ public class UserMetaService {
             po ->
                 POConverters.fromUserPO(
                     po,
-                    SupplierUtils.createRolePOsSupplier(po),
+                    Collections.emptyList(),
                     
AuthorizationUtils.ofUserNamespace(roleIdent.namespace().level(0))))
         .collect(Collectors.toList());
   }
@@ -119,8 +121,7 @@ public class UserMetaService {
       UserPO.Builder builder = UserPO.builder().withMetalakeId(metalakeId);
       UserPO userPO = POConverters.initializeUserPOWithVersion(userEntity, 
builder);
 
-      List<Long> roleIds =
-          
userEntity.roleEntities().stream().map(RoleEntity::id).collect(Collectors.toList());
+      List<Long> roleIds = 
Optional.ofNullable(userEntity.roleIds()).orElse(Lists.newArrayList());
       List<UserRoleRelPO> userRoleRelPOs =
           POConverters.initializeUserRoleRelsPOWithVersion(userEntity, 
roleIds);
 
@@ -184,9 +185,8 @@ public class UserMetaService {
     Long metalakeId =
         
MetalakeMetaService.getInstance().getMetalakeIdByName(identifier.namespace().level(0));
     UserPO oldUserPO = getUserPOByMetalakeIdAndName(metalakeId, 
identifier.name());
-    UserEntity oldUserEntity =
-        POConverters.fromUserPO(
-            oldUserPO, SupplierUtils.createRolePOsSupplier(oldUserPO), 
identifier.namespace());
+    List<RolePO> rolePOs = 
RoleMetaService.getInstance().listRolesByUserId(oldUserPO.getUserId());
+    UserEntity oldUserEntity = POConverters.fromUserPO(oldUserPO, rolePOs, 
identifier.namespace());
 
     UserEntity newEntity = (UserEntity) updater.apply((E) oldUserEntity);
     Preconditions.checkArgument(
@@ -196,10 +196,11 @@ public class UserMetaService {
         oldUserEntity.id());
 
     Set<Long> oldRoleIds =
-        
oldUserEntity.roleEntities().stream().map(RoleEntity::id).collect(Collectors.toSet());
-
+        oldUserEntity.roleIds() == null
+            ? Sets.newHashSet()
+            : Sets.newHashSet(oldUserEntity.roleIds());
     Set<Long> newRoleIds =
-        
newEntity.roleEntities().stream().map(RoleEntity::id).collect(Collectors.toSet());
+        newEntity.roleIds() == null ? Sets.newHashSet() : 
Sets.newHashSet(newEntity.roleIds());
 
     Set<Long> insertRoleIds = Sets.difference(newRoleIds, oldRoleIds);
     Set<Long> deleteRoleIds = Sets.difference(oldRoleIds, newRoleIds);
diff --git 
a/core/src/main/java/org/apache/gravitino/storage/relational/utils/POConverters.java
 
b/core/src/main/java/org/apache/gravitino/storage/relational/utils/POConverters.java
index c21ef1df0..82d739a41 100644
--- 
a/core/src/main/java/org/apache/gravitino/storage/relational/utils/POConverters.java
+++ 
b/core/src/main/java/org/apache/gravitino/storage/relational/utils/POConverters.java
@@ -24,13 +24,11 @@ import com.google.common.collect.Lists;
 import java.time.Instant;
 import java.util.List;
 import java.util.Map;
-import java.util.function.Supplier;
 import java.util.stream.Collectors;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.gravitino.Catalog;
 import org.apache.gravitino.MetadataObject;
 import org.apache.gravitino.Namespace;
-import org.apache.gravitino.authorization.AuthorizationUtils;
 import org.apache.gravitino.authorization.Privilege;
 import org.apache.gravitino.authorization.Privileges;
 import org.apache.gravitino.authorization.SecurableObject;
@@ -701,31 +699,29 @@ public class POConverters {
    * Convert {@link UserPO} to {@link UserEntity}
    *
    * @param userPO UserPo object to be converted
-   * @param rolePOsSupplier Supplier for the list of rolePO
+   * @param rolePOs list of rolePO
    * @param namespace Namespace object to be associated with the user
    * @return UserEntity object from UserPO object
    */
-  public static UserEntity fromUserPO(
-      UserPO userPO, Supplier<List<RolePO>> rolePOsSupplier, Namespace 
namespace) {
+  public static UserEntity fromUserPO(UserPO userPO, List<RolePO> rolePOs, 
Namespace namespace) {
     try {
+      List<String> roleNames =
+          
rolePOs.stream().map(RolePO::getRoleName).collect(Collectors.toList());
+      List<Long> roleIds = 
rolePOs.stream().map(RolePO::getRoleId).collect(Collectors.toList());
+
       UserEntity.Builder builder =
           UserEntity.builder()
               .withId(userPO.getUserId())
               .withName(userPO.getUserName())
               .withNamespace(namespace)
               .withAuditInfo(
-                  JsonUtils.anyFieldMapper().readValue(userPO.getAuditInfo(), 
AuditInfo.class))
-              .withRolesSupplier(
-                  () ->
-                      rolePOsSupplier.get().stream()
-                          .map(
-                              po ->
-                                  fromRolePO(
-                                      po,
-                                      
SupplierUtils.createSecurableObjectsSupplier(po),
-                                      
AuthorizationUtils.ofRoleNamespace(namespace.level(0))))
-                          .collect(Collectors.toList()));
-
+                  JsonUtils.anyFieldMapper().readValue(userPO.getAuditInfo(), 
AuditInfo.class));
+      if (!roleNames.isEmpty()) {
+        builder.withRoleNames(roleNames);
+      }
+      if (!roleIds.isEmpty()) {
+        builder.withRoleIds(roleIds);
+      }
       return builder.build();
     } catch (JsonProcessingException e) {
       throw new RuntimeException("Failed to deserialize json object:", e);
@@ -736,31 +732,30 @@ public class POConverters {
    * Convert {@link GroupPO} to {@link GroupEntity}
    *
    * @param groupPO GroupPO object to be converted
-   * @param rolePOsSupplier Supplier for the list of rolePO
+   * @param rolePOs list of rolePO
    * @param namespace Namespace object to be associated with the group
    * @return GroupEntity object from GroupPO object
    */
   public static GroupEntity fromGroupPO(
-      GroupPO groupPO, Supplier<List<RolePO>> rolePOsSupplier, Namespace 
namespace) {
+      GroupPO groupPO, List<RolePO> rolePOs, Namespace namespace) {
     try {
+      List<String> roleNames =
+          
rolePOs.stream().map(RolePO::getRoleName).collect(Collectors.toList());
+      List<Long> roleIds = 
rolePOs.stream().map(RolePO::getRoleId).collect(Collectors.toList());
+
       GroupEntity.Builder builder =
           GroupEntity.builder()
               .withId(groupPO.getGroupId())
               .withName(groupPO.getGroupName())
               .withNamespace(namespace)
               .withAuditInfo(
-                  JsonUtils.anyFieldMapper().readValue(groupPO.getAuditInfo(), 
AuditInfo.class))
-              .withRolesSupplier(
-                  () ->
-                      rolePOsSupplier.get().stream()
-                          .map(
-                              po ->
-                                  fromRolePO(
-                                      po,
-                                      
SupplierUtils.createSecurableObjectsSupplier(po),
-                                      
AuthorizationUtils.ofRoleNamespace(namespace.level(0))))
-                          .collect(Collectors.toList()));
-
+                  JsonUtils.anyFieldMapper().readValue(groupPO.getAuditInfo(), 
AuditInfo.class));
+      if (!roleNames.isEmpty()) {
+        builder.withRoleNames(roleNames);
+      }
+      if (!roleIds.isEmpty()) {
+        builder.withRoleIds(roleIds);
+      }
       return builder.build();
     } catch (JsonProcessingException e) {
       throw new RuntimeException("Failed to deserialize json object:", e);
@@ -923,16 +918,14 @@ public class POConverters {
   }
 
   public static RoleEntity fromRolePO(
-      RolePO rolePO,
-      Supplier<List<SecurableObject>> securableObjectsSupplier,
-      Namespace namespace) {
+      RolePO rolePO, List<SecurableObject> securableObjects, Namespace 
namespace) {
     try {
       return RoleEntity.builder()
           .withId(rolePO.getRoleId())
           .withName(rolePO.getRoleName())
           .withNamespace(namespace)
           
.withProperties(JsonUtils.anyFieldMapper().readValue(rolePO.getProperties(), 
Map.class))
-          .withSecurableObjectsSupplier(securableObjectsSupplier)
+          .withSecurableObjects(securableObjects)
           .withAuditInfo(
               JsonUtils.anyFieldMapper().readValue(rolePO.getAuditInfo(), 
AuditInfo.class))
           .build();
diff --git 
a/core/src/main/java/org/apache/gravitino/storage/relational/utils/SupplierUtils.java
 
b/core/src/main/java/org/apache/gravitino/storage/relational/utils/SupplierUtils.java
deleted file mode 100644
index 16c662c47..000000000
--- 
a/core/src/main/java/org/apache/gravitino/storage/relational/utils/SupplierUtils.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.gravitino.storage.relational.utils;
-
-import com.google.common.collect.Lists;
-import java.util.List;
-import java.util.function.Supplier;
-import org.apache.gravitino.MetadataObject;
-import org.apache.gravitino.authorization.SecurableObject;
-import org.apache.gravitino.storage.relational.po.GroupPO;
-import org.apache.gravitino.storage.relational.po.RolePO;
-import org.apache.gravitino.storage.relational.po.SecurableObjectPO;
-import org.apache.gravitino.storage.relational.po.UserPO;
-import org.apache.gravitino.storage.relational.service.MetadataObjectService;
-import org.apache.gravitino.storage.relational.service.RoleMetaService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/* This class is a utilization class for creating kinds of suppliers */
-public class SupplierUtils {
-
-  private static final Logger LOG = 
LoggerFactory.getLogger(SupplierUtils.class);
-
-  private SupplierUtils() {}
-
-  public static Supplier<List<RolePO>> createRolePOsSupplier(UserPO userPO) {
-    return new Supplier<List<RolePO>>() {
-      private List<RolePO> rolePOs;
-      private boolean waitToLoad = true;
-
-      @Override
-      public List<RolePO> get() {
-        if (waitToLoad) {
-          rolePOs = 
RoleMetaService.getInstance().listRolesByUserId(userPO.getUserId());
-          waitToLoad = false;
-        }
-
-        return rolePOs;
-      }
-    };
-  }
-
-  public static Supplier<List<RolePO>> createRolePOsSupplier(GroupPO groupPO) {
-    return new Supplier<List<RolePO>>() {
-      private List<RolePO> rolePOS;
-      private boolean waitToLoad = true;
-
-      @Override
-      public List<RolePO> get() {
-        if (waitToLoad) {
-          rolePOS = 
RoleMetaService.getInstance().listRolesByGroupId(groupPO.getGroupId());
-          waitToLoad = false;
-        }
-
-        return rolePOS;
-      }
-    };
-  }
-
-  public static Supplier<List<SecurableObject>> 
createSecurableObjectsSupplier(RolePO rolePO) {
-    return new Supplier<List<SecurableObject>>() {
-      private List<SecurableObject> securableObjects;
-
-      private boolean waitToLoad = true;
-
-      @Override
-      public List<SecurableObject> get() {
-        if (waitToLoad) {
-          List<SecurableObjectPO> securableObjectPOs =
-              
RoleMetaService.getInstance().listSecurableObjectsByRoleId(rolePO.getRoleId());
-
-          securableObjects = Lists.newArrayList();
-
-          for (SecurableObjectPO securableObjectPO : securableObjectPOs) {
-            String fullName =
-                MetadataObjectService.getMetadataObjectFullName(
-                    securableObjectPO.getType(), 
securableObjectPO.getMetadataObjectId());
-            if (fullName != null) {
-              securableObjects.add(
-                  POConverters.fromSecurableObjectPO(
-                      fullName,
-                      securableObjectPO,
-                      
MetadataObject.Type.valueOf(securableObjectPO.getType())));
-            } else {
-              LOG.info(
-                  "The securable object {} {} may be deleted",
-                  securableObjectPO.getMetadataObjectId(),
-                  securableObjectPO.getType());
-            }
-          }
-          waitToLoad = false;
-        }
-
-        return securableObjects;
-      }
-    };
-  }
-}
diff --git 
a/core/src/test/java/org/apache/gravitino/authorization/TestAccessControlManagerForPermissions.java
 
b/core/src/test/java/org/apache/gravitino/authorization/TestAccessControlManagerForPermissions.java
index 946cebf97..ce3c4e90c 100644
--- 
a/core/src/test/java/org/apache/gravitino/authorization/TestAccessControlManagerForPermissions.java
+++ 
b/core/src/test/java/org/apache/gravitino/authorization/TestAccessControlManagerForPermissions.java
@@ -157,7 +157,7 @@ public class TestAccessControlManagerForPermissions {
     String notExist = "not-exist";
 
     User user = accessControlManager.getUser(METALAKE, USER);
-    Assertions.assertTrue(user.roles().isEmpty());
+    Assertions.assertNull(user.roles());
 
     reset(authorizationPlugin);
 
diff --git 
a/core/src/test/java/org/apache/gravitino/authorization/TestOwnerManager.java 
b/core/src/test/java/org/apache/gravitino/authorization/TestOwnerManager.java
index 0b0b93ef0..83a562f64 100644
--- 
a/core/src/test/java/org/apache/gravitino/authorization/TestOwnerManager.java
+++ 
b/core/src/test/java/org/apache/gravitino/authorization/TestOwnerManager.java
@@ -125,7 +125,8 @@ public class TestOwnerManager {
         UserEntity.builder()
             .withId(idGenerator.nextId())
             .withName(USER)
-            .withRoles(Collections.emptyList())
+            .withRoleNames(Collections.emptyList())
+            .withRoleIds(Collections.emptyList())
             .withNamespace(AuthorizationUtils.ofUserNamespace(METALAKE))
             .withAuditInfo(audit)
             .build();
@@ -135,7 +136,8 @@ public class TestOwnerManager {
         GroupEntity.builder()
             .withId(idGenerator.nextId())
             .withName(GROUP)
-            .withRoles(Collections.emptyList())
+            .withRoleNames(Collections.emptyList())
+            .withRoleIds(Collections.emptyList())
             .withNamespace(AuthorizationUtils.ofUserNamespace(METALAKE))
             .withAuditInfo(audit)
             .build();
diff --git a/core/src/test/java/org/apache/gravitino/meta/TestEntity.java 
b/core/src/test/java/org/apache/gravitino/meta/TestEntity.java
index 2e24a7eb0..f4c32dca7 100644
--- a/core/src/test/java/org/apache/gravitino/meta/TestEntity.java
+++ b/core/src/test/java/org/apache/gravitino/meta/TestEntity.java
@@ -21,15 +21,10 @@ package org.apache.gravitino.meta;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Lists;
 import java.time.Instant;
-import java.util.Collections;
-import java.util.List;
 import java.util.Map;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.function.Supplier;
 import org.apache.gravitino.Catalog;
 import org.apache.gravitino.Field;
 import org.apache.gravitino.authorization.Privileges;
-import org.apache.gravitino.authorization.SecurableObject;
 import org.apache.gravitino.authorization.SecurableObjects;
 import org.apache.gravitino.file.Fileset;
 import org.junit.jupiter.api.Assertions;
@@ -242,48 +237,19 @@ public class TestEntity {
             .withId(userId)
             .withName(userName)
             .withAuditInfo(auditInfo)
-            .withRoles(
-                Lists.newArrayList(
-                    RoleEntity.builder()
-                        .withId(1L)
-                        .withName("role")
-                        .withAuditInfo(auditInfo)
-                        .build()))
+            .withRoleNames(Lists.newArrayList("role"))
             .build();
 
     Map<Field, Object> fields = testUserEntity.fields();
     Assertions.assertEquals(userId, fields.get(UserEntity.ID));
     Assertions.assertEquals(userName, fields.get(UserEntity.NAME));
     Assertions.assertEquals(auditInfo, fields.get(UserEntity.AUDIT_INFO));
-    Assertions.assertEquals(
-        Lists.newArrayList(
-            
RoleEntity.builder().withId(1L).withName("role").withAuditInfo(auditInfo).build()),
-        ((Supplier<List<RoleEntity>>) 
fields.get(UserEntity.ROLES_SUPPLIER)).get());
+    Assertions.assertEquals(Lists.newArrayList("role"), 
fields.get(UserEntity.ROLE_NAMES));
 
     UserEntity testUserEntityWithoutFields =
         
UserEntity.builder().withId(userId).withName(userName).withAuditInfo(auditInfo).build();
 
-    Assertions.assertTrue(testUserEntityWithoutFields.roles().isEmpty());
-
-    // Test lazily loading
-    AtomicBoolean hasCallRolesSupplier = new AtomicBoolean(false);
-
-    UserEntity userWithSupplier =
-        UserEntity.builder()
-            .withId(userId)
-            .withName(userName)
-            .withAuditInfo(auditInfo)
-            .withRolesSupplier(
-                () -> {
-                  hasCallRolesSupplier.set(true);
-                  return Collections.emptyList();
-                })
-            .build();
-
-    Assertions.assertFalse(hasCallRolesSupplier.get());
-
-    userWithSupplier.roles();
-    Assertions.assertTrue(hasCallRolesSupplier.get());
+    Assertions.assertNull(testUserEntityWithoutFields.roles());
   }
 
   @Test
@@ -292,48 +258,19 @@ public class TestEntity {
         GroupEntity.builder()
             .withId(groupId)
             .withName(groupName)
-            .withRoles(
-                Lists.newArrayList(
-                    RoleEntity.builder()
-                        .withId(1L)
-                        .withName("role")
-                        .withAuditInfo(auditInfo)
-                        .build()))
             .withAuditInfo(auditInfo)
+            .withRoleNames(Lists.newArrayList("role"))
             .build();
     Map<Field, Object> fields = group.fields();
     Assertions.assertEquals(groupId, fields.get(GroupEntity.ID));
     Assertions.assertEquals(groupName, fields.get(GroupEntity.NAME));
     Assertions.assertEquals(auditInfo, fields.get(GroupEntity.AUDIT_INFO));
-    Assertions.assertEquals(
-        Lists.newArrayList(
-            
RoleEntity.builder().withId(1L).withName("role").withAuditInfo(auditInfo).build()),
-        ((Supplier<List<RoleEntity>>) 
fields.get(GroupEntity.ROLES_SUPPLIER)).get());
+    Assertions.assertEquals(Lists.newArrayList("role"), 
fields.get(GroupEntity.ROLE_NAMES));
 
     GroupEntity groupWithoutFields =
         
GroupEntity.builder().withId(userId).withName(userName).withAuditInfo(auditInfo).build();
 
-    Assertions.assertTrue(groupWithoutFields.roles().isEmpty());
-
-    AtomicBoolean hasCallRolesSupplier = new AtomicBoolean(false);
-
-    // Test lazily loading
-    GroupEntity groupWithSupplier =
-        GroupEntity.builder()
-            .withId(userId)
-            .withName(userName)
-            .withAuditInfo(auditInfo)
-            .withRolesSupplier(
-                () -> {
-                  hasCallRolesSupplier.set(true);
-                  return Collections.emptyList();
-                })
-            .build();
-
-    Assertions.assertFalse(hasCallRolesSupplier.get());
-
-    groupWithSupplier.roles();
-    Assertions.assertTrue(hasCallRolesSupplier.get());
+    Assertions.assertNull(groupWithoutFields.roles());
   }
 
   @Test
@@ -359,8 +296,7 @@ public class TestEntity {
         Lists.newArrayList(
             SecurableObjects.ofCatalog(
                 catalogName, 
Lists.newArrayList(Privileges.UseCatalog.allow()))),
-        ((Supplier<List<SecurableObject>>) 
fields.get(RoleEntity.SECURABLE_OBJECTS_SUPPLIER))
-            .get());
+        fields.get(RoleEntity.SECURABLE_OBJECT));
 
     RoleEntity roleWithoutFields =
         RoleEntity.builder()
@@ -373,26 +309,6 @@ public class TestEntity {
                         catalogName, 
Lists.newArrayList(Privileges.UseCatalog.allow()))))
             .build();
     Assertions.assertNull(roleWithoutFields.properties());
-
-    // Test lazily loading
-    AtomicBoolean hasCallSecurableObjectsSupplier = new AtomicBoolean(false);
-
-    RoleEntity roleWithSupplier =
-        RoleEntity.builder()
-            .withId(userId)
-            .withName(userName)
-            .withAuditInfo(auditInfo)
-            .withSecurableObjectsSupplier(
-                () -> {
-                  hasCallSecurableObjectsSupplier.set(true);
-                  return null;
-                })
-            .build();
-
-    Assertions.assertFalse(hasCallSecurableObjectsSupplier.get());
-
-    roleWithSupplier.securableObjects();
-    Assertions.assertTrue(hasCallSecurableObjectsSupplier.get());
   }
 
   @Test
diff --git 
a/core/src/test/java/org/apache/gravitino/proto/TestEntityProtoSerDe.java 
b/core/src/test/java/org/apache/gravitino/proto/TestEntityProtoSerDe.java
index 226199a0d..1d4bfaa17 100644
--- a/core/src/test/java/org/apache/gravitino/proto/TestEntityProtoSerDe.java
+++ b/core/src/test/java/org/apache/gravitino/proto/TestEntityProtoSerDe.java
@@ -19,15 +19,23 @@
 package org.apache.gravitino.proto;
 
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
 import java.io.IOException;
 import java.time.Instant;
 import java.util.Map;
 import org.apache.gravitino.Catalog;
+import org.apache.gravitino.Entity;
 import org.apache.gravitino.EntitySerDe;
 import org.apache.gravitino.EntitySerDeFactory;
 import org.apache.gravitino.Namespace;
+import org.apache.gravitino.authorization.Privileges;
+import org.apache.gravitino.authorization.SecurableObject;
+import org.apache.gravitino.authorization.SecurableObjects;
 import org.apache.gravitino.file.Fileset;
+import org.apache.gravitino.meta.GroupEntity;
+import org.apache.gravitino.meta.RoleEntity;
 import org.apache.gravitino.meta.SchemaVersion;
+import org.apache.gravitino.meta.UserEntity;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
@@ -315,5 +323,110 @@ public class TestEntityProtoSerDe {
     Assertions.assertEquals(topicEntity1, topicEntityFromBytes1);
     Assertions.assertNull(topicEntityFromBytes1.comment());
     Assertions.assertNull(topicEntityFromBytes1.properties());
+
+    // Test UserEntity
+    Namespace userNamespace =
+        Namespace.of("metalake", Entity.SYSTEM_CATALOG_RESERVED_NAME, 
Entity.USER_SCHEMA_NAME);
+    Long userId = 1L;
+    String userName = "user";
+    UserEntity userEntity =
+        UserEntity.builder()
+            .withId(userId)
+            .withName(userName)
+            .withNamespace(userNamespace)
+            .withAuditInfo(auditInfo)
+            .withRoleNames(Lists.newArrayList("role"))
+            .withRoleIds(Lists.newArrayList(1L))
+            .build();
+    byte[] userBytes = protoEntitySerDe.serialize(userEntity);
+    UserEntity userEntityFromBytes =
+        protoEntitySerDe.deserialize(userBytes, UserEntity.class, 
userNamespace);
+    Assertions.assertEquals(userEntity, userEntityFromBytes);
+
+    UserEntity userEntityWithoutFields =
+        UserEntity.builder()
+            .withId(userId)
+            .withName(userName)
+            .withNamespace(userNamespace)
+            .withAuditInfo(auditInfo)
+            .build();
+    userBytes = protoEntitySerDe.serialize(userEntityWithoutFields);
+    userEntityFromBytes = protoEntitySerDe.deserialize(userBytes, 
UserEntity.class, userNamespace);
+    Assertions.assertEquals(userEntityWithoutFields, userEntityFromBytes);
+    Assertions.assertNull(userEntityWithoutFields.roles());
+    Assertions.assertNull(userEntityWithoutFields.roleIds());
+
+    // Test GroupEntity
+    Namespace groupNamespace =
+        Namespace.of("metalake", Entity.SYSTEM_CATALOG_RESERVED_NAME, 
Entity.GROUP_SCHEMA_NAME);
+    Long groupId = 1L;
+    String groupName = "group";
+
+    GroupEntity group =
+        GroupEntity.builder()
+            .withId(groupId)
+            .withName(groupName)
+            .withNamespace(groupNamespace)
+            .withAuditInfo(auditInfo)
+            .withRoleNames(Lists.newArrayList("role"))
+            .withRoleIds(Lists.newArrayList(1L))
+            .build();
+    byte[] groupBytes = protoEntitySerDe.serialize(group);
+    GroupEntity groupFromBytes =
+        protoEntitySerDe.deserialize(groupBytes, GroupEntity.class, 
groupNamespace);
+    Assertions.assertEquals(group, groupFromBytes);
+
+    GroupEntity groupWithoutFields =
+        GroupEntity.builder()
+            .withId(groupId)
+            .withName(groupName)
+            .withNamespace(groupNamespace)
+            .withAuditInfo(auditInfo)
+            .build();
+    groupBytes = protoEntitySerDe.serialize(groupWithoutFields);
+    groupFromBytes = protoEntitySerDe.deserialize(groupBytes, 
GroupEntity.class, groupNamespace);
+    Assertions.assertEquals(groupWithoutFields, groupFromBytes);
+    Assertions.assertNull(groupWithoutFields.roles());
+    Assertions.assertNull(groupWithoutFields.roleIds());
+
+    // Test RoleEntity
+    Namespace roleNamespace =
+        Namespace.of("metalake", Entity.SYSTEM_CATALOG_RESERVED_NAME, 
Entity.ROLE_SCHEMA_NAME);
+    Long roleId = 1L;
+    String roleName = "testRole";
+    String anotherCatalogName = "anotherCatalog";
+    SecurableObject securableObject =
+        SecurableObjects.ofCatalog(
+            catalogName,
+            Lists.newArrayList(Privileges.UseCatalog.allow(), 
Privileges.CreateSchema.deny()));
+    SecurableObject anotherSecurableObject =
+        SecurableObjects.ofCatalog(
+            anotherCatalogName, 
Lists.newArrayList(Privileges.UseCatalog.allow()));
+
+    RoleEntity roleEntity =
+        RoleEntity.builder()
+            .withId(roleId)
+            .withName(roleName)
+            .withNamespace(roleNamespace)
+            .withAuditInfo(auditInfo)
+            .withSecurableObjects(Lists.newArrayList(securableObject, 
anotherSecurableObject))
+            .withProperties(props)
+            .build();
+    byte[] roleBytes = protoEntitySerDe.serialize(roleEntity);
+    RoleEntity roleFromBytes =
+        protoEntitySerDe.deserialize(roleBytes, RoleEntity.class, 
roleNamespace);
+    Assertions.assertEquals(roleEntity, roleFromBytes);
+
+    RoleEntity roleWithoutFields =
+        RoleEntity.builder()
+            .withId(1L)
+            .withName(roleName)
+            .withNamespace(roleNamespace)
+            .withAuditInfo(auditInfo)
+            .withSecurableObjects(Lists.newArrayList(securableObject, 
anotherSecurableObject))
+            .build();
+    roleBytes = protoEntitySerDe.serialize(roleWithoutFields);
+    roleFromBytes = protoEntitySerDe.deserialize(roleBytes, RoleEntity.class, 
roleNamespace);
+    Assertions.assertEquals(roleWithoutFields, roleFromBytes);
   }
 }
diff --git 
a/core/src/test/java/org/apache/gravitino/storage/TestEntityStorage.java 
b/core/src/test/java/org/apache/gravitino/storage/TestEntityStorage.java
index ecb13c06b..46bb5fb93 100644
--- a/core/src/test/java/org/apache/gravitino/storage/TestEntityStorage.java
+++ b/core/src/test/java/org/apache/gravitino/storage/TestEntityStorage.java
@@ -42,7 +42,6 @@ import java.sql.SQLException;
 import java.sql.Statement;
 import java.time.Instant;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
 import java.util.UUID;
 import org.apache.commons.io.FileUtils;
@@ -1271,7 +1270,7 @@ public class TestEntityStorage {
         .withNamespace(AuthorizationUtils.ofUserNamespace(metalake))
         .withName(name)
         .withAuditInfo(auditInfo)
-        .withRoles(Collections.emptyList())
+        .withRoleNames(null)
         .build();
   }
 
@@ -1282,7 +1281,7 @@ public class TestEntityStorage {
         .withNamespace(AuthorizationUtils.ofGroupNamespace(metalake))
         .withName(name)
         .withAuditInfo(auditInfo)
-        .withRoles(Collections.emptyList())
+        .withRoleNames(null)
         .build();
   }
 
diff --git 
a/core/src/test/java/org/apache/gravitino/storage/memory/TestMemoryEntityStore.java
 
b/core/src/test/java/org/apache/gravitino/storage/memory/TestMemoryEntityStore.java
index 4d41d2f25..7cff7bcc5 100644
--- 
a/core/src/test/java/org/apache/gravitino/storage/memory/TestMemoryEntityStore.java
+++ 
b/core/src/test/java/org/apache/gravitino/storage/memory/TestMemoryEntityStore.java
@@ -22,7 +22,6 @@ import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import java.io.IOException;
 import java.time.Instant;
-import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.locks.Lock;
@@ -225,7 +224,7 @@ public class TestMemoryEntityStore {
             .withName("user")
             .withNamespace(Namespace.of("metalake", "catalog", "db"))
             .withAuditInfo(auditInfo)
-            .withRoles(Collections.emptyList())
+            .withRoleNames(null)
             .build();
 
     GroupEntity groupEntity =
@@ -234,7 +233,7 @@ public class TestMemoryEntityStore {
             .withName("group")
             .withNamespace(AuthorizationUtils.ofGroupNamespace("metalake"))
             .withAuditInfo(auditInfo)
-            .withRoles(Collections.emptyList())
+            .withRoleNames(null)
             .build();
 
     RoleEntity roleEntity =
diff --git 
a/core/src/test/java/org/apache/gravitino/storage/relational/TestJDBCBackend.java
 
b/core/src/test/java/org/apache/gravitino/storage/relational/TestJDBCBackend.java
index d72f542fa..26430d2fb 100644
--- 
a/core/src/test/java/org/apache/gravitino/storage/relational/TestJDBCBackend.java
+++ 
b/core/src/test/java/org/apache/gravitino/storage/relational/TestJDBCBackend.java
@@ -45,7 +45,6 @@ import java.sql.SQLException;
 import java.sql.Statement;
 import java.time.Instant;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -601,7 +600,8 @@ public class TestJDBCBackend {
             AuthorizationUtils.ofUserNamespace("metalake"),
             "user",
             auditInfo,
-            Lists.newArrayList(role));
+            Lists.newArrayList(role.name()),
+            Lists.newArrayList(role.id()));
     backend.insert(user, false);
 
     GroupEntity group =
@@ -610,7 +610,8 @@ public class TestJDBCBackend {
             AuthorizationUtils.ofGroupNamespace("metalake"),
             "group",
             auditInfo,
-            Lists.newArrayList(role));
+            Lists.newArrayList(role.name()),
+            Lists.newArrayList(role.id()));
     backend.insert(group, false);
 
     TagEntity tag =
@@ -687,7 +688,8 @@ public class TestJDBCBackend {
             AuthorizationUtils.ofUserNamespace("another-metalake"),
             "another-user",
             auditInfo,
-            Lists.newArrayList(anotherRole));
+            Lists.newArrayList(anotherRole.name()),
+            Lists.newArrayList(anotherRole.id()));
     backend.insert(anotherUser, false);
 
     GroupEntity anotherGroup =
@@ -696,7 +698,8 @@ public class TestJDBCBackend {
             AuthorizationUtils.ofGroupNamespace("another-metalake"),
             "another-group",
             auditInfo,
-            Lists.newArrayList(anotherRole));
+            Lists.newArrayList(anotherRole.name()),
+            Lists.newArrayList(anotherRole.id()));
     backend.insert(anotherGroup, false);
 
     TagEntity anotherTagEntity =
@@ -1109,7 +1112,8 @@ public class TestJDBCBackend {
         .withId(id)
         .withName(name)
         .withNamespace(namespace)
-        .withRoles(Collections.emptyList())
+        .withRoleNames(null)
+        .withRoleIds(null)
         .withAuditInfo(auditInfo)
         .build();
   }
@@ -1119,12 +1123,14 @@ public class TestJDBCBackend {
       Namespace namespace,
       String name,
       AuditInfo auditInfo,
-      List<RoleEntity> roleEntities) {
+      List<String> roleNames,
+      List<Long> roleIds) {
     return UserEntity.builder()
         .withId(id)
         .withName(name)
         .withNamespace(namespace)
-        .withRoles(roleEntities)
+        .withRoleNames(roleNames)
+        .withRoleIds(roleIds)
         .withAuditInfo(auditInfo)
         .build();
   }
@@ -1150,18 +1156,25 @@ public class TestJDBCBackend {
         .withId(id)
         .withName(name)
         .withNamespace(namespace)
-        .withRoles(Collections.emptyList())
+        .withRoleNames(null)
+        .withRoleIds(null)
         .withAuditInfo(auditInfo)
         .build();
   }
 
   public static GroupEntity createGroupEntity(
-      Long id, Namespace namespace, String name, AuditInfo auditInfo, 
List<RoleEntity> roles) {
+      Long id,
+      Namespace namespace,
+      String name,
+      AuditInfo auditInfo,
+      List<String> roleNames,
+      List<Long> roleIds) {
     return GroupEntity.builder()
         .withId(id)
         .withName(name)
         .withNamespace(namespace)
-        .withRoles(roles)
+        .withRoleNames(roleNames)
+        .withRoleIds(roleIds)
         .withAuditInfo(auditInfo)
         .build();
   }
diff --git 
a/core/src/test/java/org/apache/gravitino/storage/relational/service/TestGroupMetaService.java
 
b/core/src/test/java/org/apache/gravitino/storage/relational/service/TestGroupMetaService.java
index d6b330950..22246ba0c 100644
--- 
a/core/src/test/java/org/apache/gravitino/storage/relational/service/TestGroupMetaService.java
+++ 
b/core/src/test/java/org/apache/gravitino/storage/relational/service/TestGroupMetaService.java
@@ -30,7 +30,6 @@ import java.time.Instant;
 import java.util.List;
 import java.util.Optional;
 import java.util.function.Function;
-import java.util.stream.Collectors;
 import org.apache.gravitino.Entity;
 import org.apache.gravitino.EntityAlreadyExistsException;
 import org.apache.gravitino.Namespace;
@@ -111,11 +110,13 @@ class TestGroupMetaService extends TestJDBCBackend {
             AuthorizationUtils.ofGroupNamespace(metalakeName),
             "group2",
             auditInfo,
-            Lists.newArrayList(role1, role2));
+            Lists.newArrayList(role1.name(), role2.name()),
+            Lists.newArrayList(role1.id(), role2.id()));
     groupMetaService.insertGroup(group2, false);
     GroupEntity actualGroup = 
groupMetaService.getGroupByIdentifier(group2.nameIdentifier());
     Assertions.assertEquals(group2.name(), actualGroup.name());
-    Assertions.assertEquals(Sets.newHashSet(group2.roles()), 
Sets.newHashSet(actualGroup.roles()));
+    Assertions.assertEquals(
+        Sets.newHashSet(group2.roleNames()), 
Sets.newHashSet(actualGroup.roleNames()));
   }
 
   @Test
@@ -193,11 +194,13 @@ class TestGroupMetaService extends TestJDBCBackend {
             AuthorizationUtils.ofGroupNamespace(metalakeName),
             "group2",
             auditInfo,
-            Lists.newArrayList(role1, role2));
+            Lists.newArrayList(role1.name(), role2.name()),
+            Lists.newArrayList(role1.id(), role2.id()));
     Assertions.assertDoesNotThrow(() -> groupMetaService.insertGroup(group2, 
false));
     GroupEntity actualGroup = 
groupMetaService.getGroupByIdentifier(group2.nameIdentifier());
     Assertions.assertEquals(group2.name(), actualGroup.name());
-    Assertions.assertEquals(Sets.newHashSet(group2.roles()), 
Sets.newHashSet(actualGroup.roles()));
+    Assertions.assertEquals(
+        Sets.newHashSet(group2.roleNames()), 
Sets.newHashSet(actualGroup.roleNames()));
 
     // insert duplicate group with roles
     GroupEntity group2Exist =
@@ -216,16 +219,17 @@ class TestGroupMetaService extends TestJDBCBackend {
             AuthorizationUtils.ofGroupNamespace(metalakeName),
             "group2Overwrite",
             auditInfo,
-            Lists.newArrayList(role1, role2));
+            Lists.newArrayList(role1.name(), role2.name()),
+            Lists.newArrayList(role1.id(), role2.id()));
     Assertions.assertDoesNotThrow(() -> 
groupMetaService.insertGroup(group2Overwrite, true));
 
     GroupEntity actualOverwriteGroup2 =
         
groupMetaService.getGroupByIdentifier(group2Overwrite.nameIdentifier());
     Assertions.assertEquals("group2Overwrite", actualOverwriteGroup2.name());
-    Assertions.assertEquals(2, actualOverwriteGroup2.roles().size());
+    Assertions.assertEquals(2, actualOverwriteGroup2.roleNames().size());
     Assertions.assertEquals(
         Sets.newHashSet(role1.name(), role2.name()),
-        Sets.newHashSet(actualOverwriteGroup2.roles()));
+        Sets.newHashSet(actualOverwriteGroup2.roleNames()));
 
     // insert overwrite user with 1 role
     RoleEntity role3 =
@@ -242,14 +246,15 @@ class TestGroupMetaService extends TestJDBCBackend {
             AuthorizationUtils.ofUserNamespace(metalakeName),
             "group3Overwrite",
             auditInfo,
-            Lists.newArrayList(role3));
+            Lists.newArrayList(role3.name()),
+            Lists.newArrayList(role3.id()));
     Assertions.assertDoesNotThrow(() -> 
groupMetaService.insertGroup(group3Overwrite, true));
 
     GroupEntity actualOverwriteGroup3 =
         
groupMetaService.getGroupByIdentifier(group3Overwrite.nameIdentifier());
     Assertions.assertEquals("group3Overwrite", actualOverwriteGroup3.name());
-    Assertions.assertEquals(1, actualOverwriteGroup3.roles().size());
-    Assertions.assertEquals("role3", actualOverwriteGroup3.roles().get(0));
+    Assertions.assertEquals(1, actualOverwriteGroup3.roleNames().size());
+    Assertions.assertEquals("role3", actualOverwriteGroup3.roleNames().get(0));
 
     // insert overwrite user with 0 roles
     GroupEntity group4Overwrite =
@@ -263,7 +268,7 @@ class TestGroupMetaService extends TestJDBCBackend {
     GroupEntity actualOverwriteGroup4 =
         
groupMetaService.getGroupByIdentifier(group4Overwrite.nameIdentifier());
     Assertions.assertEquals("group4Overwrite", actualOverwriteGroup4.name());
-    Assertions.assertTrue(actualOverwriteGroup4.roles().isEmpty());
+    Assertions.assertNull(actualOverwriteGroup4.roleNames());
   }
 
   @Test
@@ -336,7 +341,8 @@ class TestGroupMetaService extends TestJDBCBackend {
             AuthorizationUtils.ofGroupNamespace(metalakeName),
             "group2",
             auditInfo,
-            Lists.newArrayList(role1, role2));
+            Lists.newArrayList(role1.name(), role2.name()),
+            Lists.newArrayList(role1.id(), role2.id()));
     groupMetaService.insertGroup(group2, false);
     List<RolePO> rolePOs =
         SessionUtils.doWithCommitAndFetchResult(
@@ -344,7 +350,8 @@ class TestGroupMetaService extends TestJDBCBackend {
     Assertions.assertEquals(2, rolePOs.size());
     GroupEntity actualGroup = 
groupMetaService.getGroupByIdentifier(group2.nameIdentifier());
     Assertions.assertEquals(group2.name(), actualGroup.name());
-    Assertions.assertEquals(Sets.newHashSet(group2.roles()), 
Sets.newHashSet(actualGroup.roles()));
+    Assertions.assertEquals(
+        Sets.newHashSet(group2.roleNames()), 
Sets.newHashSet(actualGroup.roleNames()));
 
     
Assertions.assertTrue(groupMetaService.deleteGroup(group2.nameIdentifier()));
     Assertions.assertThrows(
@@ -393,11 +400,13 @@ class TestGroupMetaService extends TestJDBCBackend {
             AuthorizationUtils.ofGroupNamespace(metalakeName),
             "group1",
             auditInfo,
-            Lists.newArrayList(role1, role2));
+            Lists.newArrayList(role1.name(), role2.name()),
+            Lists.newArrayList(role1.id(), role2.id()));
     groupMetaService.insertGroup(group1, false);
     GroupEntity actualGroup = 
groupMetaService.getGroupByIdentifier(group1.nameIdentifier());
     Assertions.assertEquals(group1.name(), actualGroup.name());
-    Assertions.assertEquals(Sets.newHashSet(group1.roles()), 
Sets.newHashSet(actualGroup.roles()));
+    Assertions.assertEquals(
+        Sets.newHashSet(group1.roleNames()), 
Sets.newHashSet(actualGroup.roleNames()));
 
     RoleEntity role3 =
         createRoleEntity(
@@ -419,14 +428,17 @@ class TestGroupMetaService extends TestJDBCBackend {
                   .withLastModifiedTime(Instant.now())
                   .build();
 
-          List<RoleEntity> roleEntities = 
Lists.newArrayList(group.roleEntities());
-          roleEntities.add(role3);
+          List<String> roleNames = Lists.newArrayList(group.roleNames());
+          List<Long> roleIds = Lists.newArrayList(group.roleIds());
+          roleNames.add(role3.name());
+          roleIds.add(role3.id());
 
           return GroupEntity.builder()
               .withNamespace(group.namespace())
               .withId(group.id())
               .withName(group.name())
-              .withRoles(roleEntities)
+              .withRoleNames(roleNames)
+              .withRoleIds(roleIds)
               .withAuditInfo(updateAuditInfo)
               .build();
         };
@@ -437,10 +449,9 @@ class TestGroupMetaService extends TestJDBCBackend {
     Assertions.assertEquals(group1.id(), grantGroup.id());
     Assertions.assertEquals(group1.name(), grantGroup.name());
     Assertions.assertEquals(
-        Sets.newHashSet("role1", "role2", "role3"), 
Sets.newHashSet(grantGroup.roles()));
+        Sets.newHashSet("role1", "role2", "role3"), 
Sets.newHashSet(grantGroup.roleNames()));
     Assertions.assertEquals(
-        Sets.newHashSet(role1.id(), role2.id(), role3.id()),
-        
grantGroup.roleEntities().stream().map(RoleEntity::id).collect(Collectors.toSet()));
+        Sets.newHashSet(role1.id(), role2.id(), role3.id()), 
Sets.newHashSet(grantGroup.roleIds()));
     Assertions.assertEquals("creator", grantGroup.auditInfo().creator());
     Assertions.assertEquals("grantGroup", 
grantGroup.auditInfo().lastModifier());
 
@@ -455,16 +466,17 @@ class TestGroupMetaService extends TestJDBCBackend {
                   .withLastModifiedTime(Instant.now())
                   .build();
 
-          List<RoleEntity> roleEntities = 
Lists.newArrayList(group.roleEntities());
-          List<String> roleNames =
-              
roleEntities.stream().map(RoleEntity::name).collect(Collectors.toList());
-          roleEntities.remove(roleNames.indexOf("role2"));
+          List<String> roleNames = Lists.newArrayList(group.roleNames());
+          List<Long> roleIds = Lists.newArrayList(group.roleIds());
+          roleIds.remove(roleNames.indexOf("role2"));
+          roleNames.remove("role2");
 
           return GroupEntity.builder()
               .withNamespace(group.namespace())
               .withId(group.id())
               .withName(group.name())
-              .withRoles(roleEntities)
+              .withRoleNames(roleNames)
+              .withRoleIds(roleIds)
               .withAuditInfo(updateAuditInfo)
               .build();
         };
@@ -475,10 +487,9 @@ class TestGroupMetaService extends TestJDBCBackend {
     Assertions.assertEquals(group1.id(), revokeGroup.id());
     Assertions.assertEquals(group1.name(), revokeGroup.name());
     Assertions.assertEquals(
-        Sets.newHashSet("role1", "role3"), 
Sets.newHashSet(revokeGroup.roles()));
+        Sets.newHashSet("role1", "role3"), 
Sets.newHashSet(revokeGroup.roleNames()));
     Assertions.assertEquals(
-        Sets.newHashSet(role1.id(), role3.id()),
-        
revokeGroup.roleEntities().stream().map(RoleEntity::id).collect(Collectors.toSet()));
+        Sets.newHashSet(role1.id(), role3.id()), 
Sets.newHashSet(revokeGroup.roleIds()));
     Assertions.assertEquals("creator", revokeGroup.auditInfo().creator());
     Assertions.assertEquals("revokeGroup", 
revokeGroup.auditInfo().lastModifier());
 
@@ -502,16 +513,19 @@ class TestGroupMetaService extends TestJDBCBackend {
                   .withLastModifiedTime(Instant.now())
                   .build();
 
-          List<String> roleNames = Lists.newArrayList(group.roles());
-          List<RoleEntity> roleEntities = 
Lists.newArrayList(group.roleEntities());
-          roleEntities.remove(roleNames.indexOf("role3"));
-          roleEntities.add(role4);
+          List<String> roleNames = Lists.newArrayList(group.roleNames());
+          List<Long> roleIds = Lists.newArrayList(group.roleIds());
+          roleIds.remove(roleNames.indexOf("role3"));
+          roleNames.remove("role3");
+          roleIds.add(role4.id());
+          roleNames.add(role4.name());
 
           return GroupEntity.builder()
               .withNamespace(group.namespace())
               .withId(group.id())
               .withName(group.name())
-              .withRoles(roleEntities)
+              .withRoleNames(roleNames)
+              .withRoleIds(roleIds)
               .withAuditInfo(updateAuditInfo)
               .build();
         };
@@ -522,10 +536,9 @@ class TestGroupMetaService extends TestJDBCBackend {
     Assertions.assertEquals(group1.id(), grantRevokeGroup.id());
     Assertions.assertEquals(group1.name(), grantRevokeGroup.name());
     Assertions.assertEquals(
-        Sets.newHashSet("role1", "role4"), 
Sets.newHashSet(grantRevokeGroup.roles()));
+        Sets.newHashSet("role1", "role4"), 
Sets.newHashSet(grantRevokeGroup.roleNames()));
     Assertions.assertEquals(
-        Sets.newHashSet(role1.id(), role4.id()),
-        
grantRevokeGroup.roleEntities().stream().map(RoleEntity::id).collect(Collectors.toSet()));
+        Sets.newHashSet(role1.id(), role4.id()), 
Sets.newHashSet(grantRevokeGroup.roleIds()));
     Assertions.assertEquals("creator", grantRevokeGroup.auditInfo().creator());
     Assertions.assertEquals("grantRevokeUser", 
grantRevokeGroup.auditInfo().lastModifier());
 
@@ -540,13 +553,15 @@ class TestGroupMetaService extends TestJDBCBackend {
                   .withLastModifiedTime(Instant.now())
                   .build();
 
-          List<RoleEntity> roleEntities = 
Lists.newArrayList(group.roleEntities());
+          List<String> roleNames = Lists.newArrayList(group.roleNames());
+          List<Long> roleIds = Lists.newArrayList(group.roleIds());
 
           return GroupEntity.builder()
               .withNamespace(group.namespace())
               .withId(group.id())
               .withName(group.name())
-              .withRoles(roleEntities)
+              .withRoleNames(roleNames)
+              .withRoleIds(roleIds)
               .withAuditInfo(updateAuditInfo)
               .build();
         };
@@ -556,10 +571,9 @@ class TestGroupMetaService extends TestJDBCBackend {
     Assertions.assertEquals(group1.id(), noUpdaterGroup.id());
     Assertions.assertEquals(group1.name(), noUpdaterGroup.name());
     Assertions.assertEquals(
-        Sets.newHashSet("role1", "role4"), 
Sets.newHashSet(noUpdaterGroup.roles()));
+        Sets.newHashSet("role1", "role4"), 
Sets.newHashSet(noUpdaterGroup.roleNames()));
     Assertions.assertEquals(
-        Sets.newHashSet(role1.id(), role4.id()),
-        
noUpdaterGroup.roleEntities().stream().map(RoleEntity::id).collect(Collectors.toSet()));
+        Sets.newHashSet(role1.id(), role4.id()), 
Sets.newHashSet(noUpdaterGroup.roleIds()));
     Assertions.assertEquals("creator", noUpdaterGroup.auditInfo().creator());
     Assertions.assertEquals("grantRevokeUser", 
noUpdaterGroup.auditInfo().lastModifier());
 
@@ -567,7 +581,7 @@ class TestGroupMetaService extends TestJDBCBackend {
     RoleMetaService.getInstance().deleteRole(role1.nameIdentifier());
     GroupEntity groupEntity =
         
GroupMetaService.getInstance().getGroupByIdentifier(group1.nameIdentifier());
-    Assertions.assertEquals(Sets.newHashSet("role4"), 
Sets.newHashSet(groupEntity.roles()));
+    Assertions.assertEquals(Sets.newHashSet("role4"), 
Sets.newHashSet(groupEntity.roleNames()));
   }
 
   @Test
@@ -615,14 +629,16 @@ class TestGroupMetaService extends TestJDBCBackend {
             AuthorizationUtils.ofGroupNamespace(metalakeName),
             "group1",
             auditInfo,
-            Lists.newArrayList(role1, role2));
+            Lists.newArrayList(role1.name(), role2.name()),
+            Lists.newArrayList(role1.id(), role2.id()));
     GroupEntity group2 =
         createGroupEntity(
             RandomIdGenerator.INSTANCE.nextId(),
             AuthorizationUtils.ofGroupNamespace(metalakeName),
             "group2",
             auditInfo,
-            Lists.newArrayList(role3));
+            Lists.newArrayList(role3.name()),
+            Lists.newArrayList(role3.id()));
     groupMetaService.insertGroup(group1, false);
     groupMetaService.insertGroup(group2, false);
 
@@ -694,14 +710,16 @@ class TestGroupMetaService extends TestJDBCBackend {
             AuthorizationUtils.ofGroupNamespace(metalakeName),
             "group1",
             auditInfo,
-            Lists.newArrayList(role1, role2));
+            Lists.newArrayList(role1.name(), role2.name()),
+            Lists.newArrayList(role1.id(), role2.id()));
     GroupEntity group2 =
         createGroupEntity(
             RandomIdGenerator.INSTANCE.nextId(),
             AuthorizationUtils.ofGroupNamespace(metalakeName),
             "group2",
             auditInfo,
-            Lists.newArrayList(role3));
+            Lists.newArrayList(role3.name()),
+            Lists.newArrayList(role3.id()));
     groupMetaService.insertGroup(group1, false);
     groupMetaService.insertGroup(group2, false);
 
@@ -764,28 +782,32 @@ class TestGroupMetaService extends TestJDBCBackend {
             AuthorizationUtils.ofUserNamespace(metalakeName),
             "group1",
             auditInfo,
-            Lists.newArrayList(role1, role2));
+            Lists.newArrayList(role1.name(), role2.name()),
+            Lists.newArrayList(role1.id(), role2.id()));
     GroupEntity group2 =
         createGroupEntity(
             RandomIdGenerator.INSTANCE.nextId(),
             AuthorizationUtils.ofUserNamespace(metalakeName),
             "group2",
             auditInfo,
-            Lists.newArrayList(role1, role2));
+            Lists.newArrayList(role1.name(), role2.name()),
+            Lists.newArrayList(role1.id(), role2.id()));
     GroupEntity group3 =
         createGroupEntity(
             RandomIdGenerator.INSTANCE.nextId(),
             AuthorizationUtils.ofUserNamespace(metalakeName),
             "group3",
             auditInfo,
-            Lists.newArrayList(role1, role2));
+            Lists.newArrayList(role1.name(), role2.name()),
+            Lists.newArrayList(role1.id(), role2.id()));
     GroupEntity group4 =
         createGroupEntity(
             RandomIdGenerator.INSTANCE.nextId(),
             AuthorizationUtils.ofUserNamespace(metalakeName),
             "group4",
             auditInfo,
-            Lists.newArrayList(role1, role2));
+            Lists.newArrayList(role1.name(), role2.name()),
+            Lists.newArrayList(role1.id(), role2.id()));
     groupMetaService.insertGroup(group1, false);
     groupMetaService.insertGroup(group2, false);
     groupMetaService.insertGroup(group3, false);
diff --git 
a/core/src/test/java/org/apache/gravitino/storage/relational/service/TestRoleMetaService.java
 
b/core/src/test/java/org/apache/gravitino/storage/relational/service/TestRoleMetaService.java
index 1db24de1c..d811b8b59 100644
--- 
a/core/src/test/java/org/apache/gravitino/storage/relational/service/TestRoleMetaService.java
+++ 
b/core/src/test/java/org/apache/gravitino/storage/relational/service/TestRoleMetaService.java
@@ -301,36 +301,41 @@ class TestRoleMetaService extends TestJDBCBackend {
             AuthorizationUtils.ofGroupNamespace(metalakeName),
             "group1",
             auditInfo,
-            Lists.newArrayList(role2));
+            Lists.newArrayList(role2.name()),
+            Lists.newArrayList(role2.id()));
     GroupEntity group2 =
         createGroupEntity(
             RandomIdGenerator.INSTANCE.nextId(),
             AuthorizationUtils.ofGroupNamespace(metalakeName),
             "group2",
             auditInfo,
-            Lists.newArrayList(role2));
+            Lists.newArrayList(role2.name()),
+            Lists.newArrayList(role2.id()));
     groupMetaService.insertGroup(group1, false);
     groupMetaService.insertGroup(group2, false);
     Assertions.assertEquals(
         group1.name(), 
groupMetaService.getGroupByIdentifier(group1.nameIdentifier()).name());
     Assertions.assertEquals(
-        group1.roles(), 
groupMetaService.getGroupByIdentifier(group1.nameIdentifier()).roles());
+        group1.roleNames(),
+        
groupMetaService.getGroupByIdentifier(group1.nameIdentifier()).roleNames());
     Assertions.assertEquals(
         group2.name(), 
groupMetaService.getGroupByIdentifier(group2.nameIdentifier()).name());
     Assertions.assertEquals(
-        group2.roles(), 
groupMetaService.getGroupByIdentifier(group2.nameIdentifier()).roles());
+        group2.roleNames(),
+        
groupMetaService.getGroupByIdentifier(group2.nameIdentifier()).roleNames());
     UserEntity user1 =
         createUserEntity(
             RandomIdGenerator.INSTANCE.nextId(),
             AuthorizationUtils.ofUserNamespace(metalakeName),
             "user1",
             auditInfo,
-            Lists.newArrayList(role2));
+            Lists.newArrayList(role2.name()),
+            Lists.newArrayList(role2.id()));
     userMetaService.insertUser(user1, false);
     Assertions.assertEquals(
         user1.name(), 
userMetaService.getUserByIdentifier(user1.nameIdentifier()).name());
     Assertions.assertEquals(
-        user1.roles(), 
userMetaService.getUserByIdentifier(user1.nameIdentifier()).roles());
+        user1.roleNames(), 
userMetaService.getUserByIdentifier(user1.nameIdentifier()).roleNames());
 
     Assertions.assertTrue(roleMetaService.deleteRole(role2.nameIdentifier()));
     Assertions.assertThrows(
@@ -429,14 +434,16 @@ class TestRoleMetaService extends TestJDBCBackend {
             AuthorizationUtils.ofGroupNamespace(metalakeName),
             "group1",
             auditInfo,
-            Lists.newArrayList(role1, role2));
+            Lists.newArrayList(role1.name(), role2.name()),
+            Lists.newArrayList(role1.id(), role2.id()));
     UserEntity user1 =
         createUserEntity(
             RandomIdGenerator.INSTANCE.nextId(),
             AuthorizationUtils.ofUserNamespace(metalakeName),
             "user1",
             auditInfo,
-            Lists.newArrayList(role1, role2));
+            Lists.newArrayList(role1.name(), role2.name()),
+            Lists.newArrayList(role1.id(), role2.id()));
     roleMetaService.insertRole(role1, false);
     roleMetaService.insertRole(role2, false);
     groupMetaService.insertGroup(group1, false);
@@ -539,14 +546,16 @@ class TestRoleMetaService extends TestJDBCBackend {
             AuthorizationUtils.ofGroupNamespace(metalakeName),
             "group1",
             auditInfo,
-            Lists.newArrayList(role1, role2));
+            Lists.newArrayList(role1.name(), role2.name()),
+            Lists.newArrayList(role1.id(), role2.id()));
     UserEntity user1 =
         createUserEntity(
             RandomIdGenerator.INSTANCE.nextId(),
             AuthorizationUtils.ofUserNamespace(metalakeName),
             "user1",
             auditInfo,
-            Lists.newArrayList(role1, role2));
+            Lists.newArrayList(role1.name(), role2.name()),
+            Lists.newArrayList(role1.id(), role2.id()));
     roleMetaService.insertRole(role1, false);
     roleMetaService.insertRole(role2, false);
     groupMetaService.insertGroup(group1, false);
@@ -649,7 +658,8 @@ class TestRoleMetaService extends TestJDBCBackend {
             AuthorizationUtils.ofUserNamespace(metalakeName),
             "user1",
             auditInfo,
-            Lists.newArrayList(role1, role2));
+            Lists.newArrayList(role1.name(), role2.name()),
+            Lists.newArrayList(role1.id(), role2.id()));
     userMetaService.insertUser(user1, false);
 
     GroupEntity group1 =
@@ -658,7 +668,8 @@ class TestRoleMetaService extends TestJDBCBackend {
             AuthorizationUtils.ofUserNamespace(metalakeName),
             "group1",
             auditInfo,
-            Lists.newArrayList(role1, role2));
+            Lists.newArrayList(role1.name(), role2.name()),
+            Lists.newArrayList(role1.id(), role2.id()));
     groupMetaService.insertGroup(group1, false);
 
     // hard delete before soft delete
diff --git 
a/core/src/test/java/org/apache/gravitino/storage/relational/service/TestUserMetaService.java
 
b/core/src/test/java/org/apache/gravitino/storage/relational/service/TestUserMetaService.java
index 90e675e06..326ccfc2d 100644
--- 
a/core/src/test/java/org/apache/gravitino/storage/relational/service/TestUserMetaService.java
+++ 
b/core/src/test/java/org/apache/gravitino/storage/relational/service/TestUserMetaService.java
@@ -30,7 +30,6 @@ import java.time.Instant;
 import java.util.List;
 import java.util.Optional;
 import java.util.function.Function;
-import java.util.stream.Collectors;
 import org.apache.gravitino.Entity;
 import org.apache.gravitino.EntityAlreadyExistsException;
 import org.apache.gravitino.Namespace;
@@ -110,11 +109,13 @@ class TestUserMetaService extends TestJDBCBackend {
             AuthorizationUtils.ofUserNamespace(metalakeName),
             "user2",
             auditInfo,
-            Lists.newArrayList(role1, role2));
+            Lists.newArrayList(role1.name(), role2.name()),
+            Lists.newArrayList(role1.id(), role2.id()));
     userMetaService.insertUser(user2, false);
     UserEntity actualUser = 
userMetaService.getUserByIdentifier(user2.nameIdentifier());
     Assertions.assertEquals(user2.name(), actualUser.name());
-    Assertions.assertEquals(Sets.newHashSet(user2.roles()), 
Sets.newHashSet(actualUser.roles()));
+    Assertions.assertEquals(
+        Sets.newHashSet(user2.roleNames()), 
Sets.newHashSet(actualUser.roleNames()));
   }
 
   @Test
@@ -192,11 +193,13 @@ class TestUserMetaService extends TestJDBCBackend {
             AuthorizationUtils.ofUserNamespace(metalakeName),
             "user2",
             auditInfo,
-            Lists.newArrayList(role1, role2));
+            Lists.newArrayList(role1.name(), role2.name()),
+            Lists.newArrayList(role1.id(), role2.id()));
     Assertions.assertDoesNotThrow(() -> userMetaService.insertUser(user2, 
false));
     UserEntity actualUser = 
userMetaService.getUserByIdentifier(user2.nameIdentifier());
     Assertions.assertEquals(user2.name(), actualUser.name());
-    Assertions.assertEquals(Sets.newHashSet(user2.roles()), 
Sets.newHashSet(actualUser.roles()));
+    Assertions.assertEquals(
+        Sets.newHashSet(user2.roleNames()), 
Sets.newHashSet(actualUser.roleNames()));
 
     // insert duplicate user with roles
     UserEntity user2Exist =
@@ -215,15 +218,17 @@ class TestUserMetaService extends TestJDBCBackend {
             AuthorizationUtils.ofUserNamespace(metalakeName),
             "user2Overwrite",
             auditInfo,
-            Lists.newArrayList(role1, role2));
+            Lists.newArrayList(role1.name(), role2.name()),
+            Lists.newArrayList(role1.id(), role2.id()));
     Assertions.assertDoesNotThrow(() -> 
userMetaService.insertUser(user2Overwrite, true));
 
     UserEntity actualOverwriteUser2 =
         userMetaService.getUserByIdentifier(user2Overwrite.nameIdentifier());
     Assertions.assertEquals("user2Overwrite", actualOverwriteUser2.name());
-    Assertions.assertEquals(2, actualOverwriteUser2.roles().size());
+    Assertions.assertEquals(2, actualOverwriteUser2.roleNames().size());
     Assertions.assertEquals(
-        Sets.newHashSet(role1.name(), role2.name()), 
Sets.newHashSet(actualOverwriteUser2.roles()));
+        Sets.newHashSet(role1.name(), role2.name()),
+        Sets.newHashSet(actualOverwriteUser2.roleNames()));
 
     // insert overwrite user with 1 role
     RoleEntity role3 =
@@ -240,14 +245,15 @@ class TestUserMetaService extends TestJDBCBackend {
             AuthorizationUtils.ofUserNamespace(metalakeName),
             "user3Overwrite",
             auditInfo,
-            Lists.newArrayList(role3));
+            Lists.newArrayList(role3.name()),
+            Lists.newArrayList(role3.id()));
     Assertions.assertDoesNotThrow(() -> 
userMetaService.insertUser(user3Overwrite, true));
 
     UserEntity actualOverwriteUser3 =
         userMetaService.getUserByIdentifier(user3Overwrite.nameIdentifier());
     Assertions.assertEquals("user3Overwrite", actualOverwriteUser3.name());
-    Assertions.assertEquals(1, actualOverwriteUser3.roles().size());
-    Assertions.assertEquals("role3", actualOverwriteUser3.roles().get(0));
+    Assertions.assertEquals(1, actualOverwriteUser3.roleNames().size());
+    Assertions.assertEquals("role3", actualOverwriteUser3.roleNames().get(0));
 
     // insert overwrite user with 0 roles
     UserEntity user4Overwrite =
@@ -261,7 +267,7 @@ class TestUserMetaService extends TestJDBCBackend {
     UserEntity actualOverwriteUser4 =
         userMetaService.getUserByIdentifier(user4Overwrite.nameIdentifier());
     Assertions.assertEquals("user4Overwrite", actualOverwriteUser4.name());
-    Assertions.assertTrue(actualOverwriteUser4.roles().isEmpty());
+    Assertions.assertNull(actualOverwriteUser4.roleNames());
   }
 
   @Test
@@ -332,7 +338,8 @@ class TestUserMetaService extends TestJDBCBackend {
             AuthorizationUtils.ofUserNamespace(metalakeName),
             "user2",
             auditInfo,
-            Lists.newArrayList(role1, role2));
+            Lists.newArrayList(role1.name(), role2.name()),
+            Lists.newArrayList(role1.id(), role2.id()));
     userMetaService.insertUser(user2, false);
     List<RolePO> rolePOs =
         SessionUtils.doWithCommitAndFetchResult(
@@ -340,7 +347,8 @@ class TestUserMetaService extends TestJDBCBackend {
     Assertions.assertEquals(2, rolePOs.size());
     UserEntity actualUser = 
userMetaService.getUserByIdentifier(user2.nameIdentifier());
     Assertions.assertEquals(user2.name(), actualUser.name());
-    Assertions.assertEquals(Sets.newHashSet(user2.roles()), 
Sets.newHashSet(actualUser.roles()));
+    Assertions.assertEquals(
+        Sets.newHashSet(user2.roleNames()), 
Sets.newHashSet(actualUser.roleNames()));
 
     Assertions.assertTrue(userMetaService.deleteUser(user2.nameIdentifier()));
     Assertions.assertThrows(
@@ -389,11 +397,13 @@ class TestUserMetaService extends TestJDBCBackend {
             AuthorizationUtils.ofUserNamespace(metalakeName),
             "user1",
             auditInfo,
-            Lists.newArrayList(role1, role2));
+            Lists.newArrayList(role1.name(), role2.name()),
+            Lists.newArrayList(role1.id(), role2.id()));
     userMetaService.insertUser(user1, false);
     UserEntity actualUser = 
userMetaService.getUserByIdentifier(user1.nameIdentifier());
     Assertions.assertEquals(user1.name(), actualUser.name());
-    Assertions.assertEquals(Sets.newHashSet(user1.roles()), 
Sets.newHashSet(actualUser.roles()));
+    Assertions.assertEquals(
+        Sets.newHashSet(user1.roleNames()), 
Sets.newHashSet(actualUser.roleNames()));
 
     RoleEntity role3 =
         createRoleEntity(
@@ -415,14 +425,17 @@ class TestUserMetaService extends TestJDBCBackend {
                   .withLastModifiedTime(Instant.now())
                   .build();
 
-          List<RoleEntity> roleEntities = 
Lists.newArrayList(user.roleEntities());
-          roleEntities.add(role3);
+          List<String> roleNames = Lists.newArrayList(user.roleNames());
+          List<Long> roleIds = Lists.newArrayList(user.roleIds());
+          roleNames.add(role3.name());
+          roleIds.add(role3.id());
 
           return UserEntity.builder()
               .withNamespace(user.namespace())
               .withId(user.id())
               .withName(user.name())
-              .withRoles(roleEntities)
+              .withRoleNames(roleNames)
+              .withRoleIds(roleIds)
               .withAuditInfo(updateAuditInfo)
               .build();
         };
@@ -433,10 +446,9 @@ class TestUserMetaService extends TestJDBCBackend {
     Assertions.assertEquals(user1.id(), grantUser.id());
     Assertions.assertEquals(user1.name(), grantUser.name());
     Assertions.assertEquals(
-        Sets.newHashSet("role1", "role2", "role3"), 
Sets.newHashSet(grantUser.roles()));
+        Sets.newHashSet("role1", "role2", "role3"), 
Sets.newHashSet(grantUser.roleNames()));
     Assertions.assertEquals(
-        Sets.newHashSet(role1.id(), role2.id(), role3.id()),
-        
grantUser.roleEntities().stream().map(RoleEntity::id).collect(Collectors.toSet()));
+        Sets.newHashSet(role1.id(), role2.id(), role3.id()), 
Sets.newHashSet(grantUser.roleIds()));
     Assertions.assertEquals("creator", grantUser.auditInfo().creator());
     Assertions.assertEquals("grantUser", grantUser.auditInfo().lastModifier());
 
@@ -451,15 +463,17 @@ class TestUserMetaService extends TestJDBCBackend {
                   .withLastModifiedTime(Instant.now())
                   .build();
 
-          List<String> roleNames = Lists.newArrayList(user.roles());
-          List<RoleEntity> roleEntities = 
Lists.newArrayList(user.roleEntities());
-          roleEntities.remove(roleNames.indexOf("role2"));
+          List<String> roleNames = Lists.newArrayList(user.roleNames());
+          List<Long> roleIds = Lists.newArrayList(user.roleIds());
+          roleIds.remove(roleNames.indexOf("role2"));
+          roleNames.remove("role2");
 
           return UserEntity.builder()
               .withNamespace(user.namespace())
               .withId(user.id())
               .withName(user.name())
-              .withRoles(roleEntities)
+              .withRoleNames(roleNames)
+              .withRoleIds(roleIds)
               .withAuditInfo(updateAuditInfo)
               .build();
         };
@@ -469,10 +483,10 @@ class TestUserMetaService extends TestJDBCBackend {
         
UserMetaService.getInstance().getUserByIdentifier(user1.nameIdentifier());
     Assertions.assertEquals(user1.id(), revokeUser.id());
     Assertions.assertEquals(user1.name(), revokeUser.name());
-    Assertions.assertEquals(Sets.newHashSet("role1", "role3"), 
Sets.newHashSet(revokeUser.roles()));
     Assertions.assertEquals(
-        Sets.newHashSet(role1.id(), role3.id()),
-        
revokeUser.roleEntities().stream().map(RoleEntity::id).collect(Collectors.toSet()));
+        Sets.newHashSet("role1", "role3"), 
Sets.newHashSet(revokeUser.roleNames()));
+    Assertions.assertEquals(
+        Sets.newHashSet(role1.id(), role3.id()), 
Sets.newHashSet(revokeUser.roleIds()));
     Assertions.assertEquals("creator", revokeUser.auditInfo().creator());
     Assertions.assertEquals("revokeUser", 
revokeUser.auditInfo().lastModifier());
 
@@ -496,16 +510,19 @@ class TestUserMetaService extends TestJDBCBackend {
                   .withLastModifiedTime(Instant.now())
                   .build();
 
-          List<String> roleNames = Lists.newArrayList(user.roles());
-          List<RoleEntity> roleEntities = 
Lists.newArrayList(user.roleEntities());
-          roleEntities.remove(roleNames.indexOf("role3"));
-          roleEntities.add(role4);
+          List<String> roleNames = Lists.newArrayList(user.roleNames());
+          List<Long> roleIds = Lists.newArrayList(user.roleIds());
+          roleIds.remove(roleNames.indexOf("role3"));
+          roleNames.remove("role3");
+          roleIds.add(role4.id());
+          roleNames.add(role4.name());
 
           return UserEntity.builder()
               .withNamespace(user.namespace())
               .withId(user.id())
               .withName(user.name())
-              .withRoles(roleEntities)
+              .withRoleNames(roleNames)
+              .withRoleIds(roleIds)
               .withAuditInfo(updateAuditInfo)
               .build();
         };
@@ -516,10 +533,9 @@ class TestUserMetaService extends TestJDBCBackend {
     Assertions.assertEquals(user1.id(), grantRevokeUser.id());
     Assertions.assertEquals(user1.name(), grantRevokeUser.name());
     Assertions.assertEquals(
-        Sets.newHashSet("role1", "role4"), 
Sets.newHashSet(grantRevokeUser.roles()));
+        Sets.newHashSet("role1", "role4"), 
Sets.newHashSet(grantRevokeUser.roleNames()));
     Assertions.assertEquals(
-        Sets.newHashSet(role1.id(), role4.id()),
-        
grantRevokeUser.roleEntities().stream().map(RoleEntity::id).collect(Collectors.toSet()));
+        Sets.newHashSet(role1.id(), role4.id()), 
Sets.newHashSet(grantRevokeUser.roleIds()));
     Assertions.assertEquals("creator", grantRevokeUser.auditInfo().creator());
     Assertions.assertEquals("grantRevokeUser", 
grantRevokeUser.auditInfo().lastModifier());
 
@@ -533,13 +549,15 @@ class TestUserMetaService extends TestJDBCBackend {
                   .withLastModifiedTime(Instant.now())
                   .build();
 
-          List<RoleEntity> roleEntities = 
Lists.newArrayList(user.roleEntities());
+          List<String> roleNames = Lists.newArrayList(user.roleNames());
+          List<Long> roleIds = Lists.newArrayList(user.roleIds());
 
           return UserEntity.builder()
               .withNamespace(user.namespace())
               .withId(user.id())
               .withName(user.name())
-              .withRoles(roleEntities)
+              .withRoleNames(roleNames)
+              .withRoleIds(roleIds)
               .withAuditInfo(updateAuditInfo)
               .build();
         };
@@ -549,10 +567,9 @@ class TestUserMetaService extends TestJDBCBackend {
     Assertions.assertEquals(user1.id(), noUpdaterUser.id());
     Assertions.assertEquals(user1.name(), noUpdaterUser.name());
     Assertions.assertEquals(
-        Sets.newHashSet("role1", "role4"), 
Sets.newHashSet(noUpdaterUser.roles()));
+        Sets.newHashSet("role1", "role4"), 
Sets.newHashSet(noUpdaterUser.roleNames()));
     Assertions.assertEquals(
-        Sets.newHashSet(role1.id(), role4.id()),
-        
noUpdaterUser.roleEntities().stream().map(RoleEntity::id).collect(Collectors.toSet()));
+        Sets.newHashSet(role1.id(), role4.id()), 
Sets.newHashSet(noUpdaterUser.roleIds()));
     Assertions.assertEquals("creator", noUpdaterUser.auditInfo().creator());
     Assertions.assertEquals("grantRevokeUser", 
noUpdaterUser.auditInfo().lastModifier());
 
@@ -560,7 +577,7 @@ class TestUserMetaService extends TestJDBCBackend {
     RoleMetaService.getInstance().deleteRole(role1.nameIdentifier());
     UserEntity userEntity =
         
UserMetaService.getInstance().getUserByIdentifier(user1.nameIdentifier());
-    Assertions.assertEquals(Sets.newHashSet("role4"), 
Sets.newHashSet(userEntity.roles()));
+    Assertions.assertEquals(Sets.newHashSet("role4"), 
Sets.newHashSet(userEntity.roleNames()));
   }
 
   @Test
@@ -608,14 +625,16 @@ class TestUserMetaService extends TestJDBCBackend {
             AuthorizationUtils.ofUserNamespace(metalakeName),
             "user1",
             auditInfo,
-            Lists.newArrayList(role1, role2));
+            Lists.newArrayList(role1.name(), role2.name()),
+            Lists.newArrayList(role1.id(), role2.id()));
     UserEntity user2 =
         createUserEntity(
             RandomIdGenerator.INSTANCE.nextId(),
             AuthorizationUtils.ofUserNamespace(metalakeName),
             "user2",
             auditInfo,
-            Lists.newArrayList(role3));
+            Lists.newArrayList(role3.name()),
+            Lists.newArrayList(role3.id()));
     userMetaService.insertUser(user1, false);
     userMetaService.insertUser(user2, false);
 
@@ -687,14 +706,16 @@ class TestUserMetaService extends TestJDBCBackend {
             AuthorizationUtils.ofUserNamespace(metalakeName),
             "user1",
             auditInfo,
-            Lists.newArrayList(role1, role2));
+            Lists.newArrayList(role1.name(), role2.name()),
+            Lists.newArrayList(role1.id(), role2.id()));
     UserEntity user2 =
         createUserEntity(
             RandomIdGenerator.INSTANCE.nextId(),
             AuthorizationUtils.ofUserNamespace(metalakeName),
             "user2",
             auditInfo,
-            Lists.newArrayList(role3));
+            Lists.newArrayList(role3.name()),
+            Lists.newArrayList(role3.id()));
     userMetaService.insertUser(user1, false);
     userMetaService.insertUser(user2, false);
 
@@ -757,28 +778,32 @@ class TestUserMetaService extends TestJDBCBackend {
             AuthorizationUtils.ofUserNamespace(metalakeName),
             "user1",
             auditInfo,
-            Lists.newArrayList(role1, role2));
+            Lists.newArrayList(role1.name(), role2.name()),
+            Lists.newArrayList(role1.id(), role2.id()));
     UserEntity user2 =
         createUserEntity(
             RandomIdGenerator.INSTANCE.nextId(),
             AuthorizationUtils.ofUserNamespace(metalakeName),
             "user2",
             auditInfo,
-            Lists.newArrayList(role1, role2));
+            Lists.newArrayList(role1.name(), role2.name()),
+            Lists.newArrayList(role1.id(), role2.id()));
     UserEntity user3 =
         createUserEntity(
             RandomIdGenerator.INSTANCE.nextId(),
             AuthorizationUtils.ofUserNamespace(metalakeName),
             "user3",
             auditInfo,
-            Lists.newArrayList(role1, role2));
+            Lists.newArrayList(role1.name(), role2.name()),
+            Lists.newArrayList(role1.id(), role2.id()));
     UserEntity user4 =
         createUserEntity(
             RandomIdGenerator.INSTANCE.nextId(),
             AuthorizationUtils.ofUserNamespace(metalakeName),
             "user4",
             auditInfo,
-            Lists.newArrayList(role1, role2));
+            Lists.newArrayList(role1.name(), role2.name()),
+            Lists.newArrayList(role1.id(), role2.id()));
     userMetaService.insertUser(user1, false);
     userMetaService.insertUser(user2, false);
     userMetaService.insertUser(user3, false);
diff --git 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestGroupOperations.java
 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestGroupOperations.java
index 6a4b8e953..c3b34bc6b 100644
--- 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestGroupOperations.java
+++ 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestGroupOperations.java
@@ -245,7 +245,7 @@ public class TestGroupOperations extends JerseyTest {
     return GroupEntity.builder()
         .withId(1L)
         .withName(group)
-        .withRoles(Collections.emptyList())
+        .withRoleNames(Collections.emptyList())
         .withAuditInfo(
             
AuditInfo.builder().withCreator("creator").withCreateTime(Instant.now()).build())
         .build();
diff --git 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestPermissionOperations.java
 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestPermissionOperations.java
index 39ed06ebb..76dba3edd 100644
--- 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestPermissionOperations.java
+++ 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestPermissionOperations.java
@@ -52,7 +52,6 @@ import org.apache.gravitino.exceptions.NoSuchUserException;
 import org.apache.gravitino.lock.LockManager;
 import org.apache.gravitino.meta.AuditInfo;
 import org.apache.gravitino.meta.GroupEntity;
-import org.apache.gravitino.meta.RoleEntity;
 import org.apache.gravitino.meta.UserEntity;
 import org.apache.gravitino.rest.RESTUtils;
 import org.glassfish.hk2.utilities.binding.AbstractBinder;
@@ -111,18 +110,12 @@ public class TestPermissionOperations extends JerseyTest {
 
   @Test
   public void testGrantRolesToUser() {
-    RoleEntity roleEntity =
-        RoleEntity.builder()
-            .withId(1L)
-            .withAuditInfo(
-                
AuditInfo.builder().withCreator("test").withCreateTime(Instant.now()).build())
-            .withName("roles")
-            .build();
     UserEntity userEntity =
         UserEntity.builder()
             .withId(1L)
             .withName("user")
-            .withRoles(Lists.newArrayList(roleEntity))
+            .withRoleNames(Lists.newArrayList("roles"))
+            .withRoleIds(Lists.newArrayList(1L))
             .withAuditInfo(
                 
AuditInfo.builder().withCreator("test").withCreateTime(Instant.now()).build())
             .build();
@@ -214,18 +207,12 @@ public class TestPermissionOperations extends JerseyTest {
 
   @Test
   public void testGrantRolesToGroup() {
-    RoleEntity roleEntity =
-        RoleEntity.builder()
-            .withId(1L)
-            .withName("roles")
-            .withAuditInfo(
-                
AuditInfo.builder().withCreator("test").withCreateTime(Instant.now()).build())
-            .build();
     GroupEntity groupEntity =
         GroupEntity.builder()
             .withId(1L)
             .withName("group")
-            .withRoles(Lists.newArrayList(roleEntity))
+            .withRoleNames(Lists.newArrayList("roles"))
+            .withRoleIds(Lists.newArrayList(1L))
             .withAuditInfo(
                 
AuditInfo.builder().withCreator("test").withCreateTime(Instant.now()).build())
             .build();
@@ -324,7 +311,8 @@ public class TestPermissionOperations extends JerseyTest {
         UserEntity.builder()
             .withId(1L)
             .withName("user")
-            .withRoles(Lists.newArrayList())
+            .withRoleNames(Lists.newArrayList())
+            .withRoleIds(Lists.newArrayList(1L))
             .withAuditInfo(
                 
AuditInfo.builder().withCreator("test").withCreateTime(Instant.now()).build())
             .build();
@@ -368,7 +356,8 @@ public class TestPermissionOperations extends JerseyTest {
         GroupEntity.builder()
             .withId(1L)
             .withName("group")
-            .withRoles(Lists.newArrayList())
+            .withRoleNames(Lists.newArrayList())
+            .withRoleIds(Lists.newArrayList(1L))
             .withAuditInfo(
                 
AuditInfo.builder().withCreator("test").withCreateTime(Instant.now()).build())
             .build();
diff --git 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestUserOperations.java
 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestUserOperations.java
index b13c0175b..d3209e0e2 100644
--- 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestUserOperations.java
+++ 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestUserOperations.java
@@ -246,7 +246,7 @@ public class TestUserOperations extends JerseyTest {
     return UserEntity.builder()
         .withId(1L)
         .withName(user)
-        .withRoles(Collections.emptyList())
+        .withRoleNames(Collections.emptyList())
         .withAuditInfo(
             
AuditInfo.builder().withCreator("creator").withCreateTime(Instant.now()).build())
         .build();


Reply via email to