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 2019/10/10 08:22:25 UTC
[syncope] 01/02: [SYNCOPE-1502]: find anytos in single query
This is an automated email from the ASF dual-hosted git repository.
ilgrosso pushed a commit to branch 2_1_X
in repository https://gitbox.apache.org/repos/asf/syncope.git
commit 10027bbcda7388dcac778eb931b2e26836d6de2c
Author: Dmitriy Brashevets <dm...@united-security-providers.ch>
AuthorDate: Wed Oct 9 12:25:39 2019 +0300
[SYNCOPE-1502]: find anytos in single query
- AnyTO objects are searched by keys retrieved from the search view using a single SQL query that contains IN condition
- replacement of multiple OR-realm condition in the resulted SQL query that is executed to search entities in search views with IN clause.
---
.../syncope/core/persistence/api/dao/AnyDAO.java | 2 +
.../core/persistence/jpa/dao/AbstractAnyDAO.java | 12 ++++++
.../persistence/jpa/dao/AbstractAnySearchDAO.java | 45 +++++++++++++---------
.../core/persistence/jpa/dao/JPAAnySearchDAO.java | 26 ++++++-------
4 files changed, 53 insertions(+), 32 deletions(-)
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyDAO.java
index 787f1cb..fb888eb 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyDAO.java
@@ -37,6 +37,8 @@ public interface AnyDAO<A extends Any<?>> extends DAO<A> {
String findKey(String name);
+ List<A> findByKeys(List<String> keys);
+
Date findLastChange(String key);
A authFind(String key);
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnyDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnyDAO.java
index 76761f1..90ed53f 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnyDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnyDAO.java
@@ -32,6 +32,8 @@ import java.util.Set;
import java.util.regex.Pattern;
import javax.persistence.Query;
import javax.persistence.TemporalType;
+import javax.persistence.TypedQuery;
+
import org.apache.commons.jexl3.parser.Parser;
import org.apache.commons.jexl3.parser.ParserConstants;
import org.apache.commons.jexl3.parser.Token;
@@ -153,6 +155,16 @@ public abstract class AbstractAnyDAO<A extends Any<?>> extends AbstractDAO<A> im
@Transactional(readOnly = true)
@Override
+ public List<A> findByKeys(List<String> keys) {
+ Class<A> entityClass = anyUtils().anyClass();
+ TypedQuery<A> query = entityManager()
+ .createQuery("SELECT e FROM " + entityClass.getSimpleName() + " e WHERE e.id IN (:keys)", entityClass);
+ query.setParameter("keys", keys);
+ return query.getResultList();
+ }
+
+ @Transactional(readOnly = true)
+ @Override
public A authFind(final String key) {
if (key == null) {
throw new NotFoundException("Null key");
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnySearchDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnySearchDAO.java
index cc17e32..4cebca7 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnySearchDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnySearchDAO.java
@@ -21,8 +21,12 @@ package org.apache.syncope.core.persistence.jpa.dao;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
+import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import javax.validation.ValidationException;
@@ -297,26 +301,31 @@ public abstract class AbstractAnySearchDAO extends AbstractDAO<Any<?>> implement
}
protected <T extends Any<?>> List<T> buildResult(final List<Object> raw, final AnyTypeKind kind) {
- List<T> result = new ArrayList<>();
+ List<String> orderedAnyKeys = extractSortedAnyKeys(raw);
+ return constructSortedAnyTOsBySortedKeys(findAnyTOs(kind, orderedAnyKeys), orderedAnyKeys, kind);
+ }
- raw.stream().map(anyKey -> anyKey instanceof Object[]
+ private List<String> extractSortedAnyKeys(List<Object> raw) {
+ return raw.stream().map(anyKey -> anyKey instanceof Object[]
? (String) ((Object[]) anyKey)[0]
- : ((String) anyKey)).
- forEachOrdered(actualKey -> {
- @SuppressWarnings("unchecked")
- T any = kind == AnyTypeKind.USER
- ? (T) userDAO.find(actualKey)
- : kind == AnyTypeKind.GROUP
- ? (T) groupDAO.find(actualKey)
- : (T) anyObjectDAO.find(actualKey);
- if (any == null) {
- LOG.error("Could not find {} with id {}, even if returned by native query", kind, actualKey);
- } else if (!result.contains(any)) {
- result.add(any);
- }
- });
-
- return result;
+ : ((String) anyKey))
+ .collect(Collectors.toList());
+ }
+
+ @SuppressWarnings("unchecked")
+ private <T extends Any<?>> List<T> findAnyTOs(AnyTypeKind kind, List<String> orderedAnyKeys) {
+ return new ArrayList<>((List<T>)anyUtilsFactory.getInstance(kind).dao().findByKeys(orderedAnyKeys));
+ }
+
+ private <T extends Any<?>> List<T> constructSortedAnyTOsBySortedKeys(List<T> anyTOs,
+ List<String> sortedAnyKeys, AnyTypeKind kind) {
+ Map<String, T> anyMap = anyTOs.stream().collect(Collectors.toMap(T::getKey, anyTO -> anyTO));
+ return sortedAnyKeys.stream().map(key -> {
+ if (anyMap.get(key) == null) {
+ LOG.error("Could not find {} with id {}, even if returned by native query", kind, key);
+ }
+ return anyMap.get(key);
+ }).filter(Objects::nonNull).collect(Collectors.toList());
}
@Override
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
index 3e0ccf2..29fc8e4 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
@@ -97,24 +97,22 @@ public class JPAAnySearchDAO extends AbstractAnySearchDAO {
map(Entity::getKey).collect(Collectors.toSet()));
}
+ List<String> realmKeyArgs = getRealmKeySqlArgsAndFillParameters(parameters, realmKeys);
+
StringBuilder adminRealmFilter = new StringBuilder("u.any_id IN (").
- append("SELECT any_id FROM ").append(svs.field().name).
- append(" WHERE realm_id IN (SELECT id AS realm_id FROM Realm");
+ append("SELECT any_id FROM ").append(svs.field().name)
+ .append(" WHERE realm_id IN (")
+ .append(StringUtils.join(realmKeyArgs, ", "))
+ .append("))");
+ return Pair.of(adminRealmFilter.toString(), dynRealmKeys);
+ }
- boolean firstRealm = true;
+ private List<String> getRealmKeySqlArgsAndFillParameters(List<Object> parameters, Set<String> realmKeys) {
+ List<String> realmKeyArgs = new ArrayList<>();
for (String realmKey : realmKeys) {
- if (firstRealm) {
- adminRealmFilter.append(" WHERE");
- firstRealm = false;
- } else {
- adminRealmFilter.append(" OR");
- }
- adminRealmFilter.append(" id=?").append(setParameter(parameters, realmKey));
+ realmKeyArgs.add("?" + setParameter(parameters, realmKey));
}
-
- adminRealmFilter.append("))");
-
- return Pair.of(adminRealmFilter.toString(), dynRealmKeys);
+ return realmKeyArgs;
}
SearchSupport buildSearchSupport(final AnyTypeKind kind) {