mirror of
https://gitee.com/jmix/cuba.git
synced 2024-12-04 12:17:41 +08:00
Support list parameters for JPQL query (rollback our changes and use EL capability). #PL-5846 #PL-6108
This commit is contained in:
parent
24650c4d9f
commit
069b647bb9
@ -398,7 +398,7 @@ public class DataManagerBean implements DataManager {
|
||||
View view = new View(baseAttributeValueView, null, false)
|
||||
.addProperty("categoryAttribute", new View(baseAttributeView, null, false).addProperty("category"));
|
||||
|
||||
return em.createQuery("select cav from sys$CategoryAttributeValue cav where cav.entityId in (:ids)", CategoryAttributeValue.class)
|
||||
return em.createQuery("select cav from sys$CategoryAttributeValue cav where cav.entityId in :ids", CategoryAttributeValue.class)
|
||||
.setParameter("ids", entityIds)
|
||||
.setView(view)
|
||||
.getResultList();
|
||||
|
@ -7,16 +7,15 @@ package com.haulmont.cuba.core.sys;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.haulmont.bali.util.ReflectionHelper;
|
||||
import com.haulmont.cuba.core.TypedQuery;
|
||||
import com.haulmont.cuba.core.entity.BaseEntity;
|
||||
import com.haulmont.cuba.core.entity.Entity;
|
||||
import com.haulmont.cuba.core.global.*;
|
||||
import com.haulmont.cuba.core.sys.persistence.DbmsFeatures;
|
||||
import com.haulmont.cuba.core.sys.persistence.DbmsSpecificFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.eclipse.persistence.config.HintValues;
|
||||
import org.eclipse.persistence.config.QueryHints;
|
||||
import org.eclipse.persistence.jpa.JpaQuery;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.persistence.FlushModeType;
|
||||
@ -135,8 +134,6 @@ public class QueryImpl<T> implements TypedQuery<T> {
|
||||
for (Param param : params) {
|
||||
if (param.value instanceof String && ((String) param.value).startsWith("(?i)"))
|
||||
result = replaceCaseInsensitiveParam(result, param);
|
||||
if (param.value instanceof Collection)
|
||||
result = replaceCollectionParam(result, param);
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -164,27 +161,13 @@ public class QueryImpl<T> implements TypedQuery<T> {
|
||||
return result;
|
||||
}
|
||||
|
||||
private String replaceCollectionParam(String queryStr, Param param) {
|
||||
if (!(param.name instanceof String))
|
||||
throw new UnsupportedOperationException("Only named collection parameters are supported");
|
||||
|
||||
Collection collection = (Collection) param.value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < collection.size(); i++) {
|
||||
sb.append(":").append(param.name).append(i+1);
|
||||
if (i < collection.size() - 1)
|
||||
sb.append(",");
|
||||
}
|
||||
return queryStr.replace(":" + param.name, sb.toString());
|
||||
}
|
||||
|
||||
private void addMacroParams(javax.persistence.TypedQuery jpaQuery) {
|
||||
if (macroHandlers != null) {
|
||||
for (QueryMacroHandler handler : macroHandlers) {
|
||||
|
||||
Map<String, Object> namedParams = new HashMap<>();
|
||||
for (Param param : params) {
|
||||
if (param.name instanceof String && !(param.value instanceof Collection))
|
||||
if (param.name instanceof String)
|
||||
namedParams.put((String) param.name, param.value);
|
||||
}
|
||||
handler.setQueryParams(namedParams);
|
||||
@ -263,20 +246,25 @@ public class QueryImpl<T> implements TypedQuery<T> {
|
||||
checkState();
|
||||
|
||||
if (implicitConversions) {
|
||||
if (value instanceof Entity)
|
||||
value = ((BaseEntity) value).getId();
|
||||
else if (value instanceof Collection) {
|
||||
List<Object> list = new ArrayList<>(((Collection) value).size());
|
||||
for (Object obj : ((Collection) value)) {
|
||||
list.add(obj instanceof Entity ? ((Entity) obj).getId() : obj);
|
||||
}
|
||||
value = list;
|
||||
}
|
||||
value = handleImplicitConversions(value);
|
||||
}
|
||||
params.add(new Param(name, value));
|
||||
return this;
|
||||
}
|
||||
|
||||
private Object handleImplicitConversions(Object value) {
|
||||
if (value instanceof Entity)
|
||||
value = ((Entity) value).getId();
|
||||
else if (value instanceof Collection) {
|
||||
List<Object> list = new ArrayList<>(((Collection) value).size());
|
||||
for (Object obj : ((Collection) value)) {
|
||||
list.add(obj instanceof Entity ? ((Entity) obj).getId() : obj);
|
||||
}
|
||||
value = list;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypedQuery<T> setParameter(String name, Date value, TemporalType temporalType) {
|
||||
checkState();
|
||||
@ -298,10 +286,11 @@ public class QueryImpl<T> implements TypedQuery<T> {
|
||||
try {
|
||||
value = ReflectionHelper.newInstance(c, value);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException(e);
|
||||
throw new RuntimeException("Error setting parameter value", e);
|
||||
}
|
||||
} else if (implicitConversions && value instanceof Entity)
|
||||
value = ((BaseEntity) value).getId();
|
||||
} else if (implicitConversions) {
|
||||
value = handleImplicitConversions(value);
|
||||
}
|
||||
|
||||
params.add(new Param(position, value));
|
||||
return this;
|
||||
@ -405,29 +394,15 @@ public class QueryImpl<T> implements TypedQuery<T> {
|
||||
|
||||
public void apply(JpaQuery query) {
|
||||
if (temporalType != null) {
|
||||
if (name instanceof Integer) {
|
||||
if (name instanceof Integer)
|
||||
query.setParameter((int) name, (Date) value, temporalType);
|
||||
} else {
|
||||
else
|
||||
query.setParameter((String) name, (Date) value, temporalType);
|
||||
}
|
||||
} else {
|
||||
if (name instanceof Integer) {
|
||||
if (name instanceof Integer)
|
||||
query.setParameter((int) name, value);
|
||||
} else {
|
||||
if (value instanceof Collection) {
|
||||
applyCollection(query, (String) name, (Collection) value);
|
||||
} else {
|
||||
query.setParameter((String) name, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void applyCollection(JpaQuery query, String name, Collection collection) {
|
||||
int i = 1;
|
||||
for (Object value : collection) {
|
||||
query.setParameter(name + i, value);
|
||||
i++;
|
||||
else
|
||||
query.setParameter((String) name, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,7 +125,7 @@ public class UserManagementServiceBean implements UserManagementService {
|
||||
throw new IllegalStateException("Could not found target access group with id: " + targetAccessGroupId);
|
||||
}
|
||||
|
||||
TypedQuery<User> query = em.createQuery("select u from sec$User u where u.id in (:userIds)", User.class);
|
||||
TypedQuery<User> query = em.createQuery("select u from sec$User u where u.id in :userIds", User.class);
|
||||
query.setParameter("userIds", userIds);
|
||||
query.setViewName(MOVE_USER_TO_GROUP_VIEW);
|
||||
|
||||
@ -232,7 +232,7 @@ public class UserManagementServiceBean implements UserManagementService {
|
||||
try {
|
||||
EntityManager em = persistence.getEntityManager();
|
||||
|
||||
Query query = em.createQuery("delete from sec$RememberMeToken rt where rt.user.id in (:userIds)");
|
||||
Query query = em.createQuery("delete from sec$RememberMeToken rt where rt.user.id in :userIds");
|
||||
query.setParameter("userIds", userIds);
|
||||
query.executeUpdate();
|
||||
|
||||
@ -445,7 +445,7 @@ public class UserManagementServiceBean implements UserManagementService {
|
||||
try {
|
||||
EntityManager em = persistence.getEntityManager();
|
||||
|
||||
TypedQuery<User> query = em.createQuery("select u from sec$User u where u.id in (:userIds)", User.class);
|
||||
TypedQuery<User> query = em.createQuery("select u from sec$User u where u.id in :userIds", User.class);
|
||||
query.setParameter("userIds", userIds);
|
||||
query.setViewName(RESET_PASSWORD_VIEW);
|
||||
|
||||
|
@ -304,7 +304,7 @@ public class QueryTest extends CubaTestCase {
|
||||
public void testListParameter() throws Exception {
|
||||
try (Transaction tx = persistence.createTransaction()) {
|
||||
TypedQuery<User> query = persistence.getEntityManager().createQuery(
|
||||
"select u from sec$User u where u.id in (:ids) order by u.createTs", User.class);
|
||||
"select u from sec$User u where u.id in :ids order by u.createTs", User.class);
|
||||
query.setParameter("ids", Arrays.asList(UUID.fromString("60885987-1b61-4247-94c7-dff348347f93"), userId, user2Id));
|
||||
List<User> list = query.getResultList();
|
||||
assertEquals(3, list.size());
|
||||
@ -326,7 +326,7 @@ public class QueryTest extends CubaTestCase {
|
||||
|
||||
try (Transaction tx = persistence.createTransaction()) {
|
||||
TypedQuery<User> query = persistence.getEntityManager().createQuery(
|
||||
"select u from sec$User u where u.id in (:ids) order by u.createTs", User.class);
|
||||
"select u from sec$User u where u.id in :ids order by u.createTs", User.class);
|
||||
query.setParameter("ids", Arrays.asList(user1, user2, user3));
|
||||
List<User> list = query.getResultList();
|
||||
assertEquals(3, list.size());
|
||||
@ -334,18 +334,26 @@ public class QueryTest extends CubaTestCase {
|
||||
tx.commit();
|
||||
}
|
||||
|
||||
// Positional parameters are not supported
|
||||
// Positional parameters
|
||||
|
||||
try (Transaction tx = persistence.createTransaction()) {
|
||||
TypedQuery<User> query = persistence.getEntityManager().createQuery(
|
||||
"select u from sec$User u where u.id in (?1) order by u.createTs", User.class);
|
||||
"select u from sec$User u where u.id in ?1 order by u.createTs", User.class);
|
||||
query.setParameter(1, Arrays.asList(user1.getId(), user2.getId(), user3.getId()));
|
||||
List<User> list = query.getResultList();
|
||||
assertEquals(3, list.size());
|
||||
|
||||
tx.commit();
|
||||
}
|
||||
|
||||
// Positional parameters with implicit conversion
|
||||
|
||||
try (Transaction tx = persistence.createTransaction()) {
|
||||
TypedQuery<User> query = persistence.getEntityManager().createQuery(
|
||||
"select u from sec$User u where u.id in ?1 order by u.createTs", User.class);
|
||||
query.setParameter(1, Arrays.asList(user1, user2, user3));
|
||||
try {
|
||||
query.getResultList();
|
||||
fail();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
// ok
|
||||
}
|
||||
List<User> list = query.getResultList();
|
||||
assertEquals(3, list.size());
|
||||
|
||||
tx.commit();
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
package com.haulmont.cuba.core.global;
|
||||
|
||||
import com.haulmont.cuba.core.sys.jpql.DomainModel;
|
||||
import com.haulmont.cuba.core.sys.jpql.ErrorsFoundException;
|
||||
import com.haulmont.cuba.core.sys.jpql.QueryErrorsFoundException;
|
||||
import com.haulmont.cuba.core.sys.jpql.model.Entity;
|
||||
import com.haulmont.cuba.core.sys.jpql.model.EntityBuilder;
|
||||
import com.haulmont.cuba.core.sys.jpql.model.EntityImpl;
|
||||
@ -602,7 +602,7 @@ public class QueryTransformerAstBasedTest {
|
||||
new QueryTransformerAstBased(model,
|
||||
"select h from sec$GroupHierarchy h join h.parent.constraints c group by c.level order by c.level having c.level > 0");
|
||||
fail("Incorrectly placed 'having' passed");
|
||||
} catch (ErrorsFoundException e) {
|
||||
} catch (QueryErrorsFoundException e) {
|
||||
}
|
||||
}
|
||||
|
||||
@ -614,7 +614,7 @@ public class QueryTransformerAstBasedTest {
|
||||
new QueryTransformerAstBased(model,
|
||||
"select h from sec$GroupHierarchy h join h.parent.constraints");
|
||||
fail("Not named join variable passed");
|
||||
} catch (ErrorsFoundException e) {
|
||||
} catch (QueryErrorsFoundException e) {
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,14 +108,14 @@ public class QueryTransformerSoftDeleteBugsTest extends TestCase {
|
||||
QueryTransformerRegex transformer = new QueryTransformerRegex(
|
||||
"select j from taxi$IndividualTelephone it, taxi$Job j\n" +
|
||||
"where it.telephone like :phoneNumber and it.individual.id = j.caller.id\n" +
|
||||
"and j.executionStatus not in (:notActiveStatuses)");
|
||||
"and j.executionStatus not in :notActiveStatuses");
|
||||
|
||||
transformer.addWhere("{E}.deleteTs is null");
|
||||
String res = transformer.getResult();
|
||||
assertEquals(
|
||||
"select j from taxi$IndividualTelephone it, taxi$Job j\n" +
|
||||
"where it.telephone like :phoneNumber and it.individual.id = j.caller.id\n" +
|
||||
"and j.executionStatus not in (:notActiveStatuses) and (it.deleteTs is null)",
|
||||
"and j.executionStatus not in :notActiveStatuses and (it.deleteTs is null)",
|
||||
res);
|
||||
}
|
||||
}
|
@ -12,13 +12,14 @@ import java.util.List;
|
||||
* @author chevelev
|
||||
* @version $Id$
|
||||
*/
|
||||
public class ErrorsFoundException extends RuntimeException{
|
||||
public class QueryErrorsFoundException extends RuntimeException{
|
||||
|
||||
private List<ErrorRec> errorRecs;
|
||||
|
||||
public ErrorsFoundException() {
|
||||
public QueryErrorsFoundException() {
|
||||
}
|
||||
|
||||
public ErrorsFoundException(String message, List<ErrorRec> errorRecs) {
|
||||
public QueryErrorsFoundException(String message, List<ErrorRec> errorRecs) {
|
||||
super(message);
|
||||
this.errorRecs = new ArrayList<>(errorRecs);
|
||||
}
|
||||
@ -28,11 +29,11 @@ public class ErrorsFoundException extends RuntimeException{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String result = "";
|
||||
public String getMessage() {
|
||||
String message = super.getMessage();
|
||||
for (ErrorRec rec : errorRecs) {
|
||||
result += rec + "\n";
|
||||
message += "\n" + rec;
|
||||
}
|
||||
return result;
|
||||
return message;
|
||||
}
|
||||
}
|
@ -69,7 +69,7 @@ public class QueryTransformerAstBased implements QueryTransformer {
|
||||
}
|
||||
|
||||
if (!errors.isEmpty()) {
|
||||
throw new ErrorsFoundException("Errors found", errors);
|
||||
throw new QueryErrorsFoundException("Errors found", errors);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,8 +150,6 @@ public class BulkEditorWindow extends AbstractWindow {
|
||||
datasource.setAllowCommit(false);
|
||||
|
||||
createDataComponents();
|
||||
|
||||
datasource.refresh();
|
||||
}
|
||||
|
||||
protected void createDataComponents() {
|
||||
@ -552,7 +550,7 @@ public class BulkEditorWindow extends AbstractWindow {
|
||||
}
|
||||
|
||||
protected List<Entity> loadItems(View view) {
|
||||
LoadContext lc = new LoadContext(metaClass);
|
||||
LoadContext<Entity> lc = new LoadContext<>(metaClass);
|
||||
lc.setSoftDeletion(false);
|
||||
|
||||
List<UUID> ids = new ArrayList<>();
|
||||
|
@ -41,7 +41,7 @@ public class UserSetHelper {
|
||||
|
||||
String listOfId = createIdsString(ids);
|
||||
String randomName = RandomStringUtils.randomAlphabetic(10);
|
||||
condition.addText(entityAlias + ".id in (:component$" + componentId + "." + randomName + ")");
|
||||
condition.addText(entityAlias + ".id in :component$" + componentId + "." + randomName);
|
||||
|
||||
Element param = condition.addElement("param");
|
||||
param.addAttribute("name", "component$" + componentId + "." + randomName);
|
||||
|
Loading…
Reference in New Issue
Block a user