You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by ra...@apache.org on 2026/05/26 08:13:53 UTC

(ranger) branch ranger-2.9 updated: RANGER-3899: performance improvement for policies with many users/groups/roles (ranger-2.9) (#970)

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

ramackri pushed a commit to branch ranger-2.9
in repository https://gitbox.apache.org/repos/asf/ranger.git


The following commit(s) were added to refs/heads/ranger-2.9 by this push:
     new 4559d0a01 RANGER-3899: performance improvement for policies with many users/groups/roles (ranger-2.9) (#970)
4559d0a01 is described below

commit 4559d0a01186ea65dd0de7b53b0fca308d2f63bc
Author: Ramachandran Krishnan <ra...@gmail.com>
AuthorDate: Tue May 26 13:43:48 2026 +0530

    RANGER-3899: performance improvement for policies with many users/groups/roles (ranger-2.9) (#970)
    
    * RANGER-3899: performance improvement in create/update of policies referencing large number of users/groups/roles
    
    Backport of apache/ranger@d1589d629 to ranger-2.9.
    
    Co-authored-by: Cursor <cu...@cursor.com>
    
    * RANGER-3899: fix TestServiceDBStore; omit JUnit5 TestPolicyRefUpdater on ranger-2.9
    
    Update tess28updatePolicy mock for createNewPolMappingForRefTable(..., true).
    Remove TestPolicyRefUpdater (JUnit 5) since ranger-2.9 security-admin uses
    Surefire 2.18.1; production backport does not require Surefire/JUnit5 changes.
    
    Co-authored-by: Cursor <cu...@cursor.com>
    
    * RANGER-3899: trim DAO diffs to functional-only changes on ranger-2.9
    
    Restore ranger-2.9 formatting and append only batch lookup/delete methods
    from master (d1589d629), matching ~266 lines added instead of full-file
    reformat churn.
    
    Co-authored-by: Cursor <cu...@cursor.com>
    
    * RANGER-3899: add TestPolicyRefUpdater using JUnit 4 on ranger-2.9
    
    Restore policy ref updater unit tests adapted for batch DAO APIs and
    5-arg createNewPolMappingForRefTable. Use JUnit 4 + MockitoJUnitRunner
    so tests run under security-admin Surefire 2.18.1 without pom changes.
    
    Co-authored-by: Cursor <cu...@cursor.com>
    
    * RANGER-3899: drop GDS and master-only JPA queries from 2.9 backport
    
    Align jpa_named_queries.xml with apache/ranger@d1589d629: keep only the
    13 named queries required for policy ref updater performance work.
    Remove XXGds* (GDS), XXPolicy.findByServiceType, and other queries not
    present on ranger-2.9. Restore XXRMSResourceMapping.deleteByServiceResourceIds.
    
    Co-authored-by: Cursor <cu...@cursor.com>
    
    ---------
    
    Co-authored-by: ramk <ra...@cloudera.com>
    Co-authored-by: Cursor <cu...@cursor.com>
---
 dev-support/checks/coverage.sh                     |    4 +
 .../org/apache/ranger/biz/PolicyRefUpdater.java    | 1239 ++++++++++++--------
 .../java/org/apache/ranger/biz/ServiceDBStore.java |    5 +-
 .../org/apache/ranger/db/XXAccessTypeDefDao.java   |   27 +
 .../org/apache/ranger/db/XXDataMaskTypeDefDao.java |   27 +
 .../main/java/org/apache/ranger/db/XXGroupDao.java |   21 +
 .../apache/ranger/db/XXPolicyConditionDefDao.java  |   28 +-
 .../org/apache/ranger/db/XXPolicyRefGroupDao.java  |   29 +
 .../org/apache/ranger/db/XXPolicyRefRoleDao.java   |   29 +
 .../org/apache/ranger/db/XXPolicyRefUserDao.java   |   29 +
 .../org/apache/ranger/db/XXResourceDefDao.java     |   27 +
 .../main/java/org/apache/ranger/db/XXRoleDao.java  |   25 +
 .../main/java/org/apache/ranger/db/XXUserDao.java  |   29 +-
 .../main/resources/META-INF/jpa_named_queries.xml  |   60 +
 .../apache/ranger/biz/TestPolicyRefUpdater.java    |  423 +++++++
 .../org/apache/ranger/biz/TestServiceDBStore.java  |    9 +-
 16 files changed, 1531 insertions(+), 480 deletions(-)

diff --git a/dev-support/checks/coverage.sh b/dev-support/checks/coverage.sh
index eabf0a4a3..58a8a09bd 100755
--- a/dev-support/checks/coverage.sh
+++ b/dev-support/checks/coverage.sh
@@ -49,6 +49,10 @@ find . -type d -name 'target' -prune -exec find {} -type f \( -name 'ranger-*.ja
 -or -name '*shim*' -prune \
 | xargs -n1 unzip -o -q -d target/coverage-classes
 
+# Multi-release JARs (e.g. BouncyCastle) ship the same classes under
+# META-INF/versions/* and at the root; JaCoCo fails with duplicate class names.
+rm -rf target/coverage-classes/META-INF/versions || true
+
 # get all source file paths
 src=$(find . -path '*/src/main/java' -o -path './target' -prune | sed 's/^/--sourcefiles /g' | xargs echo)
 
diff --git a/security-admin/src/main/java/org/apache/ranger/biz/PolicyRefUpdater.java b/security-admin/src/main/java/org/apache/ranger/biz/PolicyRefUpdater.java
index ab7eb5f67..6c8ede470 100644
--- a/security-admin/src/main/java/org/apache/ranger/biz/PolicyRefUpdater.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/PolicyRefUpdater.java
@@ -18,22 +18,18 @@
  */
 package org.apache.ranger.biz;
 
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.ranger.common.RESTErrorUtil;
 import org.apache.ranger.common.RangerCommonEnums;
+import org.apache.ranger.common.db.BaseDao;
 import org.apache.ranger.common.db.RangerTransactionSynchronizationAdapter;
 import org.apache.ranger.db.RangerDaoManager;
-import org.apache.ranger.entity.XXAccessTypeDef;
-import org.apache.ranger.entity.XXDataMaskTypeDef;
+import org.apache.ranger.db.XXPolicyRefGroupDao;
+import org.apache.ranger.db.XXPolicyRefRoleDao;
+import org.apache.ranger.db.XXPolicyRefUserDao;
 import org.apache.ranger.entity.XXGroup;
 import org.apache.ranger.entity.XXPolicy;
-import org.apache.ranger.entity.XXPolicyConditionDef;
 import org.apache.ranger.entity.XXPolicyRefAccessType;
 import org.apache.ranger.entity.XXPolicyRefCondition;
 import org.apache.ranger.entity.XXPolicyRefDataMaskType;
@@ -41,7 +37,6 @@
 import org.apache.ranger.entity.XXPolicyRefResource;
 import org.apache.ranger.entity.XXPolicyRefRole;
 import org.apache.ranger.entity.XXPolicyRefUser;
-import org.apache.ranger.entity.XXResourceDef;
 import org.apache.ranger.entity.XXRole;
 import org.apache.ranger.entity.XXServiceDef;
 import org.apache.ranger.entity.XXUser;
@@ -64,473 +59,781 @@
 
 import javax.servlet.http.HttpServletResponse;
 
-import static org.apache.ranger.service.RangerBaseModelService.OPERATION_CREATE_CONTEXT;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
 
+import static org.apache.ranger.service.RangerBaseModelService.OPERATION_CREATE_CONTEXT;
 
 @Component
 public class PolicyRefUpdater {
+    private static final Logger LOG = LoggerFactory.getLogger(PolicyRefUpdater.class);
+
+    @Autowired
+    RangerDaoManager daoMgr;
+
+    @Autowired
+    XUserMgr xUserMgr;
+
+    @Autowired
+    RoleDBStore roleStore;
+
+    @Autowired
+    RangerBizUtil rangerBizUtil;
+
+    @Autowired
+    XGroupService xGroupService;
+
+    @Autowired
+    RangerTransactionSynchronizationAdapter rangerTransactionSynchronizationAdapter;
+
+    @Autowired
+    RESTErrorUtil restErrorUtil;
+
+    public static List<List<? extends RangerPolicyItem>> getAllPolicyItems(RangerPolicy policy) {
+        List<List<? extends RangerPolicyItem>> ret = new ArrayList<>();
+
+        if (CollectionUtils.isNotEmpty(policy.getPolicyItems())) {
+            ret.add(policy.getPolicyItems());
+        }
+
+        if (CollectionUtils.isNotEmpty(policy.getDenyPolicyItems())) {
+            ret.add(policy.getDenyPolicyItems());
+        }
+
+        if (CollectionUtils.isNotEmpty(policy.getAllowExceptions())) {
+            ret.add(policy.getAllowExceptions());
+        }
+
+        if (CollectionUtils.isNotEmpty(policy.getDenyExceptions())) {
+            ret.add(policy.getDenyExceptions());
+        }
+
+        if (CollectionUtils.isNotEmpty(policy.getDataMaskPolicyItems())) {
+            ret.add(policy.getDataMaskPolicyItems());
+        }
+
+        if (CollectionUtils.isNotEmpty(policy.getRowFilterPolicyItems())) {
+            ret.add(policy.getRowFilterPolicyItems());
+        }
+
+        return ret;
+    }
+
+    public void createNewPolMappingForRefTable(RangerPolicy policy, XXPolicy xPolicy, XXServiceDef xServiceDef, boolean createPrincipalsIfAbsent, boolean isCleanupRefTablesNeeded) throws Exception {
+        if (policy == null) {
+            return;
+        }
+
+        final Set<String> resourceNames  = policy.getResources().keySet();
+        final Set<String> roleNames      = new HashSet<>();
+        final Set<String> groupNames     = new HashSet<>();
+        final Set<String> userNames      = new HashSet<>();
+        final Set<String> accessTypes    = new HashSet<>();
+        final Set<String> conditionTypes = new HashSet<>();
+        final Set<String> dataMaskTypes  = new HashSet<>();
+        boolean           oldBulkMode    = RangerBizUtil.isBulkMode();
+        final Long policyId = policy.getId();
+
+        List<RangerPolicy.RangerPolicyItemCondition> rangerPolicyConditions = policy.getConditions();
+
+        if (CollectionUtils.isNotEmpty(rangerPolicyConditions)) {
+            for (RangerPolicy.RangerPolicyItemCondition condition : rangerPolicyConditions) {
+                conditionTypes.add(condition.getType());
+            }
+        }
+
+        for (List<? extends RangerPolicyItem> policyItems : getAllPolicyItems(policy)) {
+            if (CollectionUtils.isEmpty(policyItems)) {
+                continue;
+            }
+
+            for (RangerPolicyItem policyItem : policyItems) {
+                roleNames.addAll(policyItem.getRoles());
+                groupNames.addAll(policyItem.getGroups());
+                userNames.addAll(policyItem.getUsers());
+
+                if (CollectionUtils.isNotEmpty(policyItem.getAccesses())) {
+                    for (RangerPolicyItemAccess access : policyItem.getAccesses()) {
+                        accessTypes.add(access.getType());
+                    }
+                }
+
+                if (CollectionUtils.isNotEmpty(policyItem.getConditions())) {
+                    for (RangerPolicyItemCondition condition : policyItem.getConditions()) {
+                        conditionTypes.add(condition.getType());
+                    }
+                }
+
+                if (policyItem instanceof RangerDataMaskPolicyItem) {
+                    RangerPolicyItemDataMaskInfo dataMaskInfo = ((RangerDataMaskPolicyItem) policyItem).getDataMaskInfo();
+
+                    dataMaskTypes.add(dataMaskInfo.getDataMaskType());
+                }
+            }
+        }
+
+        if (isCleanupRefTablesNeeded) {
+            cleanupRefTablesForUpdate(policyId, userNames, roleNames, groupNames);
+        }
+
+        if (CollectionUtils.isNotEmpty(resourceNames)) {
+            List<XXPolicyRefResource> xPolResources = new ArrayList<>();
+            Map<String, Long>         nameToId      = daoMgr.getXXResourceDef().findResourceDefIdsByNameAndPolicyId(resourceNames, policy.getId());
+
+            for (String resource : resourceNames) {
+                Long resourceDefId = nameToId.get(resource);
+
+                if (resourceDefId == null) {
+                    throw new Exception(resource + ": is not a valid resource-type. policy='" + policy.getName() + "' service='" + policy.getService() + "'");
+                }
+
+                XXPolicyRefResource xPolRes = new XXPolicyRefResource();
+
+                xPolRes.setPolicyId(policy.getId());
+                xPolRes.setResourceDefId(resourceDefId);
+                xPolRes.setResourceName(resource);
+
+                xPolResources.add(xPolRes);
+            }
+
+            batchInsert(xPolResources, daoMgr.getXXPolicyRefResource(), oldBulkMode);
+        }
+
+        if (createPrincipalsIfAbsent && !rangerBizUtil.checkAdminAccess()) {
+            LOG.warn("policy={}: createPrincipalIfAbsent=true, but current user does not have admin privileges!", policy.getName());
+
+            createPrincipalsIfAbsent = false;
+        }
+
+        if (CollectionUtils.isNotEmpty(roleNames)) {
+            LOG.debug("x_policy_ref_role - New role entries to insert for policy ID {}: {}", policyId, roleNames);
+
+            Set<String> filteredRoleNames = roleNames.stream()
+                    .filter(StringUtils::isNotBlank)
+                    .collect(Collectors.toSet());
+
+            List<XXPolicyRefRole> xPolRoles = new ArrayList<>();
+            Map<String, Long>     nameToId  = daoMgr.getXXRole().getIdsByRoleNames(filteredRoleNames);
+
+            for (String roleName : filteredRoleNames) {
+                Long                 roleId     = nameToId.get(roleName);
+                PolicyRoleAssociator associator = new PolicyRoleAssociator(roleName, roleId, xPolicy);
+
+                if (roleId != null) {
+                    XXPolicyRefRole roleRef = associator.getPolicyRef();
+
+                    if (roleRef != null) {
+                        xPolRoles.add(roleRef);
+                    }
+                } else if (createPrincipalsIfAbsent) {
+                    rangerTransactionSynchronizationAdapter.executeOnTransactionCommit(associator);
+                } else {
+                    VXResponse gjResponse = new VXResponse();
+
+                    gjResponse.setStatusCode(HttpServletResponse.SC_BAD_REQUEST);
+                    gjResponse.setMsgDesc("Operation denied. Role name: " + roleName + " specified in policy does not exist in ranger admin.");
+
+                    throw restErrorUtil.generateRESTException(gjResponse);
+                }
+            }
+
+            batchInsert(xPolRoles, daoMgr.getXXPolicyRefRole(), oldBulkMode);
+        }
+
+        if (CollectionUtils.isNotEmpty(groupNames)) {
+            LOG.debug("x_policy_ref_group - New group entries to insert for policy ID {}: {}", policyId, groupNames);
+
+            Set<String> filteredGroupNames = groupNames.stream()
+                    .filter(StringUtils::isNotBlank)
+                    .collect(Collectors.toSet());
+
+            List<XXPolicyRefGroup> xPolGroups = new ArrayList<>();
+            Map<String, Long>      nameToId   = daoMgr.getXXGroup().getIdsByGroupNames(filteredGroupNames);
+
+            for (String groupName : filteredGroupNames) {
+                Long                  groupId    = nameToId.get(groupName);
+                PolicyGroupAssociator associator = new PolicyGroupAssociator(groupName, groupId, xPolicy);
+
+                if (groupId != null) {
+                    XXPolicyRefGroup groupRef = associator.getPolicyRef();
+
+                    if (groupRef != null) {
+                        xPolGroups.add(groupRef);
+                    }
+                } else if (createPrincipalsIfAbsent) {
+                    rangerTransactionSynchronizationAdapter.executeOnTransactionCommit(associator);
+                } else {
+                    VXResponse gjResponse = new VXResponse();
+
+                    gjResponse.setStatusCode(HttpServletResponse.SC_BAD_REQUEST);
+                    gjResponse.setMsgDesc("Operation denied. Group name: " + groupName + " specified in policy does not exist in ranger admin.");
+
+                    throw restErrorUtil.generateRESTException(gjResponse);
+                }
+            }
+
+            batchInsert(xPolGroups, daoMgr.getXXPolicyRefGroup(), oldBulkMode);
+        }
+
+        if (CollectionUtils.isNotEmpty(userNames)) {
+            LOG.debug("x_policy_ref_user - New user entries to insert for policy ID {}: {}", policyId, userNames);
+
+            Set<String> filteredUserNames = userNames.stream()
+                    .filter(StringUtils::isNotBlank)
+                    .collect(Collectors.toSet());
+
+            List<XXPolicyRefUser> xPolUsers = new ArrayList<>();
+            Map<String, Long>     nameToId  = daoMgr.getXXUser().getIdsByUserNames(filteredUserNames);
+
+            for (String userName : filteredUserNames) {
+                Long                 userId     = nameToId.get(userName);
+                PolicyUserAssociator associator = new PolicyUserAssociator(userName, userId, xPolicy);
+
+                if (userId != null) {
+                    XXPolicyRefUser userRef = associator.getPolicyRef();
+
+                    if (userRef != null) {
+                        xPolUsers.add(userRef);
+                    }
+                } else if (createPrincipalsIfAbsent) {
+                    rangerTransactionSynchronizationAdapter.executeOnTransactionCommit(associator);
+                } else {
+                    VXResponse gjResponse = new VXResponse();
+
+                    gjResponse.setStatusCode(HttpServletResponse.SC_BAD_REQUEST);
+                    gjResponse.setMsgDesc("Operation denied. User name: " + userName + " specified in policy does not exist in ranger admin.");
+
+                    throw restErrorUtil.generateRESTException(gjResponse);
+                }
+            }
+
+            batchInsert(xPolUsers, daoMgr.getXXPolicyRefUser(), oldBulkMode);
+        }
+
+        // ignore built-in access-types while creating ref-table entries
+        accessTypes.removeAll(ServiceDefUtil.ACCESS_TYPE_MARKERS);
+
+        if (CollectionUtils.isNotEmpty(accessTypes)) {
+            List<XXPolicyRefAccessType> xPolAccesses = new ArrayList<>();
+            Map<String, Long>           nameToId     = daoMgr.getXXAccessTypeDef().findAccessTypeDefIdsByNamesAndServiceId(accessTypes, xPolicy.getService());
+
+            for (String accessType : accessTypes) {
+                Long accessDefId = nameToId.get(accessType);
+
+                if (accessDefId == null) {
+                    throw new Exception(accessType + ": is not a valid access-type. policy='" + policy.getName() + "' service='" + policy.getService() + "'");
+                }
+
+                XXPolicyRefAccessType xPolAccess = new XXPolicyRefAccessType();
+
+                xPolAccess.setPolicyId(policy.getId());
+                xPolAccess.setAccessDefId(accessDefId);
+                xPolAccess.setAccessTypeName(accessType);
+
+                xPolAccesses.add(xPolAccess);
+            }
+
+            batchInsert(xPolAccesses, daoMgr.getXXPolicyRefAccessType(), oldBulkMode);
+        }
+
+        if (CollectionUtils.isNotEmpty(conditionTypes)) {
+            List<XXPolicyRefCondition> xPolConds = new ArrayList<>();
+            Map<String, Long>          nameToId  = daoMgr.getXXPolicyConditionDef().findConditionDefIdsByServiceDefIdAndNames(xServiceDef.getId(), conditionTypes);
+
+            for (String condition : conditionTypes) {
+                Long conditionDefId = nameToId.get(condition);
+
+                if (conditionDefId == null) {
+                    if (StringUtils.equalsIgnoreCase(condition, ServiceDefUtil.IMPLICIT_CONDITION_EXPRESSION_NAME)) {
+                        continue;
+                    }
+
+                    throw new Exception(condition + ": is not a valid condition-type. policy='" + xPolicy.getName() + "' service='" + xPolicy.getService() + "'");
+                }
+
+                XXPolicyRefCondition xPolCond = new XXPolicyRefCondition();
+
+                xPolCond.setPolicyId(policy.getId());
+                xPolCond.setConditionDefId(conditionDefId);
+                xPolCond.setConditionName(condition);
+
+                xPolConds.add(xPolCond);
+            }
+
+            batchInsert(xPolConds, daoMgr.getXXPolicyRefCondition(), oldBulkMode);
+        }
+
+        if (CollectionUtils.isNotEmpty(dataMaskTypes)) {
+            List<XXPolicyRefDataMaskType> xxDataMaskInfos = new ArrayList<>();
+            Map<String, Long>             nameToId        = daoMgr.getXXDataMaskTypeDef().findDataMaskTypeDefIdsByNamesAndServiceId(dataMaskTypes, xPolicy.getService());
+
+            for (String dataMaskType : dataMaskTypes) {
+                Long dataMaskDefId = nameToId.get(dataMaskType);
+
+                if (dataMaskDefId == null) {
+                    throw new Exception(dataMaskType + ": is not a valid datamask-type. policy='" + policy.getName() + "' service='" + policy.getService() + "'");
+                }
+
+                XXPolicyRefDataMaskType xxDataMaskInfo = new XXPolicyRefDataMaskType();
+
+                xxDataMaskInfo.setPolicyId(policy.getId());
+                xxDataMaskInfo.setDataMaskDefId(dataMaskDefId);
+                xxDataMaskInfo.setDataMaskTypeName(dataMaskType);
+
+                xxDataMaskInfos.add(xxDataMaskInfo);
+            }
+
+            batchInsert(xxDataMaskInfos, daoMgr.getXXPolicyRefDataMaskType(), oldBulkMode);
+        }
+    }
+
+    public Boolean cleanupRefTables(RangerPolicy policy) {
+        final Long policyId = policy == null ? null : policy.getId();
+
+        if (policyId == null) {
+            return false;
+        }
+
+        daoMgr.getXXPolicyRefResource().deleteByPolicyId(policyId);
+        daoMgr.getXXPolicyRefRole().deleteByPolicyId(policyId);
+        daoMgr.getXXPolicyRefGroup().deleteByPolicyId(policyId);
+        daoMgr.getXXPolicyRefUser().deleteByPolicyId(policyId);
+        daoMgr.getXXPolicyRefAccessType().deleteByPolicyId(policyId);
+        daoMgr.getXXPolicyRefCondition().deleteByPolicyId(policyId);
+        daoMgr.getXXPolicyRefDataMaskType().deleteByPolicyId(policyId);
+
+        return true;
+    }
+
+    /**
+     * Cleans up reference tables for a given policy before updating it.
+     * This includes handling policy reference users, roles, and other
+     * associated reference entities like resources, groups, access types,
+     * conditions, and data mask types.
+     *
+     * @param policyId      ID of the policy being updated.
+     * @param policyUsers   Set of usernames associated with the updated policy.
+     * @param policyRoles   Set of role names associated with the updated policy.
+     * @param policyGroups   Set of group names associated with the updated policy.
+     * @return              true if cleanup was successful.
+     */
+    public Boolean cleanupRefTablesForUpdate(Long policyId, Set<String> policyUsers, Set<String> policyRoles, Set<String> policyGroups) {
+        cleanupPolicyRefUsers(policyUsers, policyId, daoMgr.getXXPolicyRefUser());
+        cleanupPolicyRefRoles(policyRoles, policyId, daoMgr.getXXPolicyRefRole());
+        cleanupPolicyRefGroups(policyGroups, policyId, daoMgr.getXXPolicyRefGroup());
+
+        daoMgr.getXXPolicyRefResource().deleteByPolicyId(policyId);
+        daoMgr.getXXPolicyRefAccessType().deleteByPolicyId(policyId);
+        daoMgr.getXXPolicyRefCondition().deleteByPolicyId(policyId);
+        daoMgr.getXXPolicyRefDataMaskType().deleteByPolicyId(policyId);
+
+        return true;
+    }
+
+    /**
+     * Identifies and deletes outdated user references for a given policy,
+     * and prepares a list of new users that need to be inserted.
+     *
+     * @param policyUsers   Set of usernames from the new policy.
+     * @param policyId      The ID of the policy.
+     * @param dao           DAO for policy reference users.
+     */
+    public void cleanupPolicyRefUsers(Set<String> policyUsers, Long policyId, XXPolicyRefUserDao dao) {
+        Map<String, Long> policyUserNameIdMap = dao.findUserNameIdByPolicyId(policyId);
+
+        if (policyUserNameIdMap != null && !policyUserNameIdMap.isEmpty()) {
+            Set<String> existingPolicyRefUsers = policyUserNameIdMap.keySet();
+            Set<String> toDeletePolicyRefUsers = new HashSet<>(existingPolicyRefUsers);
+            Set<String> commonUsers            = new HashSet<>(policyUsers);
+
+            // Identify users present in both new and existing sets
+            commonUsers.retainAll(toDeletePolicyRefUsers);
+
+            // Identify users to delete (in DB but not in new set)
+            toDeletePolicyRefUsers.removeAll(commonUsers);
+
+            // Remove already existing users from the new set (they don’t need to be inserted again)
+            policyUsers.removeAll(commonUsers);
+
+            if (CollectionUtils.isNotEmpty(toDeletePolicyRefUsers)) {
+                List<Long> idsToDelete = toDeletePolicyRefUsers.stream()
+                        .map(policyUserNameIdMap::get)
+                        .filter(Objects::nonNull)
+                        .collect(Collectors.toList());
+
+                LOG.debug("Deleting user IDs from x_policy_ref_user table: {} for policy ID: {}", idsToDelete, policyId);
+
+                dao.deletePolicyRefUserByIds(idsToDelete);
+            }
+        }
+    }
+
+    /**
+     * Identifies and deletes outdated role references for a given policy,
+     * and prepares a list of new roles that need to be inserted.
+     *
+     * @param policyRoles   Set of role names from the new policy.
+     * @param policyId      The ID of the policy.
+     * @param dao           DAO for policy reference roles.
+     */
+    public void cleanupPolicyRefRoles(Set<String> policyRoles, Long policyId, XXPolicyRefRoleDao dao) {
+        Map<String, Long> policyRoleNameIdMap = dao.findRoleNameIdByPolicyId(policyId);
+
+        if (policyRoleNameIdMap != null && !policyRoleNameIdMap.isEmpty()) {
+            Set<String> existingPolicyRefRoles = policyRoleNameIdMap.keySet();
+            Set<String> toDeletePolicyRefRoles = new HashSet<>(existingPolicyRefRoles);
+            Set<String> commonRoles            = new HashSet<>(policyRoles);
+
+            // Identify roles present in both new and existing sets
+            commonRoles.retainAll(toDeletePolicyRefRoles);
+
+            // Identify roles to delete (in DB but not in new set)
+            toDeletePolicyRefRoles.removeAll(commonRoles);
+
+            // Remove already existing roles from the new set (they don’t need to be inserted again)
+            policyRoles.removeAll(commonRoles);
+
+            if (CollectionUtils.isNotEmpty(toDeletePolicyRefRoles)) {
+                List<Long> idsToDelete = toDeletePolicyRefRoles.stream()
+                        .map(policyRoleNameIdMap::get)
+                        .filter(Objects::nonNull)
+                        .collect(Collectors.toList());
+
+                LOG.debug("Deleting Role IDs from x_policy_ref_role: {} for policy ID: {}", idsToDelete, policyId);
+
+                dao.deletePolicyRefRoleByIds(idsToDelete);
+            }
+        }
+    }
+
+    /**
+     * Identifies and deletes outdated group references for a given policy,
+     * and prepares a list of new groups that need to be inserted.
+     *
+     * @param policyGroups   Set of group names from the new policy.
+     * @param policyId       The ID of the policy.
+     * @param dao            DAO for policy reference groups.
+     */
+    public void cleanupPolicyRefGroups(Set<String> policyGroups, Long policyId, XXPolicyRefGroupDao dao) {
+        Map<String, Long> policyGroupNameIdMap = dao.findGroupNameByPolicyId(policyId);
+
+        if (policyGroupNameIdMap != null && !policyGroupNameIdMap.isEmpty()) {
+            Set<String> existingPolicyRefGroups = policyGroupNameIdMap.keySet();
+            Set<String> toDeletePolicyRefGroups = new HashSet<>(existingPolicyRefGroups);
+            Set<String> commonGroups            = new HashSet<>(policyGroups);
+
+            // Identify groups present in both new and existing sets
+            commonGroups.retainAll(toDeletePolicyRefGroups);
+
+            // Identify groups to delete (in DB but not in new set)
+            toDeletePolicyRefGroups.removeAll(commonGroups);
+
+            // Remove already existing groups from the new set (they don’t need to be inserted again)
+            policyGroups.removeAll(commonGroups);
+
+            if (CollectionUtils.isNotEmpty(toDeletePolicyRefGroups)) {
+                List<Long> idsToDelete = toDeletePolicyRefGroups.stream()
+                        .map(policyGroupNameIdMap::get)
+                        .filter(Objects::nonNull)
+                        .collect(Collectors.toList());
+
+                LOG.debug("Deleting Group IDs from x_policy_ref_group: {} for policy ID: {}", idsToDelete, policyId);
+
+                dao.deletePolicyRefGroupByIds(idsToDelete);
+            }
+        }
+    }
+
+    public enum PRINCIPAL_TYPE { USER, GROUP, ROLE }
+
+    private boolean doesPolicyExist(XXPolicy policy) {
+        return daoMgr.getXXPolicy().getById(policy.getId()) != null;
+    }
+
+    private class PolicyRoleAssociator implements Runnable {
+        private final String   name;
+        private final Long     roleId;
+        private final XXPolicy xPolicy;
+
+        PolicyRoleAssociator(String name, Long roleId, XXPolicy xPolicy) {
+            this.name    = name;
+            this.roleId  = roleId;
+            this.xPolicy = xPolicy;
+        }
+
+        public XXPolicyRefRole getPolicyRef() {
+            Long id = resolveRoleId(false);
+
+            if (id != null && doesPolicyExist(xPolicy)) {
+                XXPolicyRefRole xPolRole = new XXPolicyRefRole();
+
+                xPolRole.setPolicyId(xPolicy.getId());
+                xPolRole.setRoleId(id);
+                xPolRole.setRoleName(name);
+
+                return xPolRole;
+            }
+
+            return null;
+        }
+
+        public void createPolicyRef(Long id) {
+            if (doesPolicyExist(xPolicy)) {
+                XXPolicyRefRole xPolRole = new XXPolicyRefRole();
+
+                xPolRole.setPolicyId(xPolicy.getId());
+                xPolRole.setRoleId(id);
+                xPolRole.setRoleName(name);
+
+                daoMgr.getXXPolicyRefRole().create(xPolRole);
+            } else {
+                LOG.info("Policy with id ={} does not exist, skipping policy association!", xPolicy.getId());
+            }
+        }
+
+        @Override
+        public void run() {
+            Long id = resolveRoleId(true);
+
+            if (id != null) {
+                createPolicyRef(id);
+
+                LOG.debug("Associated ROLE:{} with policy id:[{}]", name, xPolicy.getId());
+            } else {
+                throw new RuntimeException("Failed to associate ROLE:" + name + " with policy id:[" + xPolicy.getId() + "]");
+            }
+        }
+
+        private Long resolveRoleId(boolean createIfAbsent) {
+            Long ret = roleId;
+
+            if (ret == null) {
+                XXRole xRole = daoMgr.getXXRole().findByRoleName(name);
+
+                if (xRole != null) {
+                    ret = xRole.getId();
+                } else if (createIfAbsent) {
+                    RangerBizUtil.setBulkMode(false);
+
+                    ret = createRole();
+                }
+            }
+
+            return ret;
+        }
+
+        private Long createRole() {
+            LOG.warn("Role specified in policy does not exist in ranger admin, creating new role, name = {}", name);
+
+            try {
+                RangerRole rRole       = new RangerRole(name, null, null, null, null);
+                RangerRole createdRole = roleStore.createRole(rRole, false);
+
+                return createdRole.getId();
+            } catch (Exception e) {
+                return null;
+            }
+        }
+    }
+
+    private class PolicyGroupAssociator implements Runnable {
+        private final String   name;
+        private final Long     groupId;
+        private final XXPolicy xPolicy;
+
+        PolicyGroupAssociator(String name, Long groupId, XXPolicy xPolicy) {
+            this.name     = name;
+            this.groupId  = groupId;
+            this.xPolicy  = xPolicy;
+        }
+
+        public XXPolicyRefGroup getPolicyRef() {
+            Long id = resolveGroupId(false);
+
+            if (id != null && doesPolicyExist(xPolicy)) {
+                XXPolicyRefGroup xPolGroup = new XXPolicyRefGroup();
+
+                xPolGroup.setPolicyId(xPolicy.getId());
+                xPolGroup.setGroupId(id);
+                xPolGroup.setGroupName(name);
+
+                return xPolGroup;
+            }
+
+            return null;
+        }
+
+        public void createPolicyRef(Long id) {
+            if (doesPolicyExist(xPolicy)) {
+                XXPolicyRefGroup xPolGroup = new XXPolicyRefGroup();
+
+                xPolGroup.setPolicyId(xPolicy.getId());
+                xPolGroup.setGroupId(id);
+                xPolGroup.setGroupName(name);
+
+                daoMgr.getXXPolicyRefGroup().create(xPolGroup);
+            } else {
+                LOG.info("Policy with id ={} does not exist, skipping policy association!", xPolicy.getId());
+            }
+        }
+
+        @Override
+        public void run() {
+            Long id = resolveGroupId(true);
+
+            if (id != null) {
+                createPolicyRef(id);
+
+                LOG.debug("Associated GROUP:{} with policy id:[{}]", name, xPolicy.getId());
+            } else {
+                throw new RuntimeException("Failed to associate GROUP:" + name + " with policy id:[" + xPolicy.getId() + "]");
+            }
+        }
+
+        private Long resolveGroupId(boolean createIfAbsent) {
+            Long ret = groupId;
+
+            if (ret == null) {
+                XXGroup xGroup = daoMgr.getXXGroup().findByGroupName(name);
+
+                if (xGroup != null) {
+                    ret = xGroup.getId();
+                } else if (createIfAbsent) {
+                    ret = createGroup();
+                }
+            }
+
+            return ret;
+        }
+
+        private Long createGroup() {
+            LOG.warn("Group specified in policy does not exist in ranger admin, creating new group, name = {}", name);
+
+            VXGroup vxGroup = new VXGroup();
+
+            vxGroup.setName(name);
+            vxGroup.setDescription(name);
+            vxGroup.setGroupSource(RangerCommonEnums.GROUP_EXTERNAL);
+
+            VXGroup vXGroup = xGroupService.createXGroupWithOutLogin(vxGroup);
+
+            if (vXGroup != null) {
+                xGroupService.createTransactionLog(vXGroup, null, OPERATION_CREATE_CONTEXT, xPolicy.getAddedByUserId());
+
+                return vXGroup.getId();
+            }
+
+            return null;
+        }
+    }
+
+    private class PolicyUserAssociator implements Runnable {
+        private final String   name;
+        private final Long     userId;
+        private final XXPolicy xPolicy;
+
+        PolicyUserAssociator(String name, Long userId, XXPolicy xPolicy) {
+            this.name    = name;
+            this.userId  = userId;
+            this.xPolicy = xPolicy;
+        }
+
+        public XXPolicyRefUser getPolicyRef() {
+            Long id = resolveUserId(false);
+
+            if (id != null && doesPolicyExist(xPolicy)) {
+                XXPolicyRefUser xPolUser = new XXPolicyRefUser();
+
+                xPolUser.setPolicyId(xPolicy.getId());
+                xPolUser.setUserId(id);
+                xPolUser.setUserName(name);
+
+                return xPolUser;
+            }
+
+            return null;
+        }
+
+        public void createPolicyRef(Long id) {
+            if (doesPolicyExist(xPolicy)) {
+                XXPolicyRefUser xPolUser = new XXPolicyRefUser();
+
+                xPolUser.setPolicyId(xPolicy.getId());
+                xPolUser.setUserId(id);
+                xPolUser.setUserName(name);
+
+                daoMgr.getXXPolicyRefUser().create(xPolUser);
+            } else {
+                LOG.info("Policy with id ={} does not exist, skipping policy association!", xPolicy.getId());
+            }
+        }
+
+        @Override
+        public void run() {
+            Long id = resolveUserId(true);
+
+            if (id != null) {
+                createPolicyRef(id);
+
+                LOG.debug("Associated USER:{} with policy id:[{}]", name, xPolicy.getId());
+            } else {
+                throw new RuntimeException("Failed to associate USER:" + name + " with policy id:[" + xPolicy.getId() + "]");
+            }
+        }
+
+        private Long resolveUserId(boolean createIfAbsent) {
+            Long ret = userId;
+
+            if (ret == null) {
+                XXUser xUser = daoMgr.getXXUser().findByUserName(name);
+
+                if (xUser != null) {
+                    ret = xUser.getId();
+                } else if (createIfAbsent) {
+                    return createUser();
+                }
+            }
+
+            return ret;
+        }
+
+        private Long createUser() {
+            LOG.warn("User specified in policy does not exist in ranger admin, creating new user, name = {}", name);
 
-	private static final Logger LOG = LoggerFactory.getLogger(PolicyRefUpdater.class);
+            VXUser vXUser = xUserMgr.createServiceConfigUser(name);
 
-	public enum PRINCIPAL_TYPE { USER, GROUP, ROLE }
+            if (vXUser != null) {
+                XXUser xUser = daoMgr.getXXUser().findByUserName(name);
 
-	@Autowired
-	RangerDaoManager daoMgr;
+                if (xUser == null) {
+                    LOG.error("No User created!! Irrecoverable error! [{}]", name);
+                } else {
+                    return xUser.getId();
+                }
+            } else {
+                LOG.warn("serviceConfigUser:[{}] creation failed. This may be a transient/spurious condition that may correct itself when transaction is committed", name);
+            }
 
-	@Autowired
-	XUserMgr xUserMgr;
+            return null;
+        }
+    }
 
-	@Autowired
-	RoleDBStore roleStore;
-
-	@Autowired
-	RangerBizUtil rangerBizUtil;
-
-	@Autowired
-	XGroupService xGroupService;
-
-	@Autowired
-	RangerTransactionSynchronizationAdapter rangerTransactionSynchronizationAdapter;
-
-	@Autowired
-	RESTErrorUtil restErrorUtil;
-
-	public void createNewPolMappingForRefTable(RangerPolicy policy, XXPolicy xPolicy, XXServiceDef xServiceDef, boolean createPrincipalsIfAbsent) throws Exception {
-		if(policy == null) {
-			return;
-		}
-
-		cleanupRefTables(policy);
-
-		final Set<String> resourceNames   = policy.getResources().keySet();
-		final Set<String> roleNames       = new HashSet<>();
-		final Set<String> groupNames      = new HashSet<>();
-		final Set<String> userNames       = new HashSet<>();
-		final Set<String> accessTypes     = new HashSet<>();
-		final Set<String> conditionTypes  = new HashSet<>();
-		final Set<String> dataMaskTypes   = new HashSet<>();
-		boolean oldBulkMode = RangerBizUtil.isBulkMode();
-
-		List<RangerPolicy.RangerPolicyItemCondition> rangerPolicyConditions = policy.getConditions();
-		if (CollectionUtils.isNotEmpty(rangerPolicyConditions)) {
-			for (RangerPolicy.RangerPolicyItemCondition condition : rangerPolicyConditions) {
-				conditionTypes.add(condition.getType());
-			}
-		}
-
-		for (List<? extends RangerPolicyItem> policyItems :  getAllPolicyItems(policy)) {
-			if (CollectionUtils.isEmpty(policyItems)) {
-				continue;
-			}
-
-			for (RangerPolicyItem policyItem : policyItems) {
-				roleNames.addAll(policyItem.getRoles());
-				groupNames.addAll(policyItem.getGroups());
-				userNames.addAll(policyItem.getUsers());
-
-				if (CollectionUtils.isNotEmpty(policyItem.getAccesses())) {
-					for (RangerPolicyItemAccess access : policyItem.getAccesses()) {
-						accessTypes.add(access.getType());
-					}
-				}
-
-				if (CollectionUtils.isNotEmpty(policyItem.getConditions())) {
-					for (RangerPolicyItemCondition condition : policyItem.getConditions()) {
-						conditionTypes.add(condition.getType());
-					}
-				}
-
-				if (policyItem instanceof RangerDataMaskPolicyItem) {
-					RangerPolicyItemDataMaskInfo dataMaskInfo = ((RangerDataMaskPolicyItem) policyItem).getDataMaskInfo();
-
-					dataMaskTypes.add(dataMaskInfo.getDataMaskType());
-				}
-			}
-		}
-
-		List<XXPolicyRefResource> xPolResources = new ArrayList<>();
-		for (String resource : resourceNames) {
-			XXResourceDef xResDef = daoMgr.getXXResourceDef().findByNameAndPolicyId(resource, policy.getId());
-
-			if (xResDef == null) {
-				throw new Exception(resource + ": is not a valid resource-type. policy='"+  policy.getName() + "' service='"+ policy.getService() + "'");
-			}
-
-			XXPolicyRefResource xPolRes = new XXPolicyRefResource();
-
-			xPolRes.setPolicyId(policy.getId());
-			xPolRes.setResourceDefId(xResDef.getId());
-			xPolRes.setResourceName(resource);
-
-			xPolResources.add(xPolRes);
-		}
-		daoMgr.getXXPolicyRefResource().batchCreate(xPolResources);
-
-		if (createPrincipalsIfAbsent && !rangerBizUtil.checkAdminAccess()) {
-			LOG.warn("policy=" + policy.getName() + ": createPrincipalIfAbsent=true, but current user does not have admin privileges!");
-
-			createPrincipalsIfAbsent = false;
-		}
-
-		List<XXPolicyRefRole> xPolRoles = new ArrayList<>();
-		for (String role : roleNames) {
-			if (StringUtils.isBlank(role)) {
-				continue;
-			}
-			PolicyPrincipalAssociator associator = new PolicyPrincipalAssociator(PRINCIPAL_TYPE.ROLE, role, xPolicy);
-			if (!associator.doAssociate(false)) {
-				if (createPrincipalsIfAbsent) {
-					rangerTransactionSynchronizationAdapter.executeOnTransactionCommit(associator);
-				} else {
-					VXResponse gjResponse = new VXResponse();
-					gjResponse.setStatusCode(HttpServletResponse.SC_BAD_REQUEST);
-					gjResponse.setMsgDesc("Operation denied. Role name: " + role + " specified in policy does not exist in ranger admin.");
-					throw restErrorUtil.generateRESTException(gjResponse);
-				}
-			}
-		}
-		RangerBizUtil.setBulkMode(oldBulkMode);
-		daoMgr.getXXPolicyRefRole().batchCreate(xPolRoles);
-
-		for (String group : groupNames) {
-			if (StringUtils.isBlank(group)) {
-				continue;
-			}
-
-			PolicyPrincipalAssociator associator = new PolicyPrincipalAssociator(PRINCIPAL_TYPE.GROUP, group, xPolicy);
-			if (!associator.doAssociate(false)) {
-				if (createPrincipalsIfAbsent) {
-					rangerTransactionSynchronizationAdapter.executeOnTransactionCommit(associator);
-				} else {
-					VXResponse gjResponse = new VXResponse();
-					gjResponse.setStatusCode(HttpServletResponse.SC_BAD_REQUEST);
-					gjResponse.setMsgDesc("Operation denied. Group name: " + group + " specified in policy does not exist in ranger admin.");
-					throw restErrorUtil.generateRESTException(gjResponse);
-				}
-			}
-		}
-
-		for (String user : userNames) {
-			if (StringUtils.isBlank(user)) {
-				continue;
-			}
-			PolicyPrincipalAssociator associator = new PolicyPrincipalAssociator(PRINCIPAL_TYPE.USER, user, xPolicy);
-			if (!associator.doAssociate(false)) {
-				if (createPrincipalsIfAbsent) {
-					rangerTransactionSynchronizationAdapter.executeOnTransactionCommit(associator);
-				} else {
-					VXResponse gjResponse = new VXResponse();
-					gjResponse.setStatusCode(HttpServletResponse.SC_BAD_REQUEST);
-					gjResponse.setMsgDesc("Operation denied. User name: " + user + " specified in policy does not exist in ranger admin.");
-					throw restErrorUtil.generateRESTException(gjResponse);
-				}
-			}
-		}
-
-		List<XXPolicyRefAccessType> xPolAccesses = new ArrayList<>();
-
-		// ignore built-in access-types while creating ref-table entries
-		accessTypes.removeAll(ServiceDefUtil.ACCESS_TYPE_MARKERS);
-
-		for (String accessType : accessTypes) {
-			XXAccessTypeDef xAccTypeDef = daoMgr.getXXAccessTypeDef().findByNameAndServiceId(accessType, xPolicy.getService());
-
-			if (xAccTypeDef == null) {
-				throw new Exception(accessType + ": is not a valid access-type. policy='" + policy.getName() + "' service='" + policy.getService() + "'");
-			}
-
-			XXPolicyRefAccessType xPolAccess = new XXPolicyRefAccessType();
-
-			xPolAccess.setPolicyId(policy.getId());
-			xPolAccess.setAccessDefId(xAccTypeDef.getId());
-			xPolAccess.setAccessTypeName(accessType);
-
-			xPolAccesses.add(xPolAccess);
-		}
-		daoMgr.getXXPolicyRefAccessType().batchCreate(xPolAccesses);
-
-		List<XXPolicyRefCondition> xPolConds = new ArrayList<>();
-		for (String condition : conditionTypes) {
-			XXPolicyConditionDef xPolCondDef = daoMgr.getXXPolicyConditionDef().findByServiceDefIdAndName(xServiceDef.getId(), condition);
-
-			if (xPolCondDef == null) {
-				if (StringUtils.equalsIgnoreCase(condition, ServiceDefUtil.IMPLICIT_CONDITION_EXPRESSION_NAME)) {
-					continue;
-				}
-
-				throw new Exception(condition + ": is not a valid condition-type. policy='"+  xPolicy.getName() + "' service='"+ xPolicy.getService() + "'");
-			}
-
-			XXPolicyRefCondition xPolCond = new XXPolicyRefCondition();
-
-			xPolCond.setPolicyId(policy.getId());
-			xPolCond.setConditionDefId(xPolCondDef.getId());
-			xPolCond.setConditionName(condition);
-
-			xPolConds.add(xPolCond);
-		}
-		daoMgr.getXXPolicyRefCondition().batchCreate(xPolConds);
-
-		List<XXPolicyRefDataMaskType> xxDataMaskInfos = new ArrayList<>();
-		for (String dataMaskType : dataMaskTypes ) {
-			XXDataMaskTypeDef dataMaskDef = daoMgr.getXXDataMaskTypeDef().findByNameAndServiceId(dataMaskType, xPolicy.getService());
-
-			if (dataMaskDef == null) {
-				throw new Exception(dataMaskType + ": is not a valid datamask-type. policy='" + policy.getName() + "' service='" + policy.getService() + "'");
-			}
-
-			XXPolicyRefDataMaskType xxDataMaskInfo = new XXPolicyRefDataMaskType();
-
-			xxDataMaskInfo.setPolicyId(policy.getId());
-			xxDataMaskInfo.setDataMaskDefId(dataMaskDef.getId());
-			xxDataMaskInfo.setDataMaskTypeName(dataMaskType);
-
-			xxDataMaskInfos.add(xxDataMaskInfo);
-		}
-		daoMgr.getXXPolicyRefDataMaskType().batchCreate(xxDataMaskInfos);
-	}
-
-	private class PolicyPrincipalAssociator implements Runnable {
-		final PRINCIPAL_TYPE type;
-		final String    name;
-		final XXPolicy  xPolicy;
-
-		public PolicyPrincipalAssociator(PRINCIPAL_TYPE type, String name, XXPolicy xPolicy) {
-			this.type    = type;
-			this.name    = name;
-			this.xPolicy = xPolicy;
-		}
-
-		@Override
-		public void run() {
-			if (doAssociate(true)) {
-				if (LOG.isDebugEnabled()) {
-					LOG.debug("Associated " + type.name() + ":" + name + " with policy id:[" + xPolicy.getId() + "]");
-				}
-			} else {
-				throw new RuntimeException("Failed to associate " + type.name() + ":" + name + " with policy id:[" + xPolicy.getId() + "]");
-			}
-		}
-
-		boolean doAssociate(boolean isAdmin) {
-			if (LOG.isDebugEnabled()) {
-				LOG.debug("===> PolicyPrincipalAssociator.doAssociate(" + isAdmin + ")");
-			}
-			final boolean ret;
-
-			Long id = createOrGetPrincipal(isAdmin);
-			if (id != null) {
-				// associate with policy
-				createPolicyAssociation(id, name);
-				ret = true;
-			} else {
-				ret = false;
-			}
-
-			if (LOG.isDebugEnabled()) {
-				LOG.debug("<=== PolicyPrincipalAssociator.doAssociate(" + isAdmin + ") : " + ret);
-			}
-			return ret;
-		}
-
-		private Long createOrGetPrincipal(final boolean createIfAbsent) {
-			if (LOG.isDebugEnabled()) {
-				LOG.debug("===> PolicyPrincipalAssociator.createOrGetPrincipal(" + createIfAbsent + ")");
-			}
-
-			Long ret = null;
-
-			switch (type) {
-				case USER: {
-					XXUser xUser = daoMgr.getXXUser().findByUserName(name);
-					if (xUser != null) {
-						ret = xUser.getId();
-					} else {
-						if (createIfAbsent) {
-							ret = createPrincipal(name);
-						}
-					}
-				}
-				break;
-				case GROUP: {
-					XXGroup xGroup = daoMgr.getXXGroup().findByGroupName(name);
-
-					if (xGroup != null) {
-						ret = xGroup.getId();
-					} else {
-						if (createIfAbsent) {
-							ret = createPrincipal(name);
-						}
-					}
-				}
-				break;
-				case ROLE: {
-					XXRole xRole = daoMgr.getXXRole().findByRoleName(name);
-					if (xRole != null) {
-						ret = xRole.getId();
-					} else {
-						if (createIfAbsent) {
-							RangerBizUtil.setBulkMode(false);
-							ret = createPrincipal(name);
-						}
-					}
-				}
-				break;
-				default:
-					break;
-			}
-			if (LOG.isDebugEnabled()) {
-				LOG.debug("<=== PolicyPrincipalAssociator.createOrGetPrincipal(" + createIfAbsent + ") : " + ret);
-			}
-			return ret;
-		}
-
-		private Long createPrincipal(String user) {
-			LOG.warn("User specified in policy does not exist in ranger admin, creating new user, Type: " + type.name() + ", name = " + user);
-
-			if (LOG.isDebugEnabled()) {
-				LOG.debug("===> PolicyPrincipalAssociator.createPrincipal(type=" + type.name() +", name=" + name + ")");
-			}
-
-			Long ret = null;
-
-			switch (type) {
-				case USER: {
-					// Create External user
-					VXUser vXUser = xUserMgr.createServiceConfigUser(name);
-					if (vXUser != null) {
-						XXUser xUser = daoMgr.getXXUser().findByUserName(name);
-
-						if (xUser == null) {
-							LOG.error("No User created!! Irrecoverable error! [" + name + "]");
-						} else {
-							ret = xUser.getId();
-						}
-					} else {
-						LOG.warn("serviceConfigUser:[" + name + "] creation failed. This may be a transient/spurious condition that may correct itself when transaction is committed");
-					}
-				}
-				break;
-				case GROUP: {
-					// Create group
-					VXGroup vxGroup = new VXGroup();
-					vxGroup.setName(name);
-					vxGroup.setDescription(name);
-					vxGroup.setGroupSource(RangerCommonEnums.GROUP_EXTERNAL);
-					VXGroup vXGroup = xGroupService.createXGroupWithOutLogin(vxGroup);
-					if (vXGroup != null) {
-						xGroupService.createTransactionLog(vXGroup, null, OPERATION_CREATE_CONTEXT, xPolicy.getAddedByUserId());
-
-						ret = vXGroup.getId();
-					}
-				}
-				break;
-				case ROLE: {
-					try {
-						RangerRole rRole = new RangerRole(name, null, null, null, null);
-						RangerRole createdRole = roleStore.createRole(rRole, false);
-						ret = createdRole.getId();
-					} catch (Exception e) {
-						// Ignore
-					}
-				}
-				break;
-				default:
-					break;
-			}
-			if (LOG.isDebugEnabled()) {
-				LOG.debug("<=== PolicyPrincipalAssociator.createPrincipal(type=" + type.name() + ", name=" + name + ") : " + ret);
-			}
-			return ret;
-		}
-
-		private void createPolicyAssociation(Long id, String name) {
-			if(LOG.isDebugEnabled()) {
-				LOG.debug("===> PolicyPrincipalAssociator.createPolicyAssociation(policyId=" + xPolicy.getId() + ", type=" + type.name() + ", name=" + name + ", id=" + id + ")");
-			}
-			switch (type) {
-				case USER: {
-					XXPolicyRefUser xPolUser = new XXPolicyRefUser();
-
-					xPolUser.setPolicyId(xPolicy.getId());
-					xPolUser.setUserId(id);
-					xPolUser.setUserName(name);
-					daoMgr.getXXPolicyRefUser().create(xPolUser);
-				}
-				break;
-				case GROUP: {
-					XXPolicyRefGroup xPolGroup = new XXPolicyRefGroup();
-
-					xPolGroup.setPolicyId(xPolicy.getId());
-					xPolGroup.setGroupId(id);
-					xPolGroup.setGroupName(name);
-					daoMgr.getXXPolicyRefGroup().create(xPolGroup);
-				}
-				break;
-				case ROLE: {
-					XXPolicyRefRole xPolRole = new XXPolicyRefRole();
-
-					xPolRole.setPolicyId(xPolicy.getId());
-					xPolRole.setRoleId(id);
-					xPolRole.setRoleName(name);
-					daoMgr.getXXPolicyRefRole().create(xPolRole);
-				}
-				break;
-				default:
-					break;
-			}
-			if(LOG.isDebugEnabled()) {
-				LOG.debug("<=== PolicyPrincipalAssociator.createPolicyAssociation(policyId=" + xPolicy.getId() + ", type=" + type.name() + ", name=" + name + ", id=" + id + ")");
-			}
-		}
-	}
-
-	public Boolean cleanupRefTables(RangerPolicy policy) {
-		final Long policyId = policy == null ? null : policy.getId();
-
-		if (policyId == null) {
-			return false;
-		}
-
-		daoMgr.getXXPolicyRefResource().deleteByPolicyId(policyId);
-		daoMgr.getXXPolicyRefRole().deleteByPolicyId(policyId);
-		daoMgr.getXXPolicyRefGroup().deleteByPolicyId(policyId);
-		daoMgr.getXXPolicyRefUser().deleteByPolicyId(policyId);
-		daoMgr.getXXPolicyRefAccessType().deleteByPolicyId(policyId);
-		daoMgr.getXXPolicyRefCondition().deleteByPolicyId(policyId);
-		daoMgr.getXXPolicyRefDataMaskType().deleteByPolicyId(policyId);
-
-		return true;
-	}
-
-	public static List<List<? extends RangerPolicyItem>> getAllPolicyItems(RangerPolicy policy) {
-		List<List<? extends RangerPolicyItem>> ret = new ArrayList<>();
-
-		if (CollectionUtils.isNotEmpty(policy.getPolicyItems())) {
-			ret.add(policy.getPolicyItems());
-		}
-
-		if (CollectionUtils.isNotEmpty(policy.getDenyPolicyItems())) {
-			ret.add(policy.getDenyPolicyItems());
-		}
-
-		if (CollectionUtils.isNotEmpty(policy.getAllowExceptions())) {
-			ret.add(policy.getAllowExceptions());
-		}
-
-		if (CollectionUtils.isNotEmpty(policy.getDenyExceptions())) {
-			ret.add(policy.getDenyExceptions());
-		}
-
-		if (CollectionUtils.isNotEmpty(policy.getDataMaskPolicyItems())) {
-			ret.add(policy.getDataMaskPolicyItems());
-		}
-
-		if (CollectionUtils.isNotEmpty(policy.getRowFilterPolicyItems())) {
-			ret.add(policy.getRowFilterPolicyItems());
-		}
-
-		return ret;
-	}
+    private <T> void batchInsert(List<T> entities, BaseDao<T> dao, boolean oldBulkMode) {
+        if (CollectionUtils.isNotEmpty(entities)) {
+            long startTimeMs = System.currentTimeMillis();
 
+            LOG.debug("Batch insert started for create/update {} with {} records.", dao.getClass().getSimpleName(), entities.size());
+
+            RangerBizUtil.setBulkMode(false);
+            dao.batchCreate(entities);
+            RangerBizUtil.setBulkMode(oldBulkMode);
+
+            LOG.debug("Batch insert completed for create/update {} with {} records in {} ms.", dao.getClass().getSimpleName(), entities.size(), (System.currentTimeMillis() - startTimeMs));
+        }
+    }
 }
diff --git a/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java b/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java
index dc3802748..501d3e454 100644
--- a/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java
@@ -2132,7 +2132,7 @@ public RangerPolicy createPolicy(RangerPolicy policy, boolean createPrincipalsIf
 		}
 
 		XXPolicy xCreatedPolicy = daoMgr.getXXPolicy().getById(policy.getId());
-		policyRefUpdater.createNewPolMappingForRefTable(policy, xCreatedPolicy, xServiceDef, createPrincipalsIfAbsent);
+		policyRefUpdater.createNewPolMappingForRefTable(policy, xCreatedPolicy, xServiceDef, createPrincipalsIfAbsent, false);
 		createOrMapLabels(xCreatedPolicy, uniquePolicyLabels);
 		RangerPolicy createdPolicy = policyService.getPopulatedViewObject(xCreatedPolicy);
 
@@ -2315,10 +2315,9 @@ public RangerPolicy updatePolicy(RangerPolicy policy) throws Exception {
 		policy = policyService.update(policy);
 		XXPolicy newUpdPolicy = daoMgr.getXXPolicy().getById(policy.getId());
 
-		policyRefUpdater.cleanupRefTables(policy);
 		deleteExistingPolicyLabel(policy);
 
-		policyRefUpdater.createNewPolMappingForRefTable(policy, newUpdPolicy, xServiceDef, bizUtil.getCreatePrincipalsIfAbsent());
+		policyRefUpdater.createNewPolMappingForRefTable(policy, newUpdPolicy, xServiceDef, bizUtil.getCreatePrincipalsIfAbsent(), true);
 		createOrMapLabels(newUpdPolicy, uniquePolicyLabels);
 		RangerPolicy updPolicy = policyService.getPopulatedViewObject(newUpdPolicy);
 
diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXAccessTypeDefDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXAccessTypeDefDao.java
index 8f5749854..3fba90df0 100644
--- a/security-admin/src/main/java/org/apache/ranger/db/XXAccessTypeDefDao.java
+++ b/security-admin/src/main/java/org/apache/ranger/db/XXAccessTypeDefDao.java
@@ -18,16 +18,25 @@
 package org.apache.ranger.db;
 
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 import javax.persistence.NoResultException;
 
+import org.apache.commons.collections.CollectionUtils;
 import org.apache.ranger.common.db.BaseDao;
 import org.apache.ranger.entity.XXAccessTypeDef;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
 
 @Service
 public class XXAccessTypeDefDao extends BaseDao<XXAccessTypeDef> {
+	private static final Logger logger = LoggerFactory.getLogger(XXAccessTypeDefDao.class);
 
 	public XXAccessTypeDefDao(RangerDaoManagerBase daoManager) {
 		super(daoManager);
@@ -60,4 +69,22 @@ public XXAccessTypeDef findByNameAndServiceId(String name, Long serviceId) {
 			return null;
 		}
 	}
+
+	public Map<String, Long> findAccessTypeDefIdsByNamesAndServiceId(Set<String> names, Long serviceId) {
+		if (serviceId != null && CollectionUtils.isNotEmpty(names)) {
+			try {
+				Collection<Object[]> result = getEntityManager()
+						.createNamedQuery("XXAccessTypeDef.findAccessTypeDefIdsByNamesAndServiceId", Object[].class)
+						.setParameter("names", names)
+						.setParameter("serviceId", serviceId)
+						.getResultList();
+
+				return result.stream().collect(Collectors.toMap(object -> (String) object[1], object -> (Long) object[0], (a, b) -> a));
+			} catch (NoResultException e) {
+				logger.debug(e.getMessage());
+			}
+		}
+
+		return Collections.emptyMap();
+	}
 }
diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXDataMaskTypeDefDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXDataMaskTypeDefDao.java
index 83c288127..b0fa07396 100644
--- a/security-admin/src/main/java/org/apache/ranger/db/XXDataMaskTypeDefDao.java
+++ b/security-admin/src/main/java/org/apache/ranger/db/XXDataMaskTypeDefDao.java
@@ -18,16 +18,25 @@
 package org.apache.ranger.db;
 
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 import javax.persistence.NoResultException;
 
+import org.apache.commons.collections.CollectionUtils;
 import org.apache.ranger.common.db.BaseDao;
 import org.apache.ranger.entity.XXDataMaskTypeDef;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
 
 @Service
 public class XXDataMaskTypeDefDao extends BaseDao<XXDataMaskTypeDef> {
+	private static final Logger logger = LoggerFactory.getLogger(XXDataMaskTypeDefDao.class);
 
 	public XXDataMaskTypeDefDao(RangerDaoManagerBase daoManager) {
 		super(daoManager);
@@ -60,4 +69,22 @@ public XXDataMaskTypeDef findByNameAndServiceId(String name, Long serviceId) {
 			return null;
 		}
 	}
+
+	public Map<String, Long> findDataMaskTypeDefIdsByNamesAndServiceId(Set<String> names, Long serviceId) {
+		if (serviceId != null && CollectionUtils.isNotEmpty(names)) {
+			try {
+				Collection<Object[]> result = getEntityManager()
+						.createNamedQuery("XXDataMaskTypeDef.findDataMaskTypeDefIdsByNamesAndServiceId", Object[].class)
+						.setParameter("names", names)
+						.setParameter("serviceId", serviceId)
+						.getResultList();
+
+				return result.stream().collect(Collectors.toMap(object -> (String) object[1], object -> (Long) object[0], (a, b) -> a));
+			} catch (NoResultException e) {
+				logger.debug(e.getMessage());
+			}
+		}
+
+		return Collections.emptyMap();
+	}
 }
diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXGroupDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXGroupDao.java
index 12708f6a3..df7a11216 100644
--- a/security-admin/src/main/java/org/apache/ranger/db/XXGroupDao.java
+++ b/security-admin/src/main/java/org/apache/ranger/db/XXGroupDao.java
@@ -21,10 +21,14 @@
 
 
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
+import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.ranger.authorization.utils.JsonUtils;
 import org.apache.ranger.common.RangerCommonEnums;
@@ -117,6 +121,23 @@ public List<GroupInfo> getAllGroupsInfo() {
 		return ret;
 	}
 
+	public Map<String, Long> getIdsByGroupNames(Collection<String> groupNames) {
+		if (CollectionUtils.isNotEmpty(groupNames)) {
+			try {
+				Collection<Object[]> result = getEntityManager()
+						.createNamedQuery("XXGroup.getIdsByGroupNames", Object[].class)
+						.setParameter("names", groupNames)
+						.getResultList();
+
+				return result.stream().collect(Collectors.toMap(object -> (String) (object[1]), object -> (Long) (object[0])));
+			} catch (NoResultException excp) {
+				logger.debug(excp.getMessage());
+			}
+		}
+
+		return Collections.emptyMap();
+	}
+
 	private GroupInfo toGroupInfo(Object[] row) {
 		String              name        = (String) row[0];
 		String              description = (String) row[1];
diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXPolicyConditionDefDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXPolicyConditionDefDao.java
index de2c47dc4..bae897a6c 100644
--- a/security-admin/src/main/java/org/apache/ranger/db/XXPolicyConditionDefDao.java
+++ b/security-admin/src/main/java/org/apache/ranger/db/XXPolicyConditionDefDao.java
@@ -18,16 +18,25 @@
 package org.apache.ranger.db;
 
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 import javax.persistence.NoResultException;
 
+import org.apache.commons.collections.CollectionUtils;
 import org.apache.ranger.common.db.BaseDao;
 import org.apache.ranger.entity.XXPolicyConditionDef;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
 
 @Service
 public class XXPolicyConditionDefDao extends BaseDao<XXPolicyConditionDef> {
+	private static final Logger logger = LoggerFactory.getLogger(XXPolicyConditionDefDao.class);
 
 	public XXPolicyConditionDefDao(RangerDaoManagerBase daoManager) {
 		super(daoManager);
@@ -61,5 +70,22 @@ public XXPolicyConditionDef findByServiceDefIdAndName(Long serviceDefId, String
 			return null;
 		}
 	}
-	
+
+	public Map<String, Long> findConditionDefIdsByServiceDefIdAndNames(Long serviceDefId, Set<String> names) {
+		if (serviceDefId != null && CollectionUtils.isNotEmpty(names)) {
+			try {
+				Collection<Object[]> result = getEntityManager()
+						.createNamedQuery("XXPolicyConditionDef.findConditionDefIdsByServiceDefIdAndNames", Object[].class)
+						.setParameter("serviceDefId", serviceDefId)
+						.setParameter("names", names)
+						.getResultList();
+
+				return result.stream().collect(Collectors.toMap(object -> (String) object[1], object -> (Long) object[0], (a, b) -> a));
+			} catch (NoResultException e) {
+				logger.debug(e.getMessage());
+			}
+		}
+
+		return Collections.emptyMap();
+	}
 }
diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXPolicyRefGroupDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXPolicyRefGroupDao.java
index 3ce371306..8c5da614b 100644
--- a/security-admin/src/main/java/org/apache/ranger/db/XXPolicyRefGroupDao.java
+++ b/security-admin/src/main/java/org/apache/ranger/db/XXPolicyRefGroupDao.java
@@ -20,8 +20,11 @@
 package org.apache.ranger.db;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 import javax.persistence.NoResultException;
 
@@ -115,4 +118,30 @@ public void deleteByPolicyId(Long policyId) {
 
 		batchDeleteByIds("XXPolicyRefGroup.deleteByIds", ids, "ids");
 	}
+
+	public Map<String, Long> findGroupNameByPolicyId(Long policyId) {
+		Map<String, Long> ret = Collections.emptyMap();
+		if (policyId != null) {
+			try {
+				Collection<Object[]> results = getEntityManager()
+						.createNamedQuery("XXPolicyRefGroup.findGroupNameByPolicyId", Object[].class)
+						.setParameter("policyId", policyId)
+						.getResultList();
+				ret = results.stream().collect(
+						Collectors.toMap(
+								object -> (String) object[0],
+								object -> (Long) object[1]));
+			} catch (NoResultException e) {
+				// ignore
+			}
+		}
+		return ret;
+	}
+
+	public void deletePolicyRefGroupByIds(List<Long> ids) {
+		if (CollectionUtils.isEmpty(ids)) {
+			return;
+		}
+		batchDeleteByIds("XXPolicyRefGroup.deletePolicyRefGroupByIds", ids, "ids");
+	}
 }
diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXPolicyRefRoleDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXPolicyRefRoleDao.java
index 29d2bc4c9..4dfe7372e 100644
--- a/security-admin/src/main/java/org/apache/ranger/db/XXPolicyRefRoleDao.java
+++ b/security-admin/src/main/java/org/apache/ranger/db/XXPolicyRefRoleDao.java
@@ -20,8 +20,11 @@
 package org.apache.ranger.db;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 import javax.persistence.NoResultException;
 
@@ -127,5 +130,31 @@ public void deleteByPolicyId(Long policyId) {
 
         batchDeleteByIds("XXPolicyRefRole.deleteByIds", ids, "ids");
 	}
+
+	public Map<String, Long> findRoleNameIdByPolicyId(Long policyId) {
+		Map<String, Long> ret = Collections.emptyMap();
+		if (policyId != null) {
+			try {
+				Collection<Object[]> results = getEntityManager()
+						.createNamedQuery("XXPolicyRefRole.findRoleNameIdByPolicyId", Object[].class)
+						.setParameter("policyId", policyId)
+						.getResultList();
+				ret = results.stream().collect(
+						Collectors.toMap(
+								object -> (String) object[0],
+								object -> (Long) object[1]));
+			} catch (NoResultException e) {
+				// ignore
+			}
+		}
+		return ret;
+	}
+
+	public void deletePolicyRefRoleByIds(List<Long> ids) {
+		if (CollectionUtils.isEmpty(ids)) {
+			return;
+		}
+		batchDeleteByIds("XXPolicyRefRole.deletePolicyRefRoleByIds", ids, "ids");
+	}
 }
 
diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXPolicyRefUserDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXPolicyRefUserDao.java
index 07d94ceb9..52543b2c3 100644
--- a/security-admin/src/main/java/org/apache/ranger/db/XXPolicyRefUserDao.java
+++ b/security-admin/src/main/java/org/apache/ranger/db/XXPolicyRefUserDao.java
@@ -20,8 +20,11 @@
 package org.apache.ranger.db;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 import javax.persistence.NoResultException;
 
@@ -127,4 +130,30 @@ public void deleteByPolicyId(Long policyId) {
 
 		batchDeleteByIds("XXPolicyRefUser.deleteByIds", ids, "ids");
 	}
+
+	public Map<String, Long> findUserNameIdByPolicyId(Long policyId) {
+		Map<String, Long> ret = Collections.emptyMap();
+		if (policyId != null) {
+			try {
+				Collection<Object[]> results = getEntityManager()
+						.createNamedQuery("XXPolicyRefUser.findUserNameIdByPolicyId", Object[].class)
+						.setParameter("policyId", policyId)
+						.getResultList();
+				ret = results.stream().collect(
+						Collectors.toMap(
+								object -> (String) object[0],
+								object -> (Long) object[1]));
+			} catch (NoResultException e) {
+				// ignore
+			}
+		}
+		return ret;
+	}
+
+	public void deletePolicyRefUserByIds(List<Long> ids) {
+		if (CollectionUtils.isEmpty(ids)) {
+			return;
+		}
+		batchDeleteByIds("XXPolicyRefUser.deletePolicyRefUserByIds", ids, "ids");
+	}
 }
diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXResourceDefDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXResourceDefDao.java
index 56139027b..df5d104ff 100644
--- a/security-admin/src/main/java/org/apache/ranger/db/XXResourceDefDao.java
+++ b/security-admin/src/main/java/org/apache/ranger/db/XXResourceDefDao.java
@@ -18,16 +18,25 @@
 package org.apache.ranger.db;
 
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 import javax.persistence.NoResultException;
 
+import org.apache.commons.collections.CollectionUtils;
 import org.apache.ranger.common.db.BaseDao;
 import org.apache.ranger.entity.XXResourceDef;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
 
 @Service
 public class XXResourceDefDao extends BaseDao<XXResourceDef> {
+	private static final Logger logger = LoggerFactory.getLogger(XXResourceDefDao.class);
 
 	public XXResourceDefDao(RangerDaoManagerBase daoMgr) {
 		super(daoMgr);
@@ -99,4 +108,22 @@ public List<XXResourceDef> findByParentResId(Long parentId) {
 			return new ArrayList<XXResourceDef>();
 		}
 	}
+
+	public Map<String, Long> findResourceDefIdsByNameAndPolicyId(Set<String> names, Long policyId) {
+		if (policyId != null && CollectionUtils.isNotEmpty(names)) {
+			try {
+				Collection<Object[]> result = getEntityManager()
+						.createNamedQuery("XXResourceDef.findResourceDefIdsByNameAndPolicyId", Object[].class)
+						.setParameter("policyId", policyId)
+						.setParameter("names", names)
+						.getResultList();
+
+				return result.stream().collect(Collectors.toMap(object -> (String) object[1], object -> (Long) object[0], (a, b) -> a));
+			} catch (NoResultException e) {
+				logger.debug(e.getMessage());
+			}
+		}
+
+		return Collections.emptyMap();
+	}
 }
diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXRoleDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXRoleDao.java
index 03e966934..1fb54895e 100644
--- a/security-admin/src/main/java/org/apache/ranger/db/XXRoleDao.java
+++ b/security-admin/src/main/java/org/apache/ranger/db/XXRoleDao.java
@@ -17,18 +17,26 @@
 
 package org.apache.ranger.db;
 
+import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.ListUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.ranger.common.db.BaseDao;
 import org.apache.ranger.entity.XXRole;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
 
 import javax.persistence.NoResultException;
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 @Service
 public class XXRoleDao extends BaseDao<XXRole> {
+    private static final Logger logger = LoggerFactory.getLogger(XXRoleDao.class);
     /**
      * Default Constructor
      */
@@ -126,5 +134,22 @@ public List<XXRole> findByGroupId(Long groupId) {
         }
         return ret;
     }
+
+    public Map<String, Long> getIdsByRoleNames(Collection<String> roleNames) {
+        if (CollectionUtils.isNotEmpty(roleNames)) {
+            try {
+                Collection<Object[]> result = getEntityManager()
+                        .createNamedQuery("XXRole.getIdsByRoleNames", Object[].class)
+                        .setParameter("roleNames", roleNames)
+                        .getResultList();
+
+                return result.stream().collect(Collectors.toMap(object -> (String) (object[1]), object -> (Long) (object[0])));
+            } catch (NoResultException e) {
+                logger.debug(e.getMessage());
+            }
+        }
+
+        return Collections.emptyMap();
+    }
 }
 
diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXUserDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXUserDao.java
index 05c65322a..61121788d 100755
--- a/security-admin/src/main/java/org/apache/ranger/db/XXUserDao.java
+++ b/security-admin/src/main/java/org/apache/ranger/db/XXUserDao.java
@@ -21,6 +21,7 @@
 
 import javax.persistence.NoResultException;
 
+import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.ListUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.ranger.authorization.utils.JsonUtils;
@@ -33,12 +34,15 @@
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
 
-import java.util.List;
-import java.util.Set;
-import java.util.HashSet;
-import java.util.Map;
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 import static org.apache.ranger.plugin.util.RangerCommonConstants.*;
 
@@ -186,6 +190,23 @@ public List<UserInfo> getAllUsersInfo() {
 		return ret;
 	}
 
+	public Map<String, Long> getIdsByUserNames(Collection<String> names) {
+		if (CollectionUtils.isNotEmpty(names)) {
+			try {
+				Collection<Object[]> result = getEntityManager()
+						.createNamedQuery("XXUser.getIdsByUserNames", Object[].class)
+						.setParameter("names", names)
+						.getResultList();
+
+				return result.stream().collect(Collectors.toMap(object -> (String) (object[1]), object -> (Long) (object[0])));
+			} catch (NoResultException e) {
+				logger.debug(e.getMessage());
+			}
+		}
+
+		return Collections.emptyMap();
+	}
+
 	private UserInfo toUserInfo(Object[] row) {
 		String              name         = (String) row[0];
 		String              description  = (String) row[1];
diff --git a/security-admin/src/main/resources/META-INF/jpa_named_queries.xml b/security-admin/src/main/resources/META-INF/jpa_named_queries.xml
index 9db7bf1ca..42d497792 100755
--- a/security-admin/src/main/resources/META-INF/jpa_named_queries.xml
+++ b/security-admin/src/main/resources/META-INF/jpa_named_queries.xml
@@ -176,6 +176,10 @@
 		</query>
 	</named-query>
 
+	<named-query name="XXGroup.getIdsByGroupNames">
+		<query>SELECT obj.id, obj.name FROM XXGroup obj WHERE obj.name IN :names</query>
+	</named-query>
+
 	<!-- XXGroup -->
 	<named-query name="XXUser.findGroupsByUserIds">
 		<query>SELECT user.name, group.name FROM XXUser user, XXGroup group, XXGroupUser groupUser
@@ -193,12 +197,17 @@
 		</query>
 	</named-query>
 
+	<named-query name="XXUser.getIdsByUserNames">
+		<query>SELECT obj.id, obj.name FROM XXUser obj WHERE obj.name IN :names</query>
+	</named-query>
+
 	<named-query name="VXXPrincipal.lookupByName">
 		<query>SELECT p.principalName, p.principalType FROM VXXPrincipal p
 			    WHERE p.principalName LIKE :principalName
 			      AND p.isVisible = 1
 			    ORDER BY p.principalName</query>
 	</named-query>
+
 	<named-query name="XXUser.getAllUsersInfo">
 		<query>SELECT user.name, user.description, user.otherAttributes, user.syncSource, pUser.userSource, pUser.emailAddress
 		         FROM XXUser user LEFT OUTER JOIN XXPortalUser pUser ON pUser.loginId = user.name
@@ -582,6 +591,15 @@
 				and xSvc.id = xPol.service and xPol.id = :policyId and obj.name = :name order by obj.level</query>
 	</named-query>
 
+	<named-query name="XXResourceDef.findResourceDefIdsByNameAndPolicyId">
+		<query>SELECT obj.id, obj.name FROM XXResourceDef obj
+		        WHERE obj.name IN :names AND obj.defId IN
+		              (SELECT xSvcDef.id FROM XXServiceDef xSvcDef, XXService xSvc, XXPolicy xPol
+		                WHERE xSvcDef.id = xSvc.type AND xSvc.id = xPol.service AND xPol.id = :policyId)
+		        ORDER BY obj.level
+		</query>
+	</named-query>
+
 	<named-query name="XXResourceDef.findByParentResId">
 		<query>
 			select obj from XXResourceDef obj where obj.parent = :parentId
@@ -635,6 +653,11 @@
 				obj.name = :name and xSvc.id = :serviceId and obj.defId = xSvc.type</query>
 	</named-query>
 
+	<named-query name="XXAccessTypeDef.findAccessTypeDefIdsByNamesAndServiceId">
+		<query>SELECT obj.id, obj.name FROM XXAccessTypeDef obj
+		        WHERE obj.name IN :names AND obj.defId IN (SELECT xSvc.type FROM XXService xSvc WHERE xSvc.id = :serviceId)</query>
+	</named-query>
+
 	<!-- XXPolicyConditionDef -->
 	<named-query name="XXPolicyConditionDef.findByServiceDefId">
 		<query>select obj from XXPolicyConditionDef obj where obj.defId = :serviceDefId order by obj.order</query>
@@ -644,6 +667,10 @@
 		<query>select obj from XXPolicyConditionDef obj where obj.defId = :serviceDefId and obj.name = :name order by obj.order</query>
 	</named-query>
 
+	<named-query name="XXPolicyConditionDef.findConditionDefIdsByServiceDefIdAndNames">
+		<query>select obj.id, obj.name from XXPolicyConditionDef obj where obj.defId = :serviceDefId and obj.name IN :names order by obj.order</query>
+	</named-query>
+
 	<!-- XXContextEnricherDef -->
 	<named-query name="XXContextEnricherDef.findByServiceDefId">
 		<query>select obj from XXContextEnricherDef obj where obj.defId = :serviceDefId order by obj.order</query>
@@ -669,6 +696,10 @@
 			obj.name = :name and xSvc.id = :serviceId and obj.defId = xSvc.type</query>
 	</named-query>
 
+	<named-query name="XXDataMaskTypeDef.findDataMaskTypeDefIdsByNamesAndServiceId">
+		<query>select obj.id, obj.name from XXDataMaskTypeDef obj, XXService xSvc where obj.name IN :names and xSvc.id = :serviceId and obj.defId = xSvc.type</query>
+	</named-query>
+
 	<!-- XXServiceConfigMap -->
 	<named-query name="XXServiceConfigMap.findByServiceId">
 		<query>select obj from XXServiceConfigMap obj where obj.serviceId = :serviceId</query>
@@ -897,6 +928,14 @@
 		<query>select obj from XXPolicyRefGroup obj where obj.groupName = :groupName</query>
 	</named-query>
 
+	<named-query name="XXPolicyRefGroup.findGroupNameByPolicyId">
+		<query>select obj.groupName, obj.id from XXPolicyRefGroup obj where obj.policyId = :policyId</query>
+	</named-query>
+
+	<named-query name="XXPolicyRefGroup.deletePolicyRefGroupByIds">
+		<query>DELETE FROM XXPolicyRefGroup obj WHERE obj.id IN :ids </query>
+	</named-query>
+
 <!-- 	new queries -->
 	<named-query name="XXPolicyRefGroup.findByGroupIdAndPolicyId">
 		<query>select obj from XXPolicyRefGroup obj where obj.groupId = :groupId and obj.policyId = :policyId </query>
@@ -1103,6 +1142,14 @@
 		<query>DELETE FROM XXPolicyRefUser obj WHERE obj.id IN :ids</query>
 	</named-query>
 
+	<named-query name="XXPolicyRefUser.findUserNameIdByPolicyId">
+		<query>SELECT obj.userName, obj.id FROM XXPolicyRefUser obj WHERE obj.policyId = :policyId</query>
+	</named-query>
+
+	<named-query name="XXPolicyRefUser.deletePolicyRefUserByIds">
+		<query>DELETE FROM XXPolicyRefUser obj WHERE obj.id IN :ids </query>
+	</named-query>
+
 	<!-- XXPolicyItemCondition -->
 
 	<named-query name="XXPolicyItemCondition.findByPolicyId">
@@ -1927,6 +1974,10 @@
         <query>select obj.name from XXRole obj</query>
     </named-query>
 
+    <named-query name="XXRole.getIdsByRoleNames">
+        <query>SELECT obj.id, obj.name FROM XXRole obj WHERE obj.name IN :roleNames</query>
+    </named-query>
+
 	<!-- XXRoleRef* -->
 
     <named-query name="XXRoleRefUser.findByRoleId">
@@ -1997,6 +2048,14 @@
 		<query>select obj from XXPolicyRefRole obj where obj.policyId = :policyId </query>
 	</named-query>
 
+	<named-query name="XXPolicyRefRole.findRoleNameIdByPolicyId">
+		<query>SELECT obj.roleName, obj.id FROM XXPolicyRefRole obj WHERE obj.policyId = :policyId</query>
+	</named-query>
+
+	<named-query name="XXPolicyRefRole.deletePolicyRefRoleByIds">
+		<query>DELETE FROM XXPolicyRefRole obj WHERE obj.id IN :ids </query>
+	</named-query>
+
 	<named-query name="XXPolicyRefRole.findIdsByPolicyId">
 		<query>select obj.id from XXPolicyRefRole obj where obj.policyId = :policyId </query>
 	</named-query>
@@ -2172,4 +2231,5 @@
 	<named-query name="XXPolicy.findByZoneId">
 		<query>select obj from XXPolicy obj where obj.zoneId = :zoneId</query>
 	</named-query>
+
 </entity-mappings>
diff --git a/security-admin/src/test/java/org/apache/ranger/biz/TestPolicyRefUpdater.java b/security-admin/src/test/java/org/apache/ranger/biz/TestPolicyRefUpdater.java
new file mode 100644
index 000000000..f84be0025
--- /dev/null
+++ b/security-admin/src/test/java/org/apache/ranger/biz/TestPolicyRefUpdater.java
@@ -0,0 +1,423 @@
+/*
+ * 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.ranger.biz;
+
+import org.apache.ranger.common.RESTErrorUtil;
+import org.apache.ranger.common.db.RangerTransactionSynchronizationAdapter;
+import org.apache.ranger.db.RangerDaoManager;
+import org.apache.ranger.db.XXAccessTypeDefDao;
+import org.apache.ranger.db.XXDataMaskTypeDefDao;
+import org.apache.ranger.db.XXGroupDao;
+import org.apache.ranger.db.XXPolicyConditionDefDao;
+import org.apache.ranger.db.XXPolicyRefAccessTypeDao;
+import org.apache.ranger.db.XXPolicyRefConditionDao;
+import org.apache.ranger.db.XXPolicyRefDataMaskTypeDao;
+import org.apache.ranger.db.XXPolicyRefGroupDao;
+import org.apache.ranger.db.XXPolicyRefResourceDao;
+import org.apache.ranger.db.XXPolicyRefRoleDao;
+import org.apache.ranger.db.XXPolicyRefUserDao;
+import org.apache.ranger.db.XXResourceDefDao;
+import org.apache.ranger.db.XXRoleDao;
+import org.apache.ranger.db.XXUserDao;
+import org.apache.ranger.entity.XXPolicy;
+import org.apache.ranger.entity.XXPolicyRefGroup;
+import org.apache.ranger.entity.XXPolicyRefRole;
+import org.apache.ranger.entity.XXPolicyRefUser;
+import org.apache.ranger.entity.XXServiceDef;
+import org.apache.ranger.entity.XXUser;
+import org.apache.ranger.plugin.model.RangerPolicy;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerDataMaskPolicyItem;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemAccess;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemCondition;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemDataMaskInfo;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerRowFilterPolicyItem;
+import org.apache.ranger.plugin.model.RangerRole;
+import org.apache.ranger.service.RangerAuditFields;
+import org.apache.ranger.service.XGroupService;
+import org.apache.ranger.view.VXGroup;
+import org.apache.ranger.view.VXUser;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+* @generated by Cursor
+* @description <Unit Test for TestPolicyRefUpdater class>
+*/
+@RunWith(MockitoJUnitRunner.class)
+public class TestPolicyRefUpdater {
+    @InjectMocks
+    PolicyRefUpdater updater;
+
+    @Mock
+    RangerDaoManager daoMgr;
+    @Mock
+    RangerAuditFields<?> rangerAuditFields;
+    @Mock
+    XUserMgr xUserMgr;
+    @Mock
+    RoleDBStore roleStore;
+    @Mock
+    RangerBizUtil rangerBizUtil;
+    @Mock
+    XGroupService xGroupService;
+    @Mock
+    RangerTransactionSynchronizationAdapter rangerTransactionSynchronizationAdapter;
+    @Mock
+    RESTErrorUtil restErrorUtil;
+
+    @Test
+    public void testGetAllPolicyItemsAggregates() {
+        RangerPolicy p = new RangerPolicy();
+        p.setPolicyItems(Arrays.asList(new RangerPolicyItem()));
+        p.setDenyPolicyItems(Arrays.asList(new RangerPolicyItem()));
+        p.setAllowExceptions(Arrays.asList(new RangerPolicyItem()));
+        p.setDenyExceptions(Arrays.asList(new RangerPolicyItem()));
+        p.setDataMaskPolicyItems(Arrays.asList(new RangerDataMaskPolicyItem()));
+        p.setRowFilterPolicyItems(Arrays.asList(new RangerRowFilterPolicyItem()));
+        List<List<? extends RangerPolicyItem>> items = PolicyRefUpdater.getAllPolicyItems(p);
+        Assert.assertEquals(6, items.size());
+    }
+
+    @Test
+    public void testCreateNewPolMappingForRefTable_NullPolicyNoop() throws Exception {
+        updater.createNewPolMappingForRefTable(null, null, null, false, false);
+    }
+
+    @Test
+    public void testCreateNewPolMappingForRefTable_ValidEverything() throws Exception {
+        // Prepare policy with resources and items
+        RangerPolicy policy = new RangerPolicy();
+        policy.setId(5L);
+        policy.setName("p");
+        policy.setService("svc");
+        policy.setResources(Collections.singletonMap("db",
+                new RangerPolicy.RangerPolicyResource(Collections.singletonList("db1"), false, false)));
+        RangerPolicyItem item = new RangerPolicyItem();
+        item.setUsers(Arrays.asList("u1"));
+        item.setGroups(Arrays.asList("g1"));
+        item.setRoles(Arrays.asList("r1"));
+        RangerPolicyItemAccess acc = new RangerPolicyItemAccess();
+        acc.setType("select");
+        item.setAccesses(Collections.singletonList(acc));
+        RangerPolicyItemCondition cond = new RangerPolicyItemCondition();
+        cond.setType("time");
+        item.setConditions(Collections.singletonList(cond));
+        RangerDataMaskPolicyItem dmItem = new RangerDataMaskPolicyItem();
+        RangerPolicyItemDataMaskInfo dm = new RangerPolicyItemDataMaskInfo();
+        dm.setDataMaskType("MASK");
+        dmItem.setDataMaskInfo(dm);
+        policy.setPolicyItems(Arrays.asList(item));
+        policy.setDataMaskPolicyItems(Arrays.asList(dmItem));
+        policy.setConditions(Collections.singletonList(cond));
+
+        XXPolicy xPolicy = new XXPolicy();
+        xPolicy.setId(5L);
+        xPolicy.setName("p");
+        xPolicy.setService(9L);
+        XXServiceDef xSvc = new XXServiceDef();
+        xSvc.setId(9L);
+
+        // Stubs for DAO lookups and batch create calls
+        XXResourceDefDao resDefDao = mock(XXResourceDefDao.class);
+        when(daoMgr.getXXResourceDef()).thenReturn(resDefDao);
+        Map<String, Long> xxResourceDefIdMap = new HashMap<>();
+        xxResourceDefIdMap.put("db", 1L);
+        when(resDefDao.findResourceDefIdsByNameAndPolicyId(Mockito.anySet(), Mockito.eq(5L))).thenReturn(xxResourceDefIdMap);
+        Mockito.lenient().when(rangerAuditFields.populateAuditFields(Mockito.any(), Mockito.any()))
+                .thenAnswer(inv -> inv.getArgument(0));
+        XXPolicyRefResourceDao polResDao = mock(XXPolicyRefResourceDao.class);
+        when(daoMgr.getXXPolicyRefResource()).thenReturn(polResDao);
+        XXPolicyRefRoleDao polRoleDao = mock(XXPolicyRefRoleDao.class);
+        when(daoMgr.getXXPolicyRefRole()).thenReturn(polRoleDao);
+        XXPolicyRefGroupDao polGroupDao = mock(XXPolicyRefGroupDao.class);
+        when(daoMgr.getXXPolicyRefGroup()).thenReturn(polGroupDao);
+        XXPolicyRefUserDao polUserDao = mock(XXPolicyRefUserDao.class);
+        when(daoMgr.getXXPolicyRefUser()).thenReturn(polUserDao);
+        XXAccessTypeDefDao accDefDao = mock(XXAccessTypeDefDao.class);
+        when(daoMgr.getXXAccessTypeDef()).thenReturn(accDefDao);
+        Map<String, Long> xAccMap = new HashMap<>();
+        xAccMap.put("select", 2L);
+        when(accDefDao.findAccessTypeDefIdsByNamesAndServiceId(Mockito.anySet(), Mockito.eq(9L))).thenReturn(xAccMap);
+        XXPolicyRefAccessTypeDao polAccDao = mock(XXPolicyRefAccessTypeDao.class);
+        when(daoMgr.getXXPolicyRefAccessType()).thenReturn(polAccDao);
+        XXPolicyConditionDefDao condDefDao = mock(XXPolicyConditionDefDao.class);
+        when(daoMgr.getXXPolicyConditionDef()).thenReturn(condDefDao);
+        Map<String, Long> xCondMap = new HashMap<>();
+        xCondMap.put("time", 3L);
+        when(condDefDao.findConditionDefIdsByServiceDefIdAndNames(Mockito.eq(9L), Mockito.anySet())).thenReturn(xCondMap);
+        XXPolicyRefConditionDao polCondDao = mock(XXPolicyRefConditionDao.class);
+        when(daoMgr.getXXPolicyRefCondition()).thenReturn(polCondDao);
+        XXDataMaskTypeDefDao dmDefDao = mock(XXDataMaskTypeDefDao.class);
+        when(daoMgr.getXXDataMaskTypeDef()).thenReturn(dmDefDao);
+        Map<String, Long> xxDataMaskTypeDefIdMap = new HashMap<>();
+        xxDataMaskTypeDefIdMap.put("MASK", 4L);
+        when(dmDefDao.findDataMaskTypeDefIdsByNamesAndServiceId(Mockito.anySet(), Mockito.eq(9L))).thenReturn(xxDataMaskTypeDefIdMap);
+        XXPolicyRefDataMaskTypeDao polDmDao = mock(XXPolicyRefDataMaskTypeDao.class);
+        when(daoMgr.getXXPolicyRefDataMaskType()).thenReturn(polDmDao);
+        when(rangerBizUtil.checkAdminAccess()).thenReturn(true);
+
+        org.apache.ranger.db.XXPolicyDao policyDao = mock(org.apache.ranger.db.XXPolicyDao.class);
+        when(daoMgr.getXXPolicy()).thenReturn(policyDao);
+        when(policyDao.getById(xPolicy.getId())).thenReturn(xPolicy);
+
+        XXUserDao userDao = mock(XXUserDao.class);
+        when(daoMgr.getXXUser()).thenReturn(userDao);
+        when(userDao.getIdsByUserNames(Mockito.anySet())).thenReturn(Collections.singletonMap("u1", 30L));
+
+        XXGroupDao groupDao = mock(XXGroupDao.class);
+        when(daoMgr.getXXGroup()).thenReturn(groupDao);
+        when(groupDao.getIdsByGroupNames(Mockito.anySet())).thenReturn(Collections.singletonMap("g1", 20L));
+
+        XXRoleDao roleDao = mock(XXRoleDao.class);
+        when(daoMgr.getXXRole()).thenReturn(roleDao);
+        when(roleDao.getIdsByRoleNames(Mockito.anySet())).thenReturn(Collections.singletonMap("r1", 10L));
+
+        updater.createNewPolMappingForRefTable(policy, xPolicy, xSvc, true, false);
+        // no exceptions indicates success across branches
+    }
+
+    @Test
+    public void testCreateNewPolMappingForRefTable_InvalidResourceDef() throws Exception {
+        RangerPolicy policy = new RangerPolicy();
+        policy.setId(6L);
+        policy.setName("p2");
+        policy.setService("svc");
+        policy.setResources(Collections.singletonMap("invalid",
+                new RangerPolicy.RangerPolicyResource(Collections.singletonList("v"), false, false)));
+        XXPolicy xPolicy = new XXPolicy();
+        xPolicy.setId(6L);
+        XXServiceDef xSvc = new XXServiceDef();
+        xSvc.setId(9L);
+        XXResourceDefDao resDefDao = mock(XXResourceDefDao.class);
+        when(daoMgr.getXXResourceDef()).thenReturn(resDefDao);
+        when(resDefDao.findResourceDefIdsByNameAndPolicyId(Mockito.anySet(), Mockito.eq(6L))).thenReturn(Collections.emptyMap());
+        try {
+            updater.createNewPolMappingForRefTable(policy, xPolicy, xSvc, false, false);
+            Assert.fail("Expected exception");
+        } catch (Exception expected) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testCleanupRefTablesForUpdate_SelectivePrincipalCleanup() {
+        final Long policyId = 100L;
+
+        Set<String> policyUsers  = new HashSet<>(Arrays.asList("alice", "bob", "carol"));
+        Set<String> policyRoles  = new HashSet<>(Arrays.asList("roleA", "roleB", "roleNew"));
+        Set<String> policyGroups = new HashSet<>(Arrays.asList("grp1", "grp2", "grpNew"));
+
+        Map<String, Long> existingUsers = new HashMap<>();
+        existingUsers.put("alice", 1L);
+        existingUsers.put("bob", 2L);
+        existingUsers.put("dave", 4L);
+
+        Map<String, Long> existingRoles = new HashMap<>();
+        existingRoles.put("roleA", 10L);
+        existingRoles.put("roleOld", 12L);
+
+        Map<String, Long> existingGroups = new HashMap<>();
+        existingGroups.put("grp1", 20L);
+        existingGroups.put("grpOld", 22L);
+
+        XXPolicyRefUserDao userDao = mock(XXPolicyRefUserDao.class);
+        XXPolicyRefRoleDao roleDao = mock(XXPolicyRefRoleDao.class);
+        XXPolicyRefGroupDao groupDao = mock(XXPolicyRefGroupDao.class);
+        XXPolicyRefResourceDao resourceDao = mock(XXPolicyRefResourceDao.class);
+        XXPolicyRefAccessTypeDao accessDao = mock(XXPolicyRefAccessTypeDao.class);
+        XXPolicyRefConditionDao conditionDao = mock(XXPolicyRefConditionDao.class);
+        XXPolicyRefDataMaskTypeDao dataMaskDao = mock(XXPolicyRefDataMaskTypeDao.class);
+
+        when(daoMgr.getXXPolicyRefUser()).thenReturn(userDao);
+        when(daoMgr.getXXPolicyRefRole()).thenReturn(roleDao);
+        when(daoMgr.getXXPolicyRefGroup()).thenReturn(groupDao);
+        when(daoMgr.getXXPolicyRefResource()).thenReturn(resourceDao);
+        when(daoMgr.getXXPolicyRefAccessType()).thenReturn(accessDao);
+        when(daoMgr.getXXPolicyRefCondition()).thenReturn(conditionDao);
+        when(daoMgr.getXXPolicyRefDataMaskType()).thenReturn(dataMaskDao);
+
+        when(userDao.findUserNameIdByPolicyId(policyId)).thenReturn(existingUsers);
+        when(roleDao.findRoleNameIdByPolicyId(policyId)).thenReturn(existingRoles);
+        when(groupDao.findGroupNameByPolicyId(policyId)).thenReturn(existingGroups);
+
+        Assert.assertTrue(updater.cleanupRefTablesForUpdate(policyId, policyUsers, policyRoles, policyGroups));
+
+        verify(userDao).deletePolicyRefUserByIds(Collections.singletonList(4L));
+        Assert.assertEquals(Collections.singleton("carol"), policyUsers);
+
+        verify(roleDao).deletePolicyRefRoleByIds(Collections.singletonList(12L));
+        Assert.assertEquals(new HashSet<>(Arrays.asList("roleB", "roleNew")), policyRoles);
+
+        verify(groupDao).deletePolicyRefGroupByIds(Collections.singletonList(22L));
+        Assert.assertEquals(new HashSet<>(Arrays.asList("grp2", "grpNew")), policyGroups);
+
+        verify(resourceDao).deleteByPolicyId(policyId);
+        verify(accessDao).deleteByPolicyId(policyId);
+        verify(conditionDao).deleteByPolicyId(policyId);
+        verify(dataMaskDao).deleteByPolicyId(policyId);
+
+        verify(userDao, never()).deleteByPolicyId(policyId);
+        verify(roleDao, never()).deleteByPolicyId(policyId);
+        verify(groupDao, never()).deleteByPolicyId(policyId);
+    }
+
+    @Test
+    public void testCleanupRefTables() {
+        when(daoMgr.getXXPolicyRefResource()).thenReturn(mock(XXPolicyRefResourceDao.class));
+        when(daoMgr.getXXPolicyRefRole()).thenReturn(mock(XXPolicyRefRoleDao.class));
+        when(daoMgr.getXXPolicyRefGroup()).thenReturn(mock(XXPolicyRefGroupDao.class));
+        when(daoMgr.getXXPolicyRefUser()).thenReturn(mock(XXPolicyRefUserDao.class));
+        when(daoMgr.getXXPolicyRefAccessType()).thenReturn(mock(XXPolicyRefAccessTypeDao.class));
+        when(daoMgr.getXXPolicyRefCondition()).thenReturn(mock(XXPolicyRefConditionDao.class));
+        when(daoMgr.getXXPolicyRefDataMaskType()).thenReturn(mock(XXPolicyRefDataMaskTypeDao.class));
+
+        RangerPolicy p = new RangerPolicy();
+        p.setId(77L);
+        Assert.assertEquals(true, updater.cleanupRefTables(p));
+        Assert.assertEquals(false, updater.cleanupRefTables(null));
+    }
+
+    @Test
+    public void testCreatePrincipal_User_Group_Role_Paths() throws Exception {
+        // Common setup: policy and xPolicy for audit fields
+        XXPolicy xPolicy = new XXPolicy();
+        xPolicy.setId(10L);
+        xPolicy.setService(100L);
+
+        // FIX: Mock policy DAO hierarchy to satisfy doesPolicyExist(xPolicy) checks
+        org.apache.ranger.db.XXPolicyDao policyDao = mock(org.apache.ranger.db.XXPolicyDao.class);
+        when(daoMgr.getXXPolicy()).thenReturn(policyDao);
+        when(policyDao.getById(xPolicy.getId())).thenReturn(xPolicy);
+
+        // Mock audit population to be identity
+        Mockito.lenient().when(rangerAuditFields.populateAuditFields(Mockito.any(), Mockito.any()))
+            .thenAnswer(inv -> inv.getArgument(0));
+
+        // USER path: user not found, xUserMgr creates, then XXUser lookup returns id
+        XXUserDao userDao = mock(XXUserDao.class);
+        when(daoMgr.getXXUser()).thenReturn(userDao);
+        when(userDao.findByUserName("uNew")).thenReturn(null).thenReturn(new XXUser() {
+            {
+                setId(11L);
+            }
+        });
+        VXUser createdVX = new VXUser();
+        when(xUserMgr.createServiceConfigUser("uNew")).thenReturn(createdVX);
+        XXPolicyRefUserDao polUserDao = mock(XXPolicyRefUserDao.class);
+        when(daoMgr.getXXPolicyRefUser()).thenReturn(polUserDao);
+
+        // Reflectively construct inner class PolicyUserAssociator for USER
+        Class<?> userAssociatorClass = null;
+        for (Class<?> c : PolicyRefUpdater.class.getDeclaredClasses()) {
+            if (c.getSimpleName().equals("PolicyUserAssociator")) {
+                userAssociatorClass = c;
+                break;
+            }
+        }
+        Assert.assertNotNull(userAssociatorClass);
+        Constructor<?> userCtor = userAssociatorClass.getDeclaredConstructor(
+                PolicyRefUpdater.class, String.class, Long.class, XXPolicy.class);
+        userCtor.setAccessible(true);
+        Object associatorUser = userCtor.newInstance(updater, "uNew", null, xPolicy);
+        Method runUser = userAssociatorClass.getDeclaredMethod("run");
+        runUser.setAccessible(true);
+        runUser.invoke(associatorUser);
+        verify(daoMgr.getXXPolicyRefUser(), Mockito.times(1))
+                .create(Mockito.any(XXPolicyRefUser.class));
+
+        // GROUP path: group not found, xGroupService creates and logs, verify ref
+        // created
+        XXGroupDao groupDao = mock(XXGroupDao.class);
+        when(daoMgr.getXXGroup()).thenReturn(groupDao);
+        when(groupDao.findByGroupName("gNew")).thenReturn(null);
+        VXGroup vXGroup = new VXGroup();
+        vXGroup.setId(22L);
+        when(xGroupService.createXGroupWithOutLogin(Mockito.any(VXGroup.class))).thenReturn(vXGroup);
+        XXPolicyRefGroupDao polGroupDao = mock(XXPolicyRefGroupDao.class);
+        when(daoMgr.getXXPolicyRefGroup()).thenReturn(polGroupDao);
+
+        Class<?> groupAssociatorClass = null;
+        for (Class<?> c : PolicyRefUpdater.class.getDeclaredClasses()) {
+            if (c.getSimpleName().equals("PolicyGroupAssociator")) {
+                groupAssociatorClass = c;
+                break;
+            }
+        }
+        Assert.assertNotNull(groupAssociatorClass);
+        Constructor<?> groupCtor = groupAssociatorClass.getDeclaredConstructor(
+                PolicyRefUpdater.class, String.class, Long.class, XXPolicy.class);
+        groupCtor.setAccessible(true);
+        Object associatorGroup = groupCtor.newInstance(updater, "gNew", null, xPolicy);
+        Method runGroup = groupAssociatorClass.getDeclaredMethod("run");
+        runGroup.setAccessible(true);
+        runGroup.invoke(associatorGroup);
+        verify(daoMgr.getXXPolicyRefGroup(), Mockito.times(1))
+                .create(Mockito.any(XXPolicyRefGroup.class));
+
+        // ROLE path: role not found, roleStore.createRole returns id, verify ref
+        // created
+        XXRoleDao roleDao = mock(XXRoleDao.class);
+        when(daoMgr.getXXRole()).thenReturn(roleDao);
+        when(roleDao.findByRoleName("rNew")).thenReturn(null);
+        RangerRole createdRole = new RangerRole("rNew", null, null, null, null);
+        createdRole.setId(33L);
+        when(roleStore.createRole(Mockito.any(RangerRole.class), Mockito.eq(false))).thenReturn(createdRole);
+        XXPolicyRefRoleDao polRoleDao = mock(XXPolicyRefRoleDao.class);
+        when(daoMgr.getXXPolicyRefRole()).thenReturn(polRoleDao);
+
+        Class<?> roleAssociatorClass = null;
+        for (Class<?> c : PolicyRefUpdater.class.getDeclaredClasses()) {
+            if (c.getSimpleName().equals("PolicyRoleAssociator")) {
+                roleAssociatorClass = c;
+                break;
+            }
+        }
+        Assert.assertNotNull(roleAssociatorClass);
+        Constructor<?> roleCtor = roleAssociatorClass.getDeclaredConstructor(
+                PolicyRefUpdater.class, String.class, Long.class, XXPolicy.class);
+        roleCtor.setAccessible(true);
+        Object associatorRole = roleCtor.newInstance(updater, "rNew", null, xPolicy);
+        Method runRole = roleAssociatorClass.getDeclaredMethod("run");
+        runRole.setAccessible(true);
+        runRole.invoke(associatorRole);
+        verify(daoMgr.getXXPolicyRefRole(), Mockito.times(1)).create(Mockito.any(XXPolicyRefRole.class));
+    }
+}
diff --git a/security-admin/src/test/java/org/apache/ranger/biz/TestServiceDBStore.java b/security-admin/src/test/java/org/apache/ranger/biz/TestServiceDBStore.java
index 9238122f5..434a64ee7 100644
--- a/security-admin/src/test/java/org/apache/ranger/biz/TestServiceDBStore.java
+++ b/security-admin/src/test/java/org/apache/ranger/biz/TestServiceDBStore.java
@@ -1688,7 +1688,7 @@ public void test26createPolicy() throws Exception {
 
 		Mockito.when(daoManager.getXXPolicy()).thenReturn(xPolicyDao);
 		Mockito.when(xPolicyDao.getById(Id)).thenReturn(xPolicy);
-		Mockito.doNothing().when(policyRefUpdater).createNewPolMappingForRefTable(rangerPolicy, xPolicy, xServiceDef, false);
+		Mockito.doNothing().when(policyRefUpdater).createNewPolMappingForRefTable(rangerPolicy, xPolicy, xServiceDef, false, false);
 		Mockito.when(policyService.getPopulatedViewObject(xPolicy)).thenReturn(rangerPolicy);
 
 		Mockito.when(daoManager.getXXService()).thenReturn(xServiceDao);
@@ -1835,10 +1835,11 @@ public void tess28updatePolicy() throws Exception {
 		Mockito.when(factory.createPolicyResourceSignature(rangerPolicy))
 				.thenReturn(signature);
 		Mockito.when(!bizUtil.hasAccess(xService, null)).thenReturn(true);
-        Mockito.when(policyRefUpdater.cleanupRefTables(rangerPolicy)).thenReturn(true);
-
+		Mockito.doNothing().when(policyRefUpdater).createNewPolMappingForRefTable(
+				Mockito.eq(rangerPolicy), Mockito.eq(xPolicy), Mockito.eq(xServiceDef),
+				Mockito.anyBoolean(), Mockito.eq(true));
 
-        RangerPolicy dbRangerPolicy = serviceDBStore.updatePolicy(rangerPolicy);
+		RangerPolicy dbRangerPolicy = serviceDBStore.updatePolicy(rangerPolicy);
 		Assert.assertNotNull(dbRangerPolicy);
 		Assert.assertEquals(dbRangerPolicy, rangerPolicy);
 		Assert.assertEquals(dbRangerPolicy.getId(), rangerPolicy.getId());