You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2017/05/25 13:56:29 UTC

[2/3] syncope git commit: [SYNCOPE-1082] Remove half-management via JPA for dynamic members

[SYNCOPE-1082] Remove half-management via JPA for dynamic members


Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/36b786c0
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/36b786c0
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/36b786c0

Branch: refs/heads/master
Commit: 36b786c041523de3779c7bb64fad1679e7c8db7e
Parents: be35817
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Thu May 25 15:52:50 2017 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Thu May 25 15:53:06 2017 +0200

----------------------------------------------------------------------
 .../apache/syncope/core/logic/RoleLogic.java    |   5 +-
 .../core/persistence/api/dao/GroupDAO.java      |   8 +-
 .../core/persistence/api/dao/RoleDAO.java       |   5 +-
 .../persistence/api/entity/DynMembership.java   |   4 -
 .../jpa/content/XMLContentExporter.java         |   3 +-
 .../jpa/content/XMLContentLoader.java           |  41 ++---
 .../persistence/jpa/dao/JPAAnyObjectDAO.java    |   9 +-
 .../core/persistence/jpa/dao/JPAGroupDAO.java   | 175 ++++++++++---------
 .../core/persistence/jpa/dao/JPARoleDAO.java    |  68 ++++---
 .../core/persistence/jpa/dao/JPAUserDAO.java    |  18 +-
 .../core/persistence/jpa/dao/SearchSupport.java |   6 +-
 .../anyobject/JPAADynGroupMembership.java       |  26 ---
 .../jpa/entity/user/AbstractUDynMembership.java |  44 -----
 .../jpa/entity/user/JPADynRoleMembership.java   |  23 +--
 .../jpa/entity/user/JPAUDynGroupMembership.java |  23 +--
 .../src/main/resources/indexes.xml              |   8 +
 .../src/main/resources/views.xml                |  42 +++--
 .../core/persistence/jpa/outer/GroupTest.java   |  68 ++++---
 .../core/persistence/jpa/outer/RoleTest.java    |  36 ++--
 .../provisioning/api/data/RoleDataBinder.java   |   2 +-
 .../java/data/AnyObjectDataBinderImpl.java      |   2 +-
 .../java/data/GroupDataBinderImpl.java          |   4 +
 .../java/data/RoleDataBinderImpl.java           |  19 +-
 .../java/data/UserDataBinderImpl.java           |  42 ++---
 .../client/ElasticsearchUtils.java              |   4 +-
 25 files changed, 319 insertions(+), 366 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/36b786c0/core/logic/src/main/java/org/apache/syncope/core/logic/RoleLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/RoleLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/RoleLogic.java
index ced5dc7..13102a5 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/RoleLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/RoleLogic.java
@@ -80,10 +80,7 @@ public class RoleLogic extends AbstractTransactionalLogic<RoleTO> {
             throw new NotFoundException(roleTO.getKey());
         }
 
-        binder.update(role, roleTO);
-        role = roleDAO.save(role);
-
-        return binder.getRoleTO(role);
+        return binder.getRoleTO(roleDAO.save(binder.update(role, roleTO)));
     }
 
     @PreAuthorize("hasRole('" + StandardEntitlement.ROLE_DELETE + "')")

http://git-wip-us.apache.org/repos/asf/syncope/blob/36b786c0/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/GroupDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/GroupDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/GroupDAO.java
index b08c9b9..04ff490 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/GroupDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/GroupDAO.java
@@ -46,13 +46,17 @@ public interface GroupDAO extends AnyDAO<Group> {
 
     List<TypeExtension> findTypeExtensions(AnyTypeClass anyTypeClass);
 
-    List<String> findADynMembersKeys(Group group);
+    List<String> findADynMembers(Group group);
+
+    void clearADynMembers(Group group);
 
     void refreshDynMemberships(AnyObject anyObject);
 
     void removeDynMemberships(AnyObject anyObject);
 
-    List<String> findUDynMembersKeys(Group group);
+    List<String> findUDynMembers(Group group);
+
+    void clearUDynMembers(Group group);
 
     void refreshDynMemberships(User user);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/36b786c0/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/RoleDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/RoleDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/RoleDAO.java
index 16f3003..f76b382 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/RoleDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/RoleDAO.java
@@ -39,9 +39,12 @@ public interface RoleDAO extends DAO<Role> {
 
     void delete(String key);
 
-    List<String> findDynMembersKeys(Role role);
+    List<String> findDynMembers(Role role);
+
+    void clearDynMembers(Role role);
 
     void refreshDynMemberships(User user);
 
     void removeDynMemberships(User user);
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/36b786c0/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DynMembership.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DynMembership.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DynMembership.java
index 2b12744..b62ea17 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DynMembership.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DynMembership.java
@@ -23,8 +23,4 @@ public interface DynMembership<A extends Any<?>> extends Entity {
     String getFIQLCond();
 
     void setFIQLCond(String fiql);
-
-    boolean add(A any);
-
-    void clear();
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/36b786c0/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/XMLContentExporter.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/XMLContentExporter.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/XMLContentExporter.java
index 6c7ce53..3fba66b 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/XMLContentExporter.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/XMLContentExporter.java
@@ -55,6 +55,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.core.provisioning.api.utils.FormatUtils;
 import org.apache.syncope.core.spring.ApplicationContextProvider;
 import org.apache.syncope.core.persistence.api.content.ContentExporter;
+import org.apache.syncope.core.persistence.jpa.entity.JPAAccessToken;
 import org.apache.syncope.core.persistence.jpa.entity.JPAReportExec;
 import org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAAMembership;
 import org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAAPlainAttr;
@@ -86,7 +87,7 @@ public class XMLContentExporter extends AbstractContentDealer implements Content
         JPAUser.TABLE, JPAUPlainAttr.TABLE, JPAUPlainAttrValue.TABLE, JPAUPlainAttrUniqueValue.TABLE,
         JPAURelationship.TABLE, JPAUMembership.TABLE,
         JPAAnyObject.TABLE, JPAAPlainAttr.TABLE, JPAAPlainAttrValue.TABLE, JPAAPlainAttrUniqueValue.TABLE,
-        JPAARelationship.TABLE, JPAAMembership.TABLE
+        JPAARelationship.TABLE, JPAAMembership.TABLE, JPAAccessToken.TABLE
     }));
 
     protected static final Map<String, String> TABLES_TO_BE_FILTERED =

http://git-wip-us.apache.org/repos/asf/syncope/blob/36b786c0/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/XMLContentLoader.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/XMLContentLoader.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/XMLContentLoader.java
index 3d46c89..8ebea1d 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/XMLContentLoader.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/XMLContentLoader.java
@@ -43,12 +43,12 @@ import org.springframework.stereotype.Component;
 @Component
 public class XMLContentLoader extends AbstractContentDealer implements ContentLoader {
 
-    @Resource(name = "indexesXML")
-    private ResourceWithFallbackLoader indexesXML;
-
     @Resource(name = "viewsXML")
     private ResourceWithFallbackLoader viewsXML;
 
+    @Resource(name = "indexesXML")
+    private ResourceWithFallbackLoader indexesXML;
+
     @Override
     public Integer getPriority() {
         return 0;
@@ -83,8 +83,8 @@ public class XMLContentLoader extends AbstractContentDealer implements ContentLo
                     LOG.error("[{}] While loading default content", entry.getKey(), e);
                 }
                 try {
-                    createIndexes(entry.getKey(), entry.getValue());
                     createViews(entry.getKey(), entry.getValue());
+                    createIndexes(entry.getKey(), entry.getValue());
                 } catch (IOException e) {
                     LOG.error("[{}] While creating indexes and views", entry.getKey(), e);
                 }
@@ -109,41 +109,42 @@ public class XMLContentLoader extends AbstractContentDealer implements ContentLo
         }
     }
 
-    private void createIndexes(final String domain, final DataSource dataSource) throws IOException {
-        LOG.debug("[{}] Creating indexes", domain);
+    private void createViews(final String domain, final DataSource dataSource) throws IOException {
+        LOG.debug("[{}] Creating views", domain);
 
         JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
 
-        Properties indexes = PropertiesLoaderUtils.loadProperties(indexesXML.getResource());
-        for (String idx : indexes.stringPropertyNames()) {
-            LOG.debug("[{}] Creating index {}", domain, indexes.get(idx).toString());
+        Properties views = PropertiesLoaderUtils.loadProperties(viewsXML.getResource());
+        for (String idx : views.stringPropertyNames()) {
+            LOG.debug("[{}] Creating view {}", domain, views.get(idx).toString());
 
             try {
-                jdbcTemplate.execute(indexes.get(idx).toString());
+                jdbcTemplate.execute(views.get(idx).toString().replaceAll("\\n", " "));
             } catch (DataAccessException e) {
-                LOG.error("[{}] Could not create index", domain, e);
+                LOG.error("[{}] Could not create view", domain, e);
             }
         }
 
-        LOG.debug("Indexes created");
+        LOG.debug("Views created");
     }
 
-    private void createViews(final String domain, final DataSource dataSource) throws IOException {
-        LOG.debug("[{}] Creating views", domain);
+    private void createIndexes(final String domain, final DataSource dataSource) throws IOException {
+        LOG.debug("[{}] Creating indexes", domain);
 
         JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
 
-        Properties views = PropertiesLoaderUtils.loadProperties(viewsXML.getResource());
-        for (String idx : views.stringPropertyNames()) {
-            LOG.debug("[{}] Creating view {}", domain, views.get(idx).toString());
+        Properties indexes = PropertiesLoaderUtils.loadProperties(indexesXML.getResource());
+        for (String idx : indexes.stringPropertyNames()) {
+            LOG.debug("[{}] Creating index {}", domain, indexes.get(idx).toString());
 
             try {
-                jdbcTemplate.execute(views.get(idx).toString().replaceAll("\\n", " "));
+                jdbcTemplate.execute(indexes.get(idx).toString());
             } catch (DataAccessException e) {
-                LOG.error("[{}] Could not create view", domain, e);
+                LOG.error("[{}] Could not create index", domain, e);
             }
         }
 
-        LOG.debug("Views created");
+        LOG.debug("Indexes created");
     }
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/36b786c0/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java
index 4a7e490..f882ad7 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java
@@ -54,10 +54,8 @@ import org.apache.syncope.core.persistence.api.entity.group.Group;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.user.URelationship;
 import org.apache.syncope.core.persistence.jpa.entity.JPAAnyUtilsFactory;
-import org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAADynGroupMembership;
 import org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAARelationship;
 import org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAAnyObject;
-import org.apache.syncope.core.persistence.jpa.entity.group.JPAGroup;
 import org.apache.syncope.core.persistence.jpa.entity.user.JPAURelationship;
 import org.apache.syncope.core.spring.ApplicationContextProvider;
 import org.apache.syncope.core.spring.event.AnyCreatedUpdatedEvent;
@@ -262,12 +260,7 @@ public class JPAAnyObjectDAO extends AbstractAnyDAO<AnyObject> implements AnyObj
     @Override
     public List<Group> findDynGroups(final AnyObject anyObject) {
         Query query = entityManager().createNativeQuery(
-                "SELECT t2.id FROM " + JPAADynGroupMembership.TABLE + " t0 "
-                + "INNER JOIN " + JPAADynGroupMembership.JOIN_TABLE + " t1 "
-                + "ON t0.id = t1.aDynGroupMembership_id "
-                + "LEFT OUTER JOIN " + JPAGroup.TABLE + " t2 "
-                + "ON t0.GROUP_ID = t2.id "
-                + "WHERE t1.anyObject_id = ?1");
+                "SELECT group_id FROM " + JPAGroupDAO.ADYNMEMB_TABLE + " WHERE any_id=?");
         query.setParameter(1, anyObject.getKey());
 
         List<Group> result = new ArrayList<>();

http://git-wip-us.apache.org/repos/asf/syncope/blob/36b786c0/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java
index e727572..cc70cd2 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java
@@ -47,6 +47,7 @@ import org.apache.syncope.core.persistence.api.dao.NotFoundException;
 import org.apache.syncope.core.persistence.api.dao.PlainAttrDAO;
 import org.apache.syncope.core.persistence.api.dao.search.AssignableCond;
 import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
+import org.apache.syncope.core.persistence.api.entity.AnyType;
 import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
 import org.apache.syncope.core.persistence.api.entity.AnyUtils;
 import org.apache.syncope.core.persistence.api.entity.Realm;
@@ -55,6 +56,7 @@ import org.apache.syncope.core.persistence.api.entity.anyobject.AMembership;
 import org.apache.syncope.core.persistence.api.entity.anyobject.APlainAttr;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
 import org.apache.syncope.core.persistence.api.entity.group.TypeExtension;
+import org.apache.syncope.core.persistence.api.entity.user.UDynGroupMembership;
 import org.apache.syncope.core.persistence.api.entity.user.UMembership;
 import org.apache.syncope.core.persistence.api.entity.user.UPlainAttr;
 import org.apache.syncope.core.persistence.jpa.entity.JPAAnyUtilsFactory;
@@ -75,6 +77,10 @@ import org.springframework.transaction.annotation.Transactional;
 @Repository
 public class JPAGroupDAO extends AbstractAnyDAO<Group> implements GroupDAO {
 
+    public static final String UDYNMEMB_TABLE = "UDynGroupMembers";
+
+    public static final String ADYNMEMB_TABLE = "ADynGroupMembers";
+
     @Autowired
     private PlainAttrDAO plainAttrDAO;
 
@@ -274,15 +280,20 @@ public class JPAGroupDAO extends AbstractAnyDAO<Group> implements GroupDAO {
         Group merged = super.save(group);
         publisher.publishEvent(new AnyCreatedUpdatedEvent<>(this, merged));
 
-        // refresh dynaminc memberships
+        // refresh dynamic memberships
         if (merged.getUDynMembership() != null) {
             List<User> matching = searchDAO().search(
                     buildDynMembershipCond(merged.getUDynMembership().getFIQLCond(), merged.getRealm()),
                     AnyTypeKind.USER);
 
-            merged.getUDynMembership().clear();
+            clearUDynMembers(merged);
+
             for (User user : matching) {
-                merged.getUDynMembership().add(user);
+                Query insert = entityManager().createNativeQuery("INSERT INTO " + UDYNMEMB_TABLE + " VALUES(?, ?)");
+                insert.setParameter(1, user.getKey());
+                insert.setParameter(2, merged.getKey());
+                insert.executeUpdate();
+
                 publisher.publishEvent(new AnyCreatedUpdatedEvent<>(this, user));
             }
         }
@@ -291,9 +302,15 @@ public class JPAGroupDAO extends AbstractAnyDAO<Group> implements GroupDAO {
                     buildDynMembershipCond(memb.getFIQLCond(), merged.getRealm()),
                     AnyTypeKind.ANY_OBJECT);
 
-            memb.clear();
+            clearADynMembers(merged);
+
             for (AnyObject anyObject : matching) {
-                memb.add(anyObject);
+                Query insert = entityManager().createNativeQuery("INSERT INTO " + ADYNMEMB_TABLE + " VALUES(?, ?, ?)");
+                insert.setParameter(1, anyObject.getType().getKey());
+                insert.setParameter(2, anyObject.getKey());
+                insert.setParameter(3, merged.getKey());
+                insert.executeUpdate();
+
                 publisher.publishEvent(new AnyCreatedUpdatedEvent<>(this, anyObject));
             }
         }
@@ -347,13 +364,13 @@ public class JPAGroupDAO extends AbstractAnyDAO<Group> implements GroupDAO {
     }
 
     @Override
-    public List<String> findADynMembersKeys(final Group group) {
+    public List<String> findADynMembers(final Group group) {
         List<String> result = new ArrayList<>();
         for (ADynGroupMembership memb : group.getADynMemberships()) {
             Query query = entityManager().createNativeQuery(
-                    "SELECT t.anyObject_id FROM " + JPAADynGroupMembership.JOIN_TABLE + " t "
-                    + "WHERE t.aDynGroupMembership_id=?");
-            query.setParameter(1, memb.getKey());
+                    "SELECT any_id FROM " + ADYNMEMB_TABLE + " WHERE group_id=? AND anyType_id=?");
+            query.setParameter(1, group.getKey());
+            query.setParameter(2, memb.getAnyType().getKey());
 
             for (Object key : query.getResultList()) {
                 String actualKey = key instanceof Object[]
@@ -366,45 +383,44 @@ public class JPAGroupDAO extends AbstractAnyDAO<Group> implements GroupDAO {
         return result;
     }
 
-    private List<Group> findWithADynMemberships(final int page, final int itemsPerPage) {
-        TypedQuery<Group> query = entityManager().createQuery(
-                "SELECT e FROM  " + JPAGroup.class.getSimpleName() + " e WHERE e.aDynMemberships IS NOT EMPTY",
-                Group.class);
-        query.setFirstResult(itemsPerPage * (page <= 0 ? 0 : page - 1));
-        query.setMaxResults(itemsPerPage);
+    @Override
+    public void clearADynMembers(final Group group) {
+        Query delete = entityManager().createNativeQuery("DELETE FROM " + ADYNMEMB_TABLE + " WHERE group_id=?");
+        delete.setParameter(1, group.getKey());
+        delete.executeUpdate();
+    }
 
+    private List<ADynGroupMembership> findWithADynMemberships(final AnyType anyType) {
+        TypedQuery<ADynGroupMembership> query = entityManager().createQuery(
+                "SELECT e FROM " + JPAADynGroupMembership.class.getSimpleName() + " e  WHERE e.anyType=:anyType",
+                ADynGroupMembership.class);
+        query.setParameter("anyType", anyType);
         return query.getResultList();
     }
 
     @Transactional
     @Override
     public void refreshDynMemberships(final AnyObject anyObject) {
-        Query countQuery = entityManager().createQuery(
-                "SELECT COUNT(e) FROM  " + JPAGroup.class.getSimpleName() + " e WHERE e.aDynMemberships IS NOT EMPTY");
-        int count = ((Number) countQuery.getSingleResult()).intValue();
-
-        for (int page = 1; page <= (count / DEFAULT_PAGE_SIZE) + 1; page++) {
-            for (Group group : findWithADynMemberships(page, DEFAULT_PAGE_SIZE)) {
-                if (!group.getADynMemberships().isEmpty()) {
-                    for (ADynGroupMembership memb : group.getADynMemberships()) {
-                        if (jpaAnySearchDAO().matches(
-                                anyObject,
-                                buildDynMembershipCond(memb.getFIQLCond(), group.getRealm()))) {
-
-                            memb.add(anyObject);
-                        } else {
-                            Query query = entityManager().createNativeQuery(
-                                    "DELETE FROM " + JPAADynGroupMembership.JOIN_TABLE + " t "
-                                    + "WHERE t.anyObject_id=? and t.aDynGroupMembership_id=?");
-                            query.setParameter(1, anyObject.getKey());
-                            query.setParameter(2, memb.getKey());
-                            query.executeUpdate();
-                        }
-
-                        publisher.publishEvent(new AnyCreatedUpdatedEvent<>(this, group));
-                    }
-                }
+        for (ADynGroupMembership memb : findWithADynMemberships(anyObject.getType())) {
+            Query delete = entityManager().createNativeQuery(
+                    "DELETE FROM " + ADYNMEMB_TABLE + " WHERE group_id=? AND any_id=?");
+            delete.setParameter(1, memb.getGroup().getKey());
+            delete.setParameter(2, anyObject.getKey());
+            delete.executeUpdate();
+
+            if (jpaAnySearchDAO().matches(
+                    anyObject,
+                    buildDynMembershipCond(memb.getFIQLCond(), memb.getGroup().getRealm()))) {
+
+                Query insert = entityManager().createNativeQuery(
+                        "INSERT INTO " + ADYNMEMB_TABLE + " VALUES(?, ?, ?)");
+                insert.setParameter(1, anyObject.getType().getKey());
+                insert.setParameter(2, anyObject.getKey());
+                insert.setParameter(3, memb.getGroup().getKey());
+                insert.executeUpdate();
             }
+
+            publisher.publishEvent(new AnyCreatedUpdatedEvent<>(this, memb.getGroup()));
         }
     }
 
@@ -412,10 +428,9 @@ public class JPAGroupDAO extends AbstractAnyDAO<Group> implements GroupDAO {
     public void removeDynMemberships(final AnyObject anyObject) {
         List<Group> dynGroups = anyObjectDAO().findDynGroups(anyObject);
 
-        Query query = entityManager().createNativeQuery(
-                "DELETE FROM " + JPAADynGroupMembership.JOIN_TABLE + " t WHERE t.anyObject_id=?");
-        query.setParameter(1, anyObject.getKey());
-        query.executeUpdate();
+        Query delete = entityManager().createNativeQuery("DELETE FROM " + ADYNMEMB_TABLE + " WHERE any_id=?");
+        delete.setParameter(1, anyObject.getKey());
+        delete.executeUpdate();
 
         for (Group group : dynGroups) {
             publisher.publishEvent(new AnyCreatedUpdatedEvent<>(this, group));
@@ -423,15 +438,14 @@ public class JPAGroupDAO extends AbstractAnyDAO<Group> implements GroupDAO {
     }
 
     @Override
-    public List<String> findUDynMembersKeys(final Group group) {
+    public List<String> findUDynMembers(final Group group) {
         if (group.getUDynMembership() == null) {
             return Collections.emptyList();
         }
 
         Query query = entityManager().createNativeQuery(
-                "SELECT t.user_id FROM " + JPAUDynGroupMembership.JOIN_TABLE + " t "
-                + "WHERE t.uDynGroupMembership_id=?");
-        query.setParameter(1, group.getUDynMembership().getKey());
+                "SELECT any_id FROM " + UDYNMEMB_TABLE + " WHERE group_id=?");
+        query.setParameter(1, group.getKey());
 
         List<String> result = new ArrayList<>();
         for (Object key : query.getResultList()) {
@@ -444,12 +458,17 @@ public class JPAGroupDAO extends AbstractAnyDAO<Group> implements GroupDAO {
         return result;
     }
 
-    private List<Group> findWithUDynMemberships(final int page, final int itemsPerPage) {
-        TypedQuery<Group> query = entityManager().createQuery(
-                "SELECT e FROM  " + JPAGroup.class.getSimpleName() + " e WHERE e.uDynMembership IS NOT NULL",
-                Group.class);
-        query.setFirstResult(itemsPerPage * (page <= 0 ? 0 : page - 1));
-        query.setMaxResults(itemsPerPage);
+    @Override
+    public void clearUDynMembers(final Group group) {
+        Query delete = entityManager().createNativeQuery("DELETE FROM " + UDYNMEMB_TABLE + " WHERE group_id=?");
+        delete.setParameter(1, group.getKey());
+        delete.executeUpdate();
+    }
+
+    private List<UDynGroupMembership> findWithUDynMemberships() {
+        TypedQuery<UDynGroupMembership> query = entityManager().createQuery(
+                "SELECT e FROM " + JPAUDynGroupMembership.class.getSimpleName() + " e",
+                UDynGroupMembership.class);
 
         return query.getResultList();
     }
@@ -457,30 +476,25 @@ public class JPAGroupDAO extends AbstractAnyDAO<Group> implements GroupDAO {
     @Transactional
     @Override
     public void refreshDynMemberships(final User user) {
-        Query countQuery = entityManager().createQuery(
-                "SELECT COUNT(e) FROM  " + JPAGroup.class.getSimpleName() + " e WHERE e.uDynMembership IS NOT NULL");
-        int count = ((Number) countQuery.getSingleResult()).intValue();
-
-        for (int page = 1; page <= (count / DEFAULT_PAGE_SIZE) + 1; page++) {
-            for (Group group : findWithUDynMemberships(page, DEFAULT_PAGE_SIZE)) {
-                if (group.getUDynMembership() != null) {
-                    if (jpaAnySearchDAO().matches(
-                            user,
-                            buildDynMembershipCond(group.getUDynMembership().getFIQLCond(), group.getRealm()))) {
-
-                        group.getUDynMembership().add(user);
-                    } else {
-                        Query query = entityManager().createNativeQuery(
-                                "DELETE FROM " + JPAUDynGroupMembership.JOIN_TABLE + " t "
-                                + "WHERE t.user_id=? and t.uDynGroupMembership_id=?");
-                        query.setParameter(1, user.getKey());
-                        query.setParameter(2, group.getUDynMembership().getKey());
-                        query.executeUpdate();
-                    }
-
-                    publisher.publishEvent(new AnyCreatedUpdatedEvent<>(this, group));
-                }
+        for (UDynGroupMembership memb : findWithUDynMemberships()) {
+            Query delete = entityManager().createNativeQuery(
+                    "DELETE FROM " + UDYNMEMB_TABLE + " WHERE group_id=? AND any_id=?");
+            delete.setParameter(1, memb.getGroup().getKey());
+            delete.setParameter(2, user.getKey());
+            delete.executeUpdate();
+
+            if (jpaAnySearchDAO().matches(
+                    user,
+                    buildDynMembershipCond(memb.getFIQLCond(), memb.getGroup().getRealm()))) {
+
+                Query insert = entityManager().createNativeQuery(
+                        "INSERT INTO " + UDYNMEMB_TABLE + " VALUES(?, ?)");
+                insert.setParameter(1, user.getKey());
+                insert.setParameter(2, memb.getGroup().getKey());
+                insert.executeUpdate();
             }
+
+            publisher.publishEvent(new AnyCreatedUpdatedEvent<>(this, memb.getGroup()));
         }
     }
 
@@ -488,10 +502,9 @@ public class JPAGroupDAO extends AbstractAnyDAO<Group> implements GroupDAO {
     public void removeDynMemberships(final User user) {
         List<Group> dynGroups = userDAO().findDynGroups(user);
 
-        Query query = entityManager().createNativeQuery(
-                "DELETE FROM " + JPAUDynGroupMembership.JOIN_TABLE + " t WHERE t.user_id=?");
-        query.setParameter(1, user.getKey());
-        query.executeUpdate();
+        Query delete = entityManager().createNativeQuery("DELETE FROM " + UDYNMEMB_TABLE + " WHERE any_id=?");
+        delete.setParameter(1, user.getKey());
+        delete.executeUpdate();
 
         for (Group group : dynGroups) {
             publisher.publishEvent(new AnyCreatedUpdatedEvent<>(this, group));

http://git-wip-us.apache.org/repos/asf/syncope/blob/36b786c0/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARoleDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARoleDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARoleDAO.java
index 7aa9300..b362778 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARoleDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARoleDAO.java
@@ -31,7 +31,6 @@ import org.apache.syncope.core.persistence.api.entity.Realm;
 import org.apache.syncope.core.persistence.api.entity.Role;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.persistence.jpa.entity.JPARole;
-import org.apache.syncope.core.persistence.jpa.entity.user.JPADynRoleMembership;
 import org.apache.syncope.core.persistence.jpa.entity.user.JPAUser;
 import org.apache.syncope.core.spring.ApplicationContextProvider;
 import org.apache.syncope.core.spring.event.AnyCreatedUpdatedEvent;
@@ -43,6 +42,8 @@ import org.springframework.transaction.annotation.Transactional;
 @Repository
 public class JPARoleDAO extends AbstractDAO<Role> implements RoleDAO {
 
+    public static final String DYNMEMB_TABLE = "DynRoleMembers";
+
     @Autowired
     private ApplicationEventPublisher publisher;
 
@@ -86,19 +87,26 @@ public class JPARoleDAO extends AbstractDAO<Role> implements RoleDAO {
 
     @Override
     public Role save(final Role role) {
-        // refresh dynaminc memberships
-        if (role.getDynMembership() != null) {
-            List<User> matchingUsers = searchDAO().search(
-                    SearchCondConverter.convert(role.getDynMembership().getFIQLCond()), AnyTypeKind.USER);
-
-            role.getDynMembership().clear();
-            for (User user : matchingUsers) {
-                role.getDynMembership().add(user);
+        Role merged = entityManager().merge(role);
+
+        // refresh dynamic memberships
+        if (merged.getDynMembership() != null) {
+            List<User> matching = searchDAO().search(
+                    SearchCondConverter.convert(merged.getDynMembership().getFIQLCond()), AnyTypeKind.USER);
+
+            clearDynMembers(merged);
+
+            for (User user : matching) {
+                Query insert = entityManager().createNativeQuery("INSERT INTO " + DYNMEMB_TABLE + " VALUES(?, ?)");
+                insert.setParameter(1, user.getKey());
+                insert.setParameter(2, merged.getKey());
+                insert.executeUpdate();
+
                 publisher.publishEvent(new AnyCreatedUpdatedEvent<>(this, user));
             }
         }
 
-        return entityManager().merge(role);
+        return merged;
     }
 
     @Override
@@ -126,15 +134,13 @@ public class JPARoleDAO extends AbstractDAO<Role> implements RoleDAO {
     }
 
     @Override
-    public List<String> findDynMembersKeys(final Role role) {
+    public List<String> findDynMembers(final Role role) {
         if (role.getDynMembership() == null) {
             return Collections.emptyList();
         }
 
-        Query query = entityManager().createNativeQuery(
-                "SELECT t.user_id FROM " + JPADynRoleMembership.JOIN_TABLE + " t "
-                + "WHERE t.dynRoleMembership_id=?");
-        query.setParameter(1, role.getDynMembership().getKey());
+        Query query = entityManager().createNativeQuery("SELECT any_id FROM " + DYNMEMB_TABLE + " WHERE role_id=?");
+        query.setParameter(1, role.getKey());
 
         List<String> result = new ArrayList<>();
         for (Object key : query.getResultList()) {
@@ -147,20 +153,29 @@ public class JPARoleDAO extends AbstractDAO<Role> implements RoleDAO {
         return result;
     }
 
+    @Override
+    public void clearDynMembers(final Role role) {
+        Query delete = entityManager().createNativeQuery("DELETE FROM " + DYNMEMB_TABLE + " WHERE role_id=?");
+        delete.setParameter(1, role.getKey());
+        delete.executeUpdate();
+    }
+
     @Transactional
     @Override
     public void refreshDynMemberships(final User user) {
         for (Role role : findAll()) {
             if (role.getDynMembership() != null) {
+                Query delete = entityManager().createNativeQuery(
+                        "DELETE FROM " + DYNMEMB_TABLE + " WHERE role_id=? AND any_id=?");
+                delete.setParameter(1, role.getKey());
+                delete.setParameter(2, user.getKey());
+                delete.executeUpdate();
+
                 if (searchDAO().matches(user, SearchCondConverter.convert(role.getDynMembership().getFIQLCond()))) {
-                    role.getDynMembership().add(user);
-                } else {
-                    Query query = entityManager().createNativeQuery(
-                            "DELETE FROM " + JPADynRoleMembership.JOIN_TABLE + " t "
-                            + "WHERE t.user_id=? and t.dynRoleMembership_id=?");
-                    query.setParameter(1, user.getKey());
-                    query.setParameter(2, role.getDynMembership().getKey());
-                    query.executeUpdate();
+                    Query insert = entityManager().createNativeQuery("INSERT INTO " + DYNMEMB_TABLE + " VALUES(?, ?)");
+                    insert.setParameter(1, user.getKey());
+                    insert.setParameter(2, role.getKey());
+                    insert.executeUpdate();
                 }
             }
         }
@@ -168,10 +183,9 @@ public class JPARoleDAO extends AbstractDAO<Role> implements RoleDAO {
 
     @Override
     public void removeDynMemberships(final User user) {
-        Query query = entityManager().createNativeQuery(
-                "DELETE FROM " + JPADynRoleMembership.JOIN_TABLE + " t WHERE t.user_id=?");
-        query.setParameter(1, user.getKey());
-        query.executeUpdate();
+        Query delete = entityManager().createNativeQuery("DELETE FROM " + DYNMEMB_TABLE + " WHERE any_id=?");
+        delete.setParameter(1, user.getKey());
+        delete.executeUpdate();
     }
 
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/36b786c0/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java
index 292b69b..28af7e2 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java
@@ -71,10 +71,6 @@ import org.apache.syncope.core.persistence.api.entity.user.SecurityQuestion;
 import org.apache.syncope.core.persistence.api.entity.user.UMembership;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.persistence.jpa.entity.JPAAnyUtilsFactory;
-import org.apache.syncope.core.persistence.jpa.entity.JPARole;
-import org.apache.syncope.core.persistence.jpa.entity.group.JPAGroup;
-import org.apache.syncope.core.persistence.jpa.entity.user.JPADynRoleMembership;
-import org.apache.syncope.core.persistence.jpa.entity.user.JPAUDynGroupMembership;
 import org.apache.syncope.core.persistence.jpa.entity.user.JPAUser;
 import org.apache.syncope.core.provisioning.api.utils.EntityUtils;
 import org.apache.syncope.core.spring.event.AnyCreatedUpdatedEvent;
@@ -480,12 +476,7 @@ public class JPAUserDAO extends AbstractAnyDAO<User> implements UserDAO {
     @Override
     public List<Role> findDynRoles(final User user) {
         Query query = entityManager().createNativeQuery(
-                "SELECT t2.id FROM " + JPADynRoleMembership.TABLE + " t0 "
-                + "INNER JOIN " + JPADynRoleMembership.JOIN_TABLE + " t1 "
-                + "ON t0.id = t1.dynRoleMembership_id "
-                + "LEFT OUTER JOIN " + JPARole.TABLE + " t2 "
-                + "ON t0.ROLE_ID = t2.id "
-                + "WHERE (t1.user_id = ?1)");
+                "SELECT role_id FROM " + JPARoleDAO.DYNMEMB_TABLE + " WHERE any_id=?");
         query.setParameter(1, user.getKey());
 
         List<Role> result = new ArrayList<>();
@@ -508,12 +499,7 @@ public class JPAUserDAO extends AbstractAnyDAO<User> implements UserDAO {
     @Override
     public List<Group> findDynGroups(final User user) {
         Query query = entityManager().createNativeQuery(
-                "SELECT t2.id FROM " + JPAUDynGroupMembership.TABLE + " t0 "
-                + "INNER JOIN " + JPAUDynGroupMembership.JOIN_TABLE + " t1 "
-                + "ON t0.id = t1.uDynGroupMembership_id "
-                + "LEFT OUTER JOIN " + JPAGroup.TABLE + " t2 "
-                + "ON t0.GROUP_ID = t2.id "
-                + "WHERE (t1.user_id = ?1)");
+                "SELECT group_id FROM " + JPAGroupDAO.UDYNMEMB_TABLE + " WHERE any_id=?");
         query.setParameter(1, user.getKey());
 
         List<Group> result = new ArrayList<>();

http://git-wip-us.apache.org/repos/asf/syncope/blob/36b786c0/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/SearchSupport.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/SearchSupport.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/SearchSupport.java
index 9964d89..fd40470 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/SearchSupport.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/SearchSupport.java
@@ -123,8 +123,8 @@ class SearchSupport {
     }
 
     public SearchView dyngroupmembership() {
-        String kind = anyTypeKind == AnyTypeKind.USER ? "u" : "a";
-        return new SearchView("sv" + kind + "dgm", field().name + "_" + kind + "dyngmemb");
+        return new SearchView("sv" + anyTypeKind.name() + "dgm",
+                anyTypeKind == AnyTypeKind.USER ? JPAGroupDAO.UDYNMEMB_TABLE : JPAGroupDAO.ADYNMEMB_TABLE);
     }
 
     public SearchView role() {
@@ -132,7 +132,7 @@ class SearchSupport {
     }
 
     public SearchView dynrolemembership() {
-        return new SearchView("svdr", field().name + "_dynrmemb");
+        return new SearchView("svdr", JPARoleDAO.DYNMEMB_TABLE);
     }
 
     public SearchView nullAttr() {

http://git-wip-us.apache.org/repos/asf/syncope/blob/36b786c0/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAADynGroupMembership.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAADynGroupMembership.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAADynGroupMembership.java
index 5ae02d3..b1d55ff 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAADynGroupMembership.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAADynGroupMembership.java
@@ -18,12 +18,7 @@
  */
 package org.apache.syncope.core.persistence.jpa.entity.anyobject;
 
-import java.util.ArrayList;
-import java.util.List;
 import javax.persistence.Entity;
-import javax.persistence.JoinColumn;
-import javax.persistence.JoinTable;
-import javax.persistence.ManyToMany;
 import javax.persistence.ManyToOne;
 import javax.persistence.OneToOne;
 import javax.persistence.Table;
@@ -43,21 +38,12 @@ public class JPAADynGroupMembership extends AbstractDynMembership<AnyObject> imp
 
     public static final String TABLE = "ADynGroupMembership";
 
-    public static final String JOIN_TABLE = TABLE + "_AnyObject";
-
     @OneToOne
     private JPAGroup group;
 
     @ManyToOne
     private JPAAnyType anyType;
 
-    @ManyToMany
-    @JoinTable(name = JOIN_TABLE, joinColumns =
-            @JoinColumn(name = "aDynGroupMembership_id"),
-            inverseJoinColumns =
-            @JoinColumn(name = "anyObject_id"))
-    private List<JPAAnyObject> anyObjects = new ArrayList<>();
-
     @Override
     public Group getGroup() {
         return group;
@@ -79,16 +65,4 @@ public class JPAADynGroupMembership extends AbstractDynMembership<AnyObject> imp
         checkType(anyType, JPAAnyType.class);
         this.anyType = (JPAAnyType) anyType;
     }
-
-    @Override
-    public boolean add(final AnyObject anyObject) {
-        checkType(anyObject, JPAAnyObject.class);
-        return anyObjects.add((JPAAnyObject) anyObject);
-    }
-
-    @Override
-    public void clear() {
-        anyObjects.clear();
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/36b786c0/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/AbstractUDynMembership.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/AbstractUDynMembership.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/AbstractUDynMembership.java
deleted file mode 100644
index 963b742..0000000
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/AbstractUDynMembership.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.core.persistence.jpa.entity.user;
-
-import java.util.List;
-import javax.persistence.MappedSuperclass;
-import org.apache.syncope.core.persistence.api.entity.user.User;
-import org.apache.syncope.core.persistence.jpa.entity.AbstractDynMembership;
-
-@MappedSuperclass
-public abstract class AbstractUDynMembership extends AbstractDynMembership<User> {
-
-    private static final long serialVersionUID = 6296230283800203205L;
-
-    protected abstract List<JPAUser> internalGetUsers();
-
-    @Override
-    public boolean add(final User user) {
-        checkType(user, JPAUser.class);
-        return internalGetUsers().add((JPAUser) user);
-    }
-
-    @Override
-    public void clear() {
-        internalGetUsers().clear();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/36b786c0/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPADynRoleMembership.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPADynRoleMembership.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPADynRoleMembership.java
index aa310cd..d2a4480 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPADynRoleMembership.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPADynRoleMembership.java
@@ -18,43 +18,26 @@
  */
 package org.apache.syncope.core.persistence.jpa.entity.user;
 
-import java.util.ArrayList;
-import java.util.List;
 import javax.persistence.Entity;
-import javax.persistence.JoinColumn;
-import javax.persistence.JoinTable;
-import javax.persistence.ManyToMany;
 import javax.persistence.OneToOne;
 import javax.persistence.Table;
 import org.apache.syncope.core.persistence.api.entity.user.DynRoleMembership;
 import org.apache.syncope.core.persistence.api.entity.Role;
+import org.apache.syncope.core.persistence.api.entity.user.User;
+import org.apache.syncope.core.persistence.jpa.entity.AbstractDynMembership;
 import org.apache.syncope.core.persistence.jpa.entity.JPARole;
 
 @Entity
 @Table(name = JPADynRoleMembership.TABLE)
-public class JPADynRoleMembership extends AbstractUDynMembership implements DynRoleMembership {
+public class JPADynRoleMembership extends AbstractDynMembership<User> implements DynRoleMembership {
 
     private static final long serialVersionUID = -7336814163949640354L;
 
     public static final String TABLE = "DynRoleMembership";
 
-    public static final String JOIN_TABLE = TABLE + "_User";
-
     @OneToOne
     private JPARole role;
 
-    @ManyToMany
-    @JoinTable(name = JOIN_TABLE, joinColumns =
-            @JoinColumn(name = "dynRoleMembership_id"),
-            inverseJoinColumns =
-            @JoinColumn(name = "user_id"))
-    private List<JPAUser> users = new ArrayList<>();
-
-    @Override
-    protected List<JPAUser> internalGetUsers() {
-        return users;
-    }
-
     @Override
     public Role getRole() {
         return role;

http://git-wip-us.apache.org/repos/asf/syncope/blob/36b786c0/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUDynGroupMembership.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUDynGroupMembership.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUDynGroupMembership.java
index 63228b3..875b572 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUDynGroupMembership.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUDynGroupMembership.java
@@ -18,43 +18,26 @@
  */
 package org.apache.syncope.core.persistence.jpa.entity.user;
 
-import java.util.ArrayList;
-import java.util.List;
 import javax.persistence.Entity;
-import javax.persistence.JoinColumn;
-import javax.persistence.JoinTable;
-import javax.persistence.ManyToMany;
 import javax.persistence.OneToOne;
 import javax.persistence.Table;
 import org.apache.syncope.core.persistence.api.entity.group.Group;
 import org.apache.syncope.core.persistence.api.entity.user.UDynGroupMembership;
+import org.apache.syncope.core.persistence.api.entity.user.User;
+import org.apache.syncope.core.persistence.jpa.entity.AbstractDynMembership;
 import org.apache.syncope.core.persistence.jpa.entity.group.JPAGroup;
 
 @Entity
 @Table(name = JPAUDynGroupMembership.TABLE)
-public class JPAUDynGroupMembership extends AbstractUDynMembership implements UDynGroupMembership {
+public class JPAUDynGroupMembership extends AbstractDynMembership<User> implements UDynGroupMembership {
 
     private static final long serialVersionUID = -7336814163949640354L;
 
     public static final String TABLE = "UDynGroupMembership";
 
-    public static final String JOIN_TABLE = TABLE + "_User";
-
     @OneToOne
     private JPAGroup group;
 
-    @ManyToMany
-    @JoinTable(name = JOIN_TABLE, joinColumns =
-            @JoinColumn(name = "uDynGroupMembership_id"),
-            inverseJoinColumns =
-            @JoinColumn(name = "user_id"))
-    private List<JPAUser> users = new ArrayList<>();
-
-    @Override
-    protected List<JPAUser> internalGetUsers() {
-        return users;
-    }
-
     @Override
     public Group getGroup() {
         return group;

http://git-wip-us.apache.org/repos/asf/syncope/blob/36b786c0/core/persistence-jpa/src/main/resources/indexes.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/resources/indexes.xml b/core/persistence-jpa/src/main/resources/indexes.xml
index 4d2ffcb..1dfa63d 100644
--- a/core/persistence-jpa/src/main/resources/indexes.xml
+++ b/core/persistence-jpa/src/main/resources/indexes.xml
@@ -21,6 +21,14 @@ under the License.
 <properties>
   <comment>Additional indexes (in respect to JPA's)</comment>
 
+  <entry key="UDynGroupMembers_any_id">CREATE INDEX UDynGroupMembers_any_id ON UDynGroupMembers(any_id)</entry>
+  <entry key="UDynGroupMembers_group_id">CREATE INDEX UDynGroupMembers_group_id ON UDynGroupMembers(group_id)</entry>
+  <entry key="ADynGroupMembers_any_id">CREATE INDEX ADynGroupMembers_any_id ON ADynGroupMembers(any_id)</entry>
+  <entry key="ADynGroupMembers_group_id">CREATE INDEX ADynGroupMembers_group_id ON ADynGroupMembers(group_id)</entry>
+
+  <entry key="DynRoleMembers_any_id">CREATE INDEX DynRoleMembers_any_id ON DynRoleMembers(any_id)</entry>
+  <entry key="DynRoleMembers_role_id">CREATE INDEX DynRoleMembers_role_id ON DynRoleMembers(role_id)</entry>
+
   <entry key="UPlainAttrValue_stringvalueIndex">CREATE INDEX UAttrValue_stringvalueIndex ON UPlainAttrValue(stringvalue)</entry>
   <entry key="UPlainAttrValue_datevalueIndex">CREATE INDEX UAttrValue_datevalueIndex ON UPlainAttrValue(datevalue)</entry>
   <entry key="UPlainAttrValue_longvalueIndex">CREATE INDEX UAttrValue_longvalueIndex ON UPlainAttrValue(longvalue)</entry>

http://git-wip-us.apache.org/repos/asf/syncope/blob/36b786c0/core/persistence-jpa/src/main/resources/views.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/resources/views.xml b/core/persistence-jpa/src/main/resources/views.xml
index 59ec334..fb68516 100644
--- a/core/persistence-jpa/src/main/resources/views.xml
+++ b/core/persistence-jpa/src/main/resources/views.xml
@@ -19,8 +19,27 @@ under the License.
 -->
 <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
 <properties>
-  <comment>Views</comment>
   
+  <entry key="UDynGroupMembers">
+    CREATE TABLE UDynGroupMembers(
+    any_id CHAR(36),
+    group_id CHAR(36),
+    UNIQUE(any_id, group_id))
+  </entry>
+  <entry key="ADynGroupMembers">
+    CREATE TABLE ADynGroupMembers(
+    anyType_id VARCHAR(255),
+    any_id CHAR(36),
+    group_id CHAR(36),
+    UNIQUE(anyType_id, any_id, group_id))
+  </entry>
+  <entry key="DynRoleMembers">
+    CREATE TABLE DynRoleMembers(
+    any_id CHAR(36),
+    role_id CHAR(36),
+    UNIQUE(any_id, role_id))
+  </entry>
+
   <!-- user -->
   <entry key="user_search">
     CREATE VIEW user_search AS
@@ -80,26 +99,12 @@ under the License.
     FROM UMembership m, SyncopeGroup g
     WHERE m.group_id = g.id
   </entry>
-  <entry key="user_search_udyngmemb">
-    CREATE VIEW user_search_udyngmemb AS
-
-    SELECT ds.user_id AS any_id, d.group_id AS group_id
-    FROM UDynGroupMembership d, UDynGroupMembership_User ds
-    WHERE d.id = ds.uDynGroupMembership_id
-  </entry>
   <entry key="user_search_role">
     CREATE VIEW user_search_role AS
 
     SELECT ss.user_id AS any_id, ss.role_id AS role_id
     FROM SyncopeUser_SyncopeRole ss
   </entry>
-  <entry key="user_search_dynrmemb">
-    CREATE VIEW user_search_dynrmemb AS
-
-    SELECT ds.user_id AS any_id, d.role_id AS role_id
-    FROM DynRoleMembership d, DynRoleMembership_User ds
-    WHERE d.id = ds.dynRoleMembership_id
-  </entry>
   <entry key="user_search_resource">
     CREATE VIEW user_search_resource AS
 
@@ -173,13 +178,6 @@ under the License.
     FROM AMembership m, SyncopeGroup g
     WHERE m.group_id = g.id
   </entry>
-  <entry key="anyObject_search_adyngmemb">
-    CREATE VIEW anyObject_search_adyngmemb AS
-
-    SELECT ds.anyObject_id AS any_id, d.group_id AS group_id
-    FROM ADynGroupMembership d, ADynGroupMembership_AnyObject ds
-    WHERE d.id = ds.aDynGroupMembership_id
-  </entry>
   <entry key="anyObject_search_resource">
     CREATE VIEW anyObject_search_resource AS
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/36b786c0/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/GroupTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/GroupTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/GroupTest.java
index ff050bf..fc359e3 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/GroupTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/GroupTest.java
@@ -29,7 +29,7 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
-import javax.persistence.TypedQuery;
+import javax.persistence.Query;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.Predicate;
 import org.apache.syncope.common.lib.SyncopeConstants;
@@ -55,6 +55,7 @@ import org.apache.syncope.core.persistence.api.entity.user.UDynGroupMembership;
 import org.apache.syncope.core.persistence.api.entity.user.UPlainAttr;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.persistence.jpa.AbstractTest;
+import org.apache.syncope.core.persistence.jpa.dao.JPAGroupDAO;
 import org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAADynGroupMembership;
 import org.apache.syncope.core.persistence.jpa.entity.user.JPAUDynGroupMembership;
 import org.junit.Test;
@@ -178,13 +179,23 @@ public class GroupTest extends AbstractTest {
      * required for avoiding creating of a new transaction - good for general use case but bad for the way how
      * this test class is architected.
      */
-    private Collection<Group> findDynGroupMemberships(final User user) {
-        TypedQuery<Group> query = entityManager().createQuery(
-                "SELECT e.group FROM " + JPAUDynGroupMembership.class.getSimpleName()
-                + " e WHERE :user MEMBER OF e.users", Group.class);
-        query.setParameter("user", user);
-
-        return query.getResultList();
+    private List<Group> findDynGroups(final User user) {
+        Query query = entityManager().createNativeQuery(
+                "SELECT group_id FROM " + JPAGroupDAO.UDYNMEMB_TABLE + " WHERE any_id=?");
+        query.setParameter(1, user.getKey());
+
+        List<Group> result = new ArrayList<>();
+        for (Object key : query.getResultList()) {
+            String actualKey = key instanceof Object[]
+                    ? (String) ((Object[]) key)[0]
+                    : ((String) key);
+
+            Group group = groupDAO.find(actualKey);
+            if (group != null && !result.contains(group)) {
+                result.add(group);
+            }
+        }
+        return result;
     }
 
     @Test
@@ -229,14 +240,14 @@ public class GroupTest extends AbstractTest {
         assertEquals(actual, actual.getUDynMembership().getGroup());
 
         // 3. verify that expected users have the created group dynamically assigned
-        List<String> members = groupDAO.findUDynMembersKeys(actual);
+        List<String> members = groupDAO.findUDynMembers(actual);
         assertEquals(2, members.size());
         assertEquals(new HashSet<>(Arrays.asList("c9b2dec2-00a7-4855-97c0-d854842b4b24", newUserKey)),
                 new HashSet<>(members));
 
         user = userDAO.findByUsername("bellini");
         assertNotNull(user);
-        Collection<Group> dynGroupMemberships = findDynGroupMemberships(user);
+        Collection<Group> dynGroupMemberships = findDynGroups(user);
         assertEquals(1, dynGroupMemberships.size());
         assertTrue(dynGroupMemberships.contains(actual.getUDynMembership().getGroup()));
 
@@ -246,7 +257,7 @@ public class GroupTest extends AbstractTest {
         userDAO.flush();
 
         actual = groupDAO.find(actual.getKey());
-        members = groupDAO.findUDynMembersKeys(actual);
+        members = groupDAO.findUDynMembers(actual);
         assertEquals(1, members.size());
         assertEquals("c9b2dec2-00a7-4855-97c0-d854842b4b24", members.get(0));
 
@@ -259,7 +270,7 @@ public class GroupTest extends AbstractTest {
 
         assertNull(entityManager().find(JPAUDynGroupMembership.class, dynMembershipKey));
 
-        dynGroupMemberships = findDynGroupMemberships(user);
+        dynGroupMemberships = findDynGroups(user);
         assertTrue(dynGroupMemberships.isEmpty());
     }
 
@@ -268,13 +279,23 @@ public class GroupTest extends AbstractTest {
      * required for avoiding creating of a new transaction - good for general use case but bad for the way how
      * this test class is architected.
      */
-    private List<Group> findDynGroupMemberships(final AnyObject anyObject) {
-        TypedQuery<Group> query = entityManager().createQuery(
-                "SELECT e.group FROM " + JPAADynGroupMembership.class.getSimpleName()
-                + " e WHERE :anyObject MEMBER OF e.anyObjects", Group.class);
-        query.setParameter("anyObject", anyObject);
-
-        return query.getResultList();
+    private List<Group> findDynGroups(final AnyObject anyObject) {
+        Query query = entityManager().createNativeQuery(
+                "SELECT group_id FROM " + JPAGroupDAO.ADYNMEMB_TABLE + " WHERE any_id=?");
+        query.setParameter(1, anyObject.getKey());
+
+        List<Group> result = new ArrayList<>();
+        for (Object key : query.getResultList()) {
+            String actualKey = key instanceof Object[]
+                    ? (String) ((Object[]) key)[0]
+                    : ((String) key);
+
+            Group group = groupDAO.find(actualKey);
+            if (group != null && !result.contains(group)) {
+                result.add(group);
+            }
+        }
+        return result;
     }
 
     @Test
@@ -320,8 +341,7 @@ public class GroupTest extends AbstractTest {
         assertEquals(actual, actual.getADynMembership(anyTypeDAO.find("PRINTER")).getGroup());
 
         // 3. verify that expected any objects have the created group dynamically assigned
-        System.out.println("MMMMMMMMM " + groupDAO.findADynMembersKeys(actual));
-        List<String> members = CollectionUtils.select(groupDAO.findADynMembersKeys(actual), new Predicate<String>() {
+        List<String> members = CollectionUtils.select(groupDAO.findADynMembers(actual), new Predicate<String>() {
 
             @Override
             public boolean evaluate(final String object) {
@@ -335,7 +355,7 @@ public class GroupTest extends AbstractTest {
 
         anyObject = anyObjectDAO.find("fc6dbc3a-6c07-4965-8781-921e7401a4a5");
         assertNotNull(anyObject);
-        Collection<Group> dynGroupMemberships = findDynGroupMemberships(anyObject);
+        Collection<Group> dynGroupMemberships = findDynGroups(anyObject);
         assertEquals(1, dynGroupMemberships.size());
         assertTrue(dynGroupMemberships.contains(actual.getADynMembership(anyTypeDAO.find("PRINTER")).getGroup()));
 
@@ -345,7 +365,7 @@ public class GroupTest extends AbstractTest {
         anyObjectDAO.flush();
 
         actual = groupDAO.find(actual.getKey());
-        members = CollectionUtils.select(groupDAO.findADynMembersKeys(actual), new Predicate<String>() {
+        members = CollectionUtils.select(groupDAO.findADynMembers(actual), new Predicate<String>() {
 
             @Override
             public boolean evaluate(final String object) {
@@ -364,7 +384,7 @@ public class GroupTest extends AbstractTest {
 
         assertNull(entityManager().find(JPAADynGroupMembership.class, dynMembershipKey));
 
-        dynGroupMemberships = findDynGroupMemberships(anyObject);
+        dynGroupMemberships = findDynGroups(anyObject);
         assertTrue(dynGroupMemberships.isEmpty());
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/36b786c0/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/RoleTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/RoleTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/RoleTest.java
index 49d92c7..6ba7906 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/RoleTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/RoleTest.java
@@ -23,11 +23,12 @@ import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
-import javax.persistence.TypedQuery;
+import javax.persistence.Query;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
 import org.apache.syncope.core.persistence.api.dao.AnyTypeClassDAO;
@@ -40,6 +41,7 @@ import org.apache.syncope.core.persistence.api.entity.Role;
 import org.apache.syncope.core.persistence.api.entity.user.UPlainAttr;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.persistence.jpa.AbstractTest;
+import org.apache.syncope.core.persistence.jpa.dao.JPARoleDAO;
 import org.apache.syncope.core.persistence.jpa.entity.user.JPADynRoleMembership;
 import org.junit.Test;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -68,13 +70,23 @@ public class RoleTest extends AbstractTest {
      * required for avoiding creating new transaction - good for general use case but bad for the way how
      * this test class is architected.
      */
-    private Collection<Role> findDynRoleMemberships(final User user) {
-        TypedQuery<Role> query = entityManager().createQuery(
-                "SELECT e.role FROM " + JPADynRoleMembership.class.getSimpleName()
-                + " e WHERE :user MEMBER OF e.users", Role.class);
-        query.setParameter("user", user);
-
-        return query.getResultList();
+    private List<Role> findDynRoles(final User user) {
+        Query query = entityManager().createNativeQuery(
+                "SELECT role_id FROM " + JPARoleDAO.DYNMEMB_TABLE + " WHERE any_id=?");
+        query.setParameter(1, user.getKey());
+
+        List<Role> result = new ArrayList<>();
+        for (Object key : query.getResultList()) {
+            String actualKey = key instanceof Object[]
+                    ? (String) ((Object[]) key)[0]
+                    : ((String) key);
+
+            Role role = roleDAO.find(actualKey);
+            if (role != null && !result.contains(role)) {
+                result.add(role);
+            }
+        }
+        return result;
     }
 
     @Test
@@ -122,7 +134,7 @@ public class RoleTest extends AbstractTest {
         assertEquals(actual, actual.getDynMembership().getRole());
 
         // 3. verify that expected users have the created role dynamically assigned
-        List<String> members = roleDAO.findDynMembersKeys(actual);
+        List<String> members = roleDAO.findDynMembers(actual);
         assertEquals(2, members.size());
         assertEquals(
                 new HashSet<>(Arrays.asList("c9b2dec2-00a7-4855-97c0-d854842b4b24", newUserKey)),
@@ -130,7 +142,7 @@ public class RoleTest extends AbstractTest {
 
         user = userDAO.find("c9b2dec2-00a7-4855-97c0-d854842b4b24");
         assertNotNull(user);
-        Collection<Role> dynRoleMemberships = findDynRoleMemberships(user);
+        Collection<Role> dynRoleMemberships = findDynRoles(user);
         assertEquals(1, dynRoleMemberships.size());
         assertTrue(dynRoleMemberships.contains(actual.getDynMembership().getRole()));
 
@@ -140,7 +152,7 @@ public class RoleTest extends AbstractTest {
         userDAO.flush();
 
         actual = roleDAO.find(actual.getKey());
-        members = roleDAO.findDynMembersKeys(actual);
+        members = roleDAO.findDynMembers(actual);
         assertEquals(1, members.size());
         assertEquals("c9b2dec2-00a7-4855-97c0-d854842b4b24", members.get(0));
 
@@ -153,7 +165,7 @@ public class RoleTest extends AbstractTest {
 
         assertNull(entityManager().find(JPADynRoleMembership.class, dynMembershipKey));
 
-        dynRoleMemberships = findDynRoleMemberships(user);
+        dynRoleMemberships = findDynRoles(user);
         assertTrue(dynRoleMemberships.isEmpty());
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/36b786c0/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/RoleDataBinder.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/RoleDataBinder.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/RoleDataBinder.java
index 7631543..3ebd707 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/RoleDataBinder.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/RoleDataBinder.java
@@ -25,7 +25,7 @@ public interface RoleDataBinder {
 
     Role create(RoleTO roleTO);
 
-    void update(Role role, RoleTO roleTO);
+    Role update(Role role, RoleTO roleTO);
 
     RoleTO getRoleTO(Role role);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/36b786c0/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java
index fa17f20..dc944b5 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java
@@ -251,7 +251,7 @@ public class AnyObjectDataBinderImpl extends AbstractAnyDataBinder implements An
     @Override
     public PropagationByResource update(final AnyObject toBeUpdated, final AnyObjectPatch anyObjectPatch) {
         // Re-merge any pending change from workflow tasks
-        final AnyObject anyObject = anyObjectDAO.save(toBeUpdated);
+        AnyObject anyObject = anyObjectDAO.save(toBeUpdated);
 
         PropagationByResource propByRes = new PropagationByResource();
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/36b786c0/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java
index d0d751a..32206aa 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java
@@ -230,11 +230,14 @@ public class GroupDataBinderImpl extends AbstractAnyDataBinder implements GroupD
             }
         }
 
+        group = groupDAO.save(group);
+        
         // dynamic membership
         if (groupPatch.getUDynMembershipCond() == null) {
             if (group.getUDynMembership() != null) {
                 group.getUDynMembership().setGroup(null);
                 group.setUDynMembership(null);
+                groupDAO.clearUDynMembers(group);
             }
         } else {
             setDynMembership(group, anyTypeDAO.findUser(), groupPatch.getUDynMembershipCond());
@@ -244,6 +247,7 @@ public class GroupDataBinderImpl extends AbstractAnyDataBinder implements GroupD
             memb.setGroup(null);
             itor.remove();
         }
+        groupDAO.clearADynMembers(group);
         for (Map.Entry<String, String> entry : groupPatch.getADynMembershipConds().entrySet()) {
             AnyType anyType = anyTypeDAO.find(entry.getKey());
             if (anyType == null) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/36b786c0/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RoleDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RoleDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RoleDataBinderImpl.java
index 567739d..6ccb229 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RoleDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RoleDataBinderImpl.java
@@ -25,6 +25,7 @@ import org.apache.syncope.common.lib.to.RoleTO;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.core.persistence.api.search.SearchCondConverter;
 import org.apache.syncope.core.persistence.api.dao.RealmDAO;
+import org.apache.syncope.core.persistence.api.dao.RoleDAO;
 import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
 import org.apache.syncope.core.persistence.api.entity.EntityFactory;
 import org.apache.syncope.core.persistence.api.entity.Realm;
@@ -45,6 +46,9 @@ public class RoleDataBinderImpl implements RoleDataBinder {
     private RealmDAO realmDAO;
 
     @Autowired
+    private RoleDAO roleDAO;
+
+    @Autowired
     private EntityFactory entityFactory;
 
     private void setDynMembership(final Role role, final String dynMembershipFIQL) {
@@ -68,14 +72,13 @@ public class RoleDataBinderImpl implements RoleDataBinder {
 
     @Override
     public Role create(final RoleTO roleTO) {
-        Role role = entityFactory.newEntity(Role.class);
-        update(role, roleTO);
-        return role;
+        return update(entityFactory.newEntity(Role.class), roleTO);
     }
 
     @Override
-    public void update(final Role role, final RoleTO roleTO) {
-        role.setKey(roleTO.getKey());
+    public Role update(final Role toBeUpdated, final RoleTO roleTO) {
+        toBeUpdated.setKey(roleTO.getKey());
+        Role role = roleDAO.save(toBeUpdated);
 
         role.getEntitlements().clear();
         role.getEntitlements().addAll(roleTO.getEntitlements());
@@ -90,7 +93,10 @@ public class RoleDataBinderImpl implements RoleDataBinder {
             }
         }
 
+        role = roleDAO.save(role);
+
         // dynamic membership
+        roleDAO.clearDynMembers(role);
         if (role.getKey() == null && roleTO.getDynMembershipCond() != null) {
             setDynMembership(role, roleTO.getDynMembershipCond());
         } else if (role.getDynMembership() != null && roleTO.getDynMembershipCond() == null) {
@@ -100,9 +106,10 @@ public class RoleDataBinderImpl implements RoleDataBinder {
         } else if (role.getDynMembership() != null && roleTO.getDynMembershipCond() != null
                 && !role.getDynMembership().getFIQLCond().equals(roleTO.getDynMembershipCond())) {
 
-            role.getDynMembership().clear();
             setDynMembership(role, roleTO.getDynMembershipCond());
         }
+
+        return role;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/36b786c0/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
index 647e850..0140de3 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
@@ -174,6 +174,27 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat
     public void create(final User user, final UserTO userTO, final boolean storePassword) {
         SyncopeClientCompositeException scce = SyncopeClientException.buildComposite();
 
+        // set username
+        user.setUsername(userTO.getUsername());
+
+        // set password
+        if (StringUtils.isBlank(userTO.getPassword()) || !storePassword) {
+            LOG.debug("Password was not provided or not required to be stored");
+        } else {
+            setPassword(user, userTO.getPassword(), scce);
+        }
+
+        user.setMustChangePassword(userTO.isMustChangePassword());
+
+        // security question / answer
+        if (userTO.getSecurityQuestion() != null) {
+            SecurityQuestion securityQuestion = securityQuestionDAO.find(userTO.getSecurityQuestion());
+            if (securityQuestion != null) {
+                user.setSecurityQuestion(securityQuestion);
+            }
+        }
+        user.setSecurityAnswer(userTO.getSecurityAnswer());
+
         // roles
         for (String roleKey : userTO.getRoles()) {
             Role role = roleDAO.find(roleKey);
@@ -262,27 +283,6 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat
         // attributes and resources
         fill(user, userTO, anyUtils, scce);
 
-        // set password
-        if (StringUtils.isBlank(userTO.getPassword()) || !storePassword) {
-            LOG.debug("Password was not provided or not required to be stored");
-        } else {
-            setPassword(user, userTO.getPassword(), scce);
-        }
-
-        // set username
-        user.setUsername(userTO.getUsername());
-
-        // security question / answer
-        if (userTO.getSecurityQuestion() != null) {
-            SecurityQuestion securityQuestion = securityQuestionDAO.find(userTO.getSecurityQuestion());
-            if (securityQuestion != null) {
-                user.setSecurityQuestion(securityQuestion);
-            }
-        }
-        user.setSecurityAnswer(userTO.getSecurityAnswer());
-
-        user.setMustChangePassword(userTO.isMustChangePassword());
-
         // Throw composite exception if there is at least one element set in the composing exceptions
         if (scce.hasExceptions()) {
             throw scce;

http://git-wip-us.apache.org/repos/asf/syncope/blob/36b786c0/ext/elasticsearch/client-elasticsearch/src/main/java/org/apache/syncope/ext/elasticsearch/client/ElasticsearchUtils.java
----------------------------------------------------------------------
diff --git a/ext/elasticsearch/client-elasticsearch/src/main/java/org/apache/syncope/ext/elasticsearch/client/ElasticsearchUtils.java b/ext/elasticsearch/client-elasticsearch/src/main/java/org/apache/syncope/ext/elasticsearch/client/ElasticsearchUtils.java
index 1ff146e..47bcf9d 100644
--- a/ext/elasticsearch/client-elasticsearch/src/main/java/org/apache/syncope/ext/elasticsearch/client/ElasticsearchUtils.java
+++ b/ext/elasticsearch/client-elasticsearch/src/main/java/org/apache/syncope/ext/elasticsearch/client/ElasticsearchUtils.java
@@ -138,7 +138,7 @@ public class ElasticsearchUtils {
                     return input.getLeftEnd().getKey();
                 }
             }, new ArrayList<>());
-            members.add(groupDAO.findUDynMembersKeys(group));
+            members.add(groupDAO.findUDynMembers(group));
             CollectionUtils.collect(groupDAO.findAMemberships(group),
                     new Transformer<AMembership, Object>() {
 
@@ -147,7 +147,7 @@ public class ElasticsearchUtils {
                     return input.getLeftEnd().getKey();
                 }
             }, members);
-            members.add(groupDAO.findADynMembersKeys(group));
+            members.add(groupDAO.findADynMembers(group));
             builder = builder.field("members", members);
         } else if (any instanceof User) {
             User user = ((User) any);