@Override public Object execute(Object[] parameters) { NamedParameterJdbcOperations jdbcTemplate = BeanFactoryUtils.getBeanByNameOrType(beanFactory, configuration.getOperationsBeanName(), NamedParameterJdbcOperations.class); Map<String, Object> paramMap = new HashMap<>(); for (int i = 0; i < parameters.length; i++) { Parameter param = queryMethod.getParameters().getParameter(i); paramMap.put(param.getName(), convertValue(parameters[i], param.getType())); } Class<?> resultType = queryMethod.getReturnedObjectType(); if (queryMethod.isModifyingQuery()) { return jdbcTemplate.update(getQuery(), paramMap); } else { return jdbcTemplate.query(getQuery(), paramMap, getRowMapper(this.queryMethod, resultType)); } }
@Override protected boolean canBindParameter(Parameter parameter) { List<StringQuery.ParameterBinding> parameterBindings = query.getParameterBindings(); // if no parameter bindings are present, we simply rely on the check in super. if (parameterBindings.isEmpty()) { return super.canBindParameter(parameter); } // otherwise determine whether there are any non expression parameters left to be bound. int expressionParameterCount = 0; for (StringQuery.ParameterBinding binding : parameterBindings) { if (binding.isExpression()) { expressionParameterCount++; } } boolean allParametersAreUsedInExpressions = parameterBindings.size() - expressionParameterCount == 0; // if all parameters are used in expressions, then we can skip their bindings now, since they'll get bound later. return !allParametersAreUsedInExpressions && super.canBindParameter(parameter); }
/** * Finds the {@link LikeParameterBinding} to be applied before binding a parameter value to the query. * * @param ebeanQuery must not be {@literal null}. * @param position * @param parameter must not be {@literal null}. * @return the {@link ParameterBinding} for the given parameters or {@literal null} if none available. */ private ParameterBinding getBindingFor(Object ebeanQuery, int position, Parameter parameter) { Assert.notNull(ebeanQuery, "Query must not be null!"); Assert.notNull(parameter, "Parameter must not be null!"); if (parameter.isNamedParameter()) { return query.getBindingFor( Optional.ofNullable(parameter.getName()).orElseThrow(() -> new IllegalArgumentException("Parameter needs to be named!")).get()); } try { return query.getBindingFor(position); } catch (IllegalArgumentException ex) { // We should actually reject parameters unavailable, but as EclipseLink doesn't implement ….getParameter(int) for // native queries correctly we need to fall back to an indexed parameter // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=427892 return new ParameterBinding(position); } }
/** * Binds the parameters to the given {@link Query}. * * @param query must not be {@literal null}. * @return */ public Object bind(Object query) { Assert.notNull(query, "Query must not be null!"); int bindableParameterIndex = 0; int queryParameterPosition = 1; for (Parameter parameter : parameters) { if (canBindParameter(parameter)) { Object value = accessor.getBindableValue(bindableParameterIndex); bind(query, parameter, value, queryParameterPosition++); bindableParameterIndex++; } } return query; }
private Map<String, Object> getParams(Object[] values) { JpaParameters parameters = getQueryMethod().getParameters(); //gen model Map<String, Object> params = new HashMap<String, Object>(); for (int i = 0; i < parameters.getNumberOfParameters(); i++) { Object value = values[i]; Parameter parameter = parameters.getParameter(i); if (value != null && canBindParameter(parameter)) { if (!QueryBuilder.isValidValue(value)) { continue; } Class<?> clz = value.getClass(); if (clz.isPrimitive() || String.class.isAssignableFrom(clz) || Number.class.isAssignableFrom(clz) || clz.isArray() || Collection.class.isAssignableFrom(clz) || clz.isEnum()) { params.put(parameter.getName(), value); } else { params = QueryBuilder.toParams(value); } } } return params; }
static String buildQuery(final String rawQuery, Parameters parameters, Object... parameterValues) { String replacedRawQuery = rawQuery; for (Iterator<Parameter> iterator = parameters.iterator(); iterator .hasNext();) { Parameter eachParameter = iterator.next(); if (Pageable.class.isAssignableFrom(eachParameter.getType()) || Sort.class.isAssignableFrom(eachParameter.getType())) { continue; } replacedRawQuery = replaceOneParameterInQuery(replacedRawQuery, eachParameter, parameterValues[eachParameter.getIndex()]); } return replacedRawQuery.trim(); }
private void assertParameterNamesInAnnotatedQuery(String annotatedQuery) { if(!StringUtils.hasText(annotatedQuery)) { return; } for(Parameter parameter : getParameters()) { if(!parameter.isNamedParameter()) { continue; } if(!annotatedQuery.contains(String.format(":%s", parameter.getName()))) { throw new IllegalStateException(String.format( "Using named parameters for method %s but parameter '%s' not found in annotated query '%s'!", method, parameter.getName(), annotatedQuery)); } } }
/** * @return whether or not the query method contains a {@link Pageable} parameter in its signature. */ public boolean isPagedQuery() { boolean isPaged = false; final Iterator<Parameter> it = getParameters().iterator(); while(it.hasNext()) { final Parameter param = it.next(); if(Pageable.class.isAssignableFrom(param.getType())) { isPaged = true; break; } } return isPaged; }
/** * Builds a new {@link ParameterMetadata} for the given type and name. * * @param <T> * @param part must not be {@literal null}. * @param type parameter type, must not be {@literal null}. * @param parameter * @return */ private <T> ParameterMetadata<T> next(Part part, Class<T> type, Parameter parameter) { Assert.notNull(type, "Type must not be null!"); ParameterMetadata<T> value = new ParameterMetadata<T>(type, parameter.getName().get(), part.getType(), bindableParameterValues == null ? ParameterMetadata.PLACEHOLDER : bindableParameterValues.next()); expressions.add(value); return value; }
public List<Object> getParameterValues(Method method, MongoParameterAccessor mongoParameterAccessor, ConvertingParameterAccessor convertingParameterAccessor) { List<Object> retval = new ArrayList<>(); int numArgs = method.getParameterCount(); for (int i = 0; i < numArgs; i++) { Parameter param = ((MongoParametersParameterAccessor) mongoParameterAccessor).getParameters().getParameter(i); if (param.isBindable()) { retval.add(convertingParameterAccessor.getBindableValue(i)); } else { LOGGER.debug("{} was unbindable, adding it as an unbindable object", param.getName()); retval.add(new UnbindableObject(param.getName())); } } return retval; }
private void assertParameterNamesInAnnotatedQuery() { String annotatedQuery = getAnnotatedQuery(); if (!QueryUtils.hasNamedParameter(annotatedQuery)) { return; } for (Parameter parameter : getParameters()) { if (!parameter.isNamedParameter()) { continue; } String paramName=parameter.getName().orElse(null); if (!annotatedQuery.contains(String.format(":%s", paramName)) && !annotatedQuery.contains(String.format("#%s", paramName))) { throw new IllegalStateException(String.format("Using named parameters for method %s but parameter '%s' not found in annotated query '%s'!", method, parameter.getName(), annotatedQuery)); } } }
/** * <P> * Determine if the arguments to the method need reordered. * </P> * <P> * For searches such as {@code findBySomethingNotNull} there may be more parts than parameters needed to be bound to * them. * </P> * * @param partTree Query parts * @param bindableParameters Parameters expected */ @SuppressWarnings("unchecked") private void prepareRearrange(final PartTree partTree, final Parameters<?, ?> bindableParameters) { this.isRearrangeRequired = false; if (partTree == null || bindableParameters == null) { return; } List<String> queryParams = new ArrayList<>(); List<String> methodParams = new ArrayList<>(); Iterator<Part> partTreeIterator = partTree.getParts().iterator(); while (partTreeIterator.hasNext()) { Part part = partTreeIterator.next(); queryParams.add(part.getProperty().getSegment()); } Iterator<Parameter> bindableParameterIterator = (Iterator<Parameter>) bindableParameters.iterator(); while (bindableParameterIterator.hasNext()) { Parameter parameter = bindableParameterIterator.next(); methodParams.add(parameter.getName()); } this.rearrangeIndex = new int[queryParams.size()]; String[] paramsExpected = queryParams.toArray(new String[queryParams.size()]); String[] paramsProvided = methodParams.toArray(new String[methodParams.size()]); for (int i = 0; i < this.rearrangeIndex.length; i++) { this.rearrangeIndex[i] = i; for (int j = 0; j < paramsProvided.length; j++) { if (paramsProvided[j] != null && paramsProvided[j].equals(paramsExpected[i])) { this.rearrangeIndex[i] = j; this.isRearrangeRequired = true; } } } }
public static boolean hasNamedParameter(SimpleDbQueryMethod queryMethod) { for (Parameter param : queryMethod.getParameters()) { if (param.isNamedParameter()) { return Boolean.TRUE; } } return Boolean.FALSE; }
/** * Supported types: primitives & core java types (Date, primitive arrays, * primitive wrappers) */ public static void validateBindParametersTypes(Parameters parameters) { final Iterator<Parameter> it = parameters.iterator(); while (it.hasNext()) { final Parameter param = it.next(); final Class<?> paramType = param.getType(); if (!(param.isSpecialParameter() || SupportedCoreTypes .isSupported(paramType))) { throw (new IllegalArgumentException("Type " + paramType + " not supported as an annotated query parameter!")); } } }
@SuppressWarnings({ "rawtypes", "unchecked" }) private Parameter getMockParameter(String placeHolder, Integer idx, Class clazz) { Parameter mockParameter = Mockito.mock(Parameter.class); Mockito.when(mockParameter.getPlaceholder()).thenReturn(placeHolder); Mockito.when(mockParameter.isNamedParameter()).thenReturn(Boolean.TRUE); Mockito.when(mockParameter.getIndex()).thenReturn(idx); Mockito.when(mockParameter.getType()).thenReturn(clazz); Mockito.when(mockParameter.isSpecialParameter()).thenReturn(TYPES.contains(clazz)); return mockParameter; }
@SuppressWarnings({ "rawtypes" }) private Parameters getMockParameters(String[] placeHolders, Class[] clazzes) { Parameters mockParameters = Mockito.mock(Parameters.class); List<Parameter> parameters = new ArrayList<Parameter>(placeHolders.length); for(int idx = 0; idx < placeHolders.length; ++idx) { parameters.add(getMockParameter(placeHolders[idx], idx, clazzes[idx])); } Mockito.when(mockParameters.iterator()).thenReturn(parameters.iterator()); Mockito.when(mockParameters.getNumberOfParameters()).thenReturn(parameters.size()); return mockParameters; }
@SuppressWarnings({ "rawtypes", "unchecked" }) private Parameter getMockParameter(String placeHolder, Integer idx, Class clazz) { Parameter mockParameter = Mockito.mock(Parameter.class); Mockito.when(mockParameter.getPlaceholder()).thenReturn(placeHolder); Mockito.when(mockParameter.isNamedParameter()).thenReturn(Boolean.FALSE); Mockito.when(mockParameter.getIndex()).thenReturn(idx); Mockito.when(mockParameter.getType()).thenReturn(clazz); Mockito.when(mockParameter.isSpecialParameter()).thenReturn(TYPES.contains(clazz)); return mockParameter; }
@SuppressWarnings({ "rawtypes", "unchecked" }) private Parameter getMockParameter(String placeHolder, Integer idx, Class clazz) { Parameter mockParameter = Mockito.mock(Parameter.class); Mockito.when(mockParameter.getPlaceholder()).thenReturn(placeHolder); Mockito.when(mockParameter.isNamedParameter()).thenReturn(Boolean.FALSE); Mockito.when(mockParameter.getIndex()).thenReturn(idx); Mockito.when(mockParameter.getType()).thenReturn(clazz); Mockito.when(mockParameter.getType()).thenReturn(clazz); Mockito.when(mockParameter.isSpecialParameter()).thenReturn(TYPES.contains(clazz)); return mockParameter; }
@Override protected void bind(Object ebeanQuery, Parameter methodParameter, Object value, int position) { ParameterBinding binding = getBindingFor(ebeanQuery, position, methodParameter); super.bind(ebeanQuery, methodParameter, binding.prepare(value), position); }
protected boolean canBindParameter(Parameter parameter) { return parameter.isBindable(); }
@SuppressWarnings({ "rawtypes", "unchecked" }) private <T, ID extends Serializable> void setupCommonMocksForThisRepositoryMethod( DynamoDBEntityInformation<T, ID> mockEntityMetadata, DynamoDBQueryMethod<T, ID> mockDynamoDBQueryMethod, Class<T> clazz, String repositoryMethodName, int numberOfParameters, String hashKeyProperty, String rangeKeyProperty) { if (rangeKeyProperty != null) { Mockito.when(mockEntityMetadata.isRangeKeyAware()).thenReturn(true); } // Dirty Harry 9 3/4: In recent versions of spring-data-commons, a lot of methods within // org.springframework.data.repository.query.QueryMethod have become final. Thus they can't // be mocked by Mockito anymore https://github.com/mockito/mockito/wiki/FAQ#what-are-the-limitations-of-mockito // Therefore setting the field explicitly that is used by all the isXXX methods try { Field unwrappedReturnTypeField = mockDynamoDBQueryMethod.getClass() // Mockito-generated class .getSuperclass() // org.socialsignin.spring.data.dynamodb.repository.query.DynamoDBQueryMethod .getSuperclass() // org.springframework.data.repository.query.QueryMethod .getDeclaredField("unwrappedReturnType"); unwrappedReturnTypeField.setAccessible(true); // It's final therefore unlocking the field unwrappedReturnTypeField.set(mockDynamoDBQueryMethod, clazz); } catch (Exception e) { // There is little we can and want do if it fails - Aborting the whole test is fine throw new RuntimeException(e); } Class returnedObjectClass = clazz; Mockito.when(mockDynamoDBQueryMethod.getEntityType()).thenReturn(clazz); Mockito.when(mockDynamoDBQueryMethod.getName()).thenReturn(repositoryMethodName); Mockito.when(mockParameters.getNumberOfParameters()).thenReturn(numberOfParameters); Mockito.when(mockDynamoDBQueryMethod.getReturnedObjectType()).thenReturn(returnedObjectClass); if (hashKeyProperty != null) { Mockito.when(mockEntityMetadata.isHashKeyProperty(hashKeyProperty)).thenReturn(true); } for (int i = 0; i < numberOfParameters; i++) { Parameter mockParameter = Mockito.mock(Parameter.class); Mockito.when(mockParameter.getIndex()).thenReturn(i); Mockito.when(mockParameters.getBindableParameter(i)).thenReturn(mockParameter); } partTreeDynamoDBQuery = new PartTreeDynamoDBQuery(mockDynamoDBOperations, mockDynamoDBQueryMethod); }
static String replaceOneParameterInQuery(String rawQuery, Parameter parameter, Object parameterValue) { final String bindEndCharacter = "\\b"; String namedParameter; if (parameter.isNamedParameter()) { namedParameter = parameter.getPlaceholder() + bindEndCharacter; } else { namedParameter = "\\?"; } Assert.isTrue(rawQuery.matches("(.*)(" + namedParameter + ")(.*)")); // String rawQuery = aRawQuery; // if (isInOperation(rawQuery, namedParameter)) { // String replacedValue = createInOperatorStatement(parameterValue); // rawQuery = rawQuery.replaceFirst(namedParameter, replacedValue); // } else { // // handle LIKE queries & quoting together // String encodedValue = SimpleDBAttributeConverter.encode(parameterValue); // StringBuilder namedParamBuilder = new StringBuilder(); // StringBuilder paramValueBuilder = new StringBuilder(); // Pattern likeOperatorPattern = Pattern.compile("(%?)" + namedParameter + "(%?)"); // Matcher m = likeOperatorPattern.matcher(rawQuery); // if (m.find()) { // paramValueBuilder.append(SINGLE_QUOTE); // if (!m.group(1).isEmpty()) { // namedParamBuilder.append("%"); // paramValueBuilder.append("%"); // } // namedParamBuilder.append(namedParameter); // paramValueBuilder.append(encodedValue); // if (!m.group(2).isEmpty()) { // namedParamBuilder.append("%"); // paramValueBuilder.append("%"); // } // paramValueBuilder.append(SINGLE_QUOTE); // rawQuery = rawQuery.replaceFirst(namedParamBuilder.toString(), paramValueBuilder.toString()); // } // } return replaceOneParameterInQuery(rawQuery, namedParameter, parameterValue); }
/** * Builds a new {@link ParameterMetadata} of the given {@link Part} and type. Forwards the underlying * {@link Parameters} as well. * * @param <T> * @param type must not be {@literal null}. * @return */ @SuppressWarnings("unchecked") public <T> ParameterMetadata<? extends T> next(Part part, Class<T> type) { Parameter parameter = parameters.next(); Class<?> typeToUse = ClassUtils.isAssignable(type, parameter.getType()) ? parameter.getType() : type; return (ParameterMetadata<? extends T>) next(part, typeToUse, parameter); }
/** * Builds a new {@link ParameterMetadata} for given {@link Part} and the next {@link Parameter}. * * @param <T> * @return */ @SuppressWarnings("unchecked") public <T> ParameterMetadata<T> next(Part part) { Parameter parameter = parameters.next(); return (ParameterMetadata<T>) next(part, parameter.getType(), parameter); }
/** * Returns {@literal true} if the given parameter can be bound. * * @param parameter * @return */ protected boolean canBindParameter(Parameter parameter) { return parameter.isBindable(); }
/** * Add {@link EntityGraph} to the special types.<br> * {@link EntityGraph} must be considered as a special type by Spring Data JPA.<br> * For this to occur, {@link EntityGraph} must be part of Spring Data JPA arrays storing special * types.<br> * Once a type is marked as special, Spring Data JPA will not try to bind it to an under * construction query. */ private static void addEntityGraphToSpecialTypes() { addEntityGraphToSpecialTypes(Parameters.class, "TYPES"); addEntityGraphToSpecialTypes(Parameter.class, "TYPES"); }