DATAJPA-564 - Expose invocation arguments as well as delegate root object properties via root expressions.
We now use the rootObject of the delegates context as the rootObject for the expression evaluation as well as the arguments of the current method call are available via positional indices as well via the special variable called "args". Added minimalistic Security Context infrastructure that mimics that from Spring Security to ease testing. Referenced appropriate JIRA issues.
This commit is contained in:
committed by
Oliver Gierke
parent
b09588f922
commit
1879fea1f0
@@ -56,6 +56,7 @@ import org.springframework.util.StringUtils;
|
|||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Eberhard Wolff
|
* @author Eberhard Wolff
|
||||||
* @author Gil Markham
|
* @author Gil Markham
|
||||||
|
* @author Thomas Darimont
|
||||||
*/
|
*/
|
||||||
public class JpaRepositoryConfigExtension extends RepositoryConfigurationExtensionSupport {
|
public class JpaRepositoryConfigExtension extends RepositoryConfigurationExtensionSupport {
|
||||||
|
|
||||||
@@ -104,7 +105,8 @@ public class JpaRepositoryConfigExtension extends RepositoryConfigurationExtensi
|
|||||||
|
|
||||||
String expressionEvaluationContextProviderRef = source.getAttribute("expressionEvaluationContextProviderRef");
|
String expressionEvaluationContextProviderRef = source.getAttribute("expressionEvaluationContextProviderRef");
|
||||||
if (StringUtils.hasText(expressionEvaluationContextProviderRef)) {
|
if (StringUtils.hasText(expressionEvaluationContextProviderRef)) {
|
||||||
builder.addPropertyReference("expressionEvaluationContextProvider", expressionEvaluationContextProviderRef);
|
builder.addPropertyReference(DEFAULT_EXPRESSION_EVALUATION_CONTEXT_PROVIDER,
|
||||||
|
expressionEvaluationContextProviderRef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,10 +15,12 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.jpa.repository.query;
|
package org.springframework.data.jpa.repository.query;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.query.JpaParameters.JpaParameter;
|
import org.springframework.data.jpa.repository.query.JpaParameters.JpaParameter;
|
||||||
import org.springframework.data.jpa.repository.support.ExpressionEvaluationContextProvider;
|
import org.springframework.data.jpa.repository.support.ExpressionEvaluationContextProvider;
|
||||||
|
import org.springframework.expression.AccessException;
|
||||||
import org.springframework.expression.BeanResolver;
|
import org.springframework.expression.BeanResolver;
|
||||||
import org.springframework.expression.ConstructorResolver;
|
import org.springframework.expression.ConstructorResolver;
|
||||||
import org.springframework.expression.EvaluationContext;
|
import org.springframework.expression.EvaluationContext;
|
||||||
@@ -29,7 +31,9 @@ import org.springframework.expression.PropertyAccessor;
|
|||||||
import org.springframework.expression.TypeComparator;
|
import org.springframework.expression.TypeComparator;
|
||||||
import org.springframework.expression.TypeConverter;
|
import org.springframework.expression.TypeConverter;
|
||||||
import org.springframework.expression.TypeLocator;
|
import org.springframework.expression.TypeLocator;
|
||||||
|
import org.springframework.expression.TypedValue;
|
||||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||||
|
import org.springframework.expression.spel.support.ReflectivePropertyAccessor;
|
||||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
@@ -143,11 +147,15 @@ class ExpressionAwareParameterBinder extends ParameterBinder {
|
|||||||
evalContext.setVariable(param.getName(), getValues()[param.getIndex()]);
|
evalContext.setVariable(param.getName(), getValues()[param.getIndex()]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
evalContext.setVariable("args", getValues());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link StandardEvaluationContext} that delegates to the given {@link EvaluationContext}. Variables are first
|
* A {@link StandardEvaluationContext} that delegates to the given {@link EvaluationContext}. Variables are first
|
||||||
* looked-up locally and if not the lookup is performed against the delegatee.
|
* looked-up locally and if not the lookup is performed against the delegatee. Property references at the expression
|
||||||
|
* root are resolved against the delegatees rootObject first potentially followed by a second lookup against the
|
||||||
|
* current rootObject.
|
||||||
*
|
*
|
||||||
* @author Thomas Darimont
|
* @author Thomas Darimont
|
||||||
*/
|
*/
|
||||||
@@ -158,12 +166,11 @@ class ExpressionAwareParameterBinder extends ParameterBinder {
|
|||||||
/**
|
/**
|
||||||
* Creates a new {@link DelegatingStandardEvaluationContext}.
|
* Creates a new {@link DelegatingStandardEvaluationContext}.
|
||||||
*
|
*
|
||||||
* @param values must not be {@literal null}
|
* @param objects
|
||||||
* @param delegatee must not be {@literal null}
|
* @param delegatee must not be {@literal null}
|
||||||
*/
|
*/
|
||||||
public DelegatingStandardEvaluationContext(Object[] values, EvaluationContext delegatee) {
|
public DelegatingStandardEvaluationContext(Object[] parameterValues, EvaluationContext delegatee) {
|
||||||
|
super(parameterValues);
|
||||||
super(values);
|
|
||||||
|
|
||||||
Assert.notNull(delegatee, "EvaluationContext delegatee must not be null!");
|
Assert.notNull(delegatee, "EvaluationContext delegatee must not be null!");
|
||||||
|
|
||||||
@@ -191,7 +198,38 @@ class ExpressionAwareParameterBinder extends ParameterBinder {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<PropertyAccessor> getPropertyAccessors() {
|
public List<PropertyAccessor> getPropertyAccessors() {
|
||||||
return delegatee.getPropertyAccessors();
|
|
||||||
|
List<PropertyAccessor> propertyAccessors = new ArrayList<PropertyAccessor>();
|
||||||
|
|
||||||
|
// First we want to lookup properties against the delegatees root object
|
||||||
|
propertyAccessors.add(newDelegatingPropertyAccessor(delegatee.getRootObject()));
|
||||||
|
|
||||||
|
// Second we want to loopup properties against the current root object
|
||||||
|
propertyAccessors.addAll(delegatee.getPropertyAccessors());
|
||||||
|
|
||||||
|
return propertyAccessors;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@link ReflectivePropertyAccessor} that always looks up properties at the expression root against the
|
||||||
|
* delegates root object first.
|
||||||
|
*
|
||||||
|
* @param delegateRoot
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private ReflectivePropertyAccessor newDelegatingPropertyAccessor(final TypedValue delegateRoot) {
|
||||||
|
|
||||||
|
return new ReflectivePropertyAccessor() {
|
||||||
|
@Override
|
||||||
|
public boolean canRead(EvaluationContext context, Object target, String name) throws AccessException {
|
||||||
|
return super.canRead(context, delegateRoot.getValue(), name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TypedValue read(EvaluationContext context, Object target, String name) throws AccessException {
|
||||||
|
return super.read(context, delegateRoot.getValue(), name);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ public class JavaConfigUserRepositoryTests extends UserRepositoryTests {
|
|||||||
factory.setRepositoryInterface(UserRepository.class);
|
factory.setRepositoryInterface(UserRepository.class);
|
||||||
factory.setCustomImplementation(new UserRepositoryImpl());
|
factory.setCustomImplementation(new UserRepositoryImpl());
|
||||||
factory.setNamedQueries(namedQueries());
|
factory.setNamedQueries(namedQueries());
|
||||||
|
factory.setExpressionEvaluationContextProvider(new SampleExpressionEvaluationContextProvider());
|
||||||
factory.afterPropertiesSet();
|
factory.afterPropertiesSet();
|
||||||
|
|
||||||
return factory.getObject();
|
return factory.getObject();
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed 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.springframework.data.jpa.repository;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.SampleSecurity.SampleSecurityContextHolder;
|
||||||
|
import org.springframework.data.jpa.repository.support.ExpressionEvaluationContextProvider;
|
||||||
|
import org.springframework.expression.EvaluationContext;
|
||||||
|
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Thomas Darimont
|
||||||
|
*/
|
||||||
|
public class SampleExpressionEvaluationContextProvider implements ExpressionEvaluationContextProvider {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EvaluationContext getEvaluationContext() {
|
||||||
|
return new StandardEvaluationContext(SampleSecurityContextHolder.getCurrent());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed 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.springframework.data.jpa.repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Minimalistic thread-scoped security context analogous to Spring Security for testing.
|
||||||
|
*
|
||||||
|
* @author Thomas Darimont
|
||||||
|
*/
|
||||||
|
public class SampleSecurity {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Thomas Darimont
|
||||||
|
*/
|
||||||
|
public static class SampleSecurityContextHolder {
|
||||||
|
|
||||||
|
private static ThreadLocal<SampleAuthentication> auth = new ThreadLocal<SampleAuthentication>() {
|
||||||
|
|
||||||
|
protected SampleAuthentication initialValue() {
|
||||||
|
return new SampleAuthentication(new SampleUser(-1, "anonymous"));
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
public static SampleAuthentication getCurrent() {
|
||||||
|
return auth.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void clear() {
|
||||||
|
auth.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Thomas Darimont
|
||||||
|
*/
|
||||||
|
public static class SampleAuthentication {
|
||||||
|
|
||||||
|
private Object principal;
|
||||||
|
|
||||||
|
public SampleAuthentication(Object principal) {
|
||||||
|
this.principal = principal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getPrincipal() {
|
||||||
|
return principal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPrincipal(Object principal) {
|
||||||
|
this.principal = principal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Thomas Darimont
|
||||||
|
*/
|
||||||
|
public static class SampleUser {
|
||||||
|
private Object id;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public SampleUser(Object id, String name) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Object id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SampleUser withName(String name) {
|
||||||
|
|
||||||
|
this.name = name;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SampleUser withId(Object id) {
|
||||||
|
|
||||||
|
this.id = id;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -58,6 +58,7 @@ import org.springframework.data.jpa.domain.sample.Address;
|
|||||||
import org.springframework.data.jpa.domain.sample.Role;
|
import org.springframework.data.jpa.domain.sample.Role;
|
||||||
import org.springframework.data.jpa.domain.sample.SpecialUser;
|
import org.springframework.data.jpa.domain.sample.SpecialUser;
|
||||||
import org.springframework.data.jpa.domain.sample.User;
|
import org.springframework.data.jpa.domain.sample.User;
|
||||||
|
import org.springframework.data.jpa.repository.SampleSecurity.SampleSecurityContextHolder;
|
||||||
import org.springframework.data.jpa.repository.sample.UserRepository;
|
import org.springframework.data.jpa.repository.sample.UserRepository;
|
||||||
import org.springframework.expression.Expression;
|
import org.springframework.expression.Expression;
|
||||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||||
@@ -105,6 +106,8 @@ public class UserRepositoryTests {
|
|||||||
fourthUser = new User("kevin", "raymond", "no@gmail.com");
|
fourthUser = new User("kevin", "raymond", "no@gmail.com");
|
||||||
fourthUser.setAge(31);
|
fourthUser.setAge(31);
|
||||||
adminRole = new Role("admin");
|
adminRole = new Role("admin");
|
||||||
|
|
||||||
|
SampleSecurityContextHolder.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -1592,7 +1595,7 @@ public class UserRepositoryTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see DATAJPA-XXX
|
* @see DATAJPA-564
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void shouldFindUserByFirstnameAndLastnameWithSpelExpressionInStringBasedQuery() {
|
public void shouldFindUserByFirstnameAndLastnameWithSpelExpressionInStringBasedQuery() {
|
||||||
@@ -1605,7 +1608,7 @@ public class UserRepositoryTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see DATAJPA-XXX
|
* @see DATAJPA-564
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void shouldFindUserByLastnameWithSpelExpressionInStringBasedQuery() {
|
public void shouldFindUserByLastnameWithSpelExpressionInStringBasedQuery() {
|
||||||
@@ -1618,7 +1621,7 @@ public class UserRepositoryTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see DATAJPA-XXX
|
* @see DATAJPA-564
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void shouldFindBySpELExpressionWithoutArgumentsWithQuestionmark() {
|
public void shouldFindBySpELExpressionWithoutArgumentsWithQuestionmark() {
|
||||||
@@ -1631,7 +1634,7 @@ public class UserRepositoryTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see DATAJPA-XXX
|
* @see DATAJPA-564
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void shouldFindBySpELExpressionWithoutArgumentsWithColon() {
|
public void shouldFindBySpELExpressionWithoutArgumentsWithColon() {
|
||||||
@@ -1644,7 +1647,7 @@ public class UserRepositoryTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see DATAJPA-XXX
|
* @see DATAJPA-564
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void shouldFindUsersByAgeForSpELExpression() {
|
public void shouldFindUsersByAgeForSpELExpression() {
|
||||||
@@ -1657,7 +1660,7 @@ public class UserRepositoryTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see DATAJPA-XXX
|
* @see DATAJPA-564
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void shouldfindUsersByFirstnameForSpELExpressionWithParameterNameVariableReference() {
|
public void shouldfindUsersByFirstnameForSpELExpressionWithParameterNameVariableReference() {
|
||||||
@@ -1670,7 +1673,7 @@ public class UserRepositoryTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see DATAJPA-XXX
|
* @see DATAJPA-564
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void shouldFindUserByLastnameWithSpelExpressionInDerivedQuery() {
|
public void shouldFindUserByLastnameWithSpelExpressionInDerivedQuery() {
|
||||||
@@ -1684,6 +1687,42 @@ public class UserRepositoryTests {
|
|||||||
assertThat(users.get(0), is(firstUser));
|
assertThat(users.get(0), is(firstUser));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see DATAJPA-564
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void shouldFindCurrentUserWithCustomQueryDependingOnSecurityContext() {
|
||||||
|
|
||||||
|
flushTestUsers();
|
||||||
|
|
||||||
|
SampleSecurityContextHolder.getCurrent().setPrincipal(secondUser);
|
||||||
|
List<User> users = repository.findCurrentUserWithCustomQuery();
|
||||||
|
|
||||||
|
assertThat(users, hasSize(1));
|
||||||
|
assertThat(users.get(0), is(secondUser));
|
||||||
|
|
||||||
|
SampleSecurityContextHolder.getCurrent().setPrincipal(firstUser);
|
||||||
|
users = repository.findCurrentUserWithCustomQuery();
|
||||||
|
|
||||||
|
assertThat(users, hasSize(1));
|
||||||
|
assertThat(users.get(0), is(firstUser));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see DATAJPA-564
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void shouldFindByFirstnameAndCurrentUserWithCustomQuery() {
|
||||||
|
|
||||||
|
flushTestUsers();
|
||||||
|
|
||||||
|
SampleSecurityContextHolder.getCurrent().setPrincipal(secondUser);
|
||||||
|
List<User> users = repository.findByFirstnameAndCurrentUserWithCustomQuery("Joachim");
|
||||||
|
|
||||||
|
assertThat(users, hasSize(1));
|
||||||
|
assertThat(users.get(0), is(secondUser));
|
||||||
|
}
|
||||||
|
|
||||||
private Page<User> executeSpecWithSort(Sort sort) {
|
private Page<User> executeSpecWithSort(Sort sort) {
|
||||||
|
|
||||||
flushTestUsers();
|
flushTestUsers();
|
||||||
|
|||||||
@@ -448,7 +448,7 @@ public interface UserRepository extends JpaRepository<User, Integer>, JpaSpecifi
|
|||||||
* @see DATAJPA-551
|
* @see DATAJPA-551
|
||||||
*/
|
*/
|
||||||
Slice<User> findTop2UsersBy(Pageable page);
|
Slice<User> findTop2UsersBy(Pageable page);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see DATAJPA-506
|
* @see DATAJPA-506
|
||||||
*/
|
*/
|
||||||
@@ -462,43 +462,55 @@ public interface UserRepository extends JpaRepository<User, Integer>, JpaSpecifi
|
|||||||
Optional<User> findOptionalByEmailAddress(String emailAddress);
|
Optional<User> findOptionalByEmailAddress(String emailAddress);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see DATAJPA-XXX
|
* @see DATAJPA-564
|
||||||
*/
|
*/
|
||||||
@Query("select u from User u where u.firstname = ?#{[0]} and u.firstname = ?1 and u.lastname like %?#{[1]}% and u.lastname like %?2%")
|
@Query("select u from User u where u.firstname = ?#{[0]} and u.firstname = ?1 and u.lastname like %?#{[1]}% and u.lastname like %?2%")
|
||||||
List<User> findByFirstnameAndLastnameWithSpelExpression(String firstname, String lastname);
|
List<User> findByFirstnameAndLastnameWithSpelExpression(String firstname, String lastname);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see DATAJPA-XXX
|
* @see DATAJPA-564
|
||||||
*/
|
*/
|
||||||
@Query("select u from User u where u.lastname like %:#{[0]}% and u.lastname like %:lastname%")
|
@Query("select u from User u where u.lastname like %:#{[0]}% and u.lastname like %:lastname%")
|
||||||
List<User> findByLastnameWithSpelExpression(@Param("lastname") String lastname);
|
List<User> findByLastnameWithSpelExpression(@Param("lastname") String lastname);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see DATAJPA-XXX
|
* @see DATAJPA-564
|
||||||
*/
|
*/
|
||||||
List<User> queryByLastname(Expression lastname);
|
List<User> queryByLastname(Expression lastname);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see DATAJPA-XXX
|
* @see DATAJPA-564
|
||||||
*/
|
*/
|
||||||
@Query("select u from User u where u.firstname = ?#{'Oliver'}")
|
@Query("select u from User u where u.firstname = ?#{'Oliver'}")
|
||||||
List<User> findOliverBySpELExpressionWithoutArgumentsWithQuestionmark();
|
List<User> findOliverBySpELExpressionWithoutArgumentsWithQuestionmark();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see DATAJPA-XXX
|
* @see DATAJPA-564
|
||||||
*/
|
*/
|
||||||
@Query("select u from User u where u.firstname = :#{'Oliver'}")
|
@Query("select u from User u where u.firstname = :#{'Oliver'}")
|
||||||
List<User> findOliverBySpELExpressionWithoutArgumentsWithColon();
|
List<User> findOliverBySpELExpressionWithoutArgumentsWithColon();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see DATAJPA-XXX
|
* @see DATAJPA-564
|
||||||
*/
|
*/
|
||||||
@Query("select u from User u where u.age = ?#{[0]}")
|
@Query("select u from User u where u.age = ?#{[0]}")
|
||||||
List<User> findUsersByAgeForSpELExpressionByIndexedParameter(int age);
|
List<User> findUsersByAgeForSpELExpressionByIndexedParameter(int age);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see DATAJPA-XXX
|
* @see DATAJPA-564
|
||||||
*/
|
*/
|
||||||
@Query("select u from User u where u.firstname = :firstname and u.firstname = :#{#firstname}")
|
@Query("select u from User u where u.firstname = :firstname and u.firstname = :#{#firstname}")
|
||||||
List<User> findUsersByFirstnameForSpELExpression(@Param("firstname") String firstname);
|
List<User> findUsersByFirstnameForSpELExpression(@Param("firstname") String firstname);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see DATAJPA-564
|
||||||
|
*/
|
||||||
|
@Query("select u from User u where u.emailAddress = ?#{principal.emailAddress}")
|
||||||
|
List<User> findCurrentUserWithCustomQuery();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see DATAJPA-564
|
||||||
|
*/
|
||||||
|
@Query("select u from User u where u.firstname = ?1 and u.firstname=?#{[0]} and u.emailAddress = ?#{principal.emailAddress}")
|
||||||
|
List<User> findByFirstnameAndCurrentUserWithCustomQuery(String firstname);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,8 @@
|
|||||||
</constructor-arg>
|
</constructor-arg>
|
||||||
</bean>
|
</bean>
|
||||||
</property>
|
</property>
|
||||||
|
|
||||||
|
<property name="expressionEvaluationContextProvider" ref="expressionEvaluationContextProvider"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="roleDao" class="org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean">
|
<bean id="roleDao" class="org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean">
|
||||||
|
|||||||
@@ -24,6 +24,8 @@
|
|||||||
<property name="entityManagerFactory" ref="entityManagerFactory" />
|
<property name="entityManagerFactory" ref="entityManagerFactory" />
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<bean name="expressionEvaluationContextProvider" class="org.springframework.data.jpa.repository.SampleExpressionEvaluationContextProvider"/>
|
||||||
|
|
||||||
<jdbc:embedded-database id="dataSource" type="HSQL">
|
<jdbc:embedded-database id="dataSource" type="HSQL">
|
||||||
<jdbc:script execution="INIT" separator="/;" location="classpath:scripts/schema-stored-procedures.sql"/>
|
<jdbc:script execution="INIT" separator="/;" location="classpath:scripts/schema-stored-procedures.sql"/>
|
||||||
</jdbc:embedded-database>
|
</jdbc:embedded-database>
|
||||||
|
|||||||
Reference in New Issue
Block a user