SpEL support in Spring Data JPA @Query definitions
2017-07-12 09:37
537 查看
https://spring.io/blog/2014/07/15/spel-support-in-spring-data-jpa-query-definitions
Spring Data JPA allows manually defining the query to be executed by a repository method using the
Unfortunately parameter binding in JPQL is quite limited only allowing you to set a value and providing some type conversion. The latest Spring
Data JPA M1release of the Evans release train eases this pain by adding support
for using SpEL expressions to use dynamically bound parameters within statements in
which provides additional flexibility when defining queries manually. In this blog post, I am going to introduce you to the capabilities of this feature.
Method
SpEL support provides access to the query method arguments. This allows you to either simply bind the parameter as is or perform additional operations before binding.
Parameters are exposed for indexed access (
the first method) or via the name declared using
The actual SpEL expression binding is either triggered by
We support both types to allow you to be consistent to standard JPQL parameter bindings that also might occur in the query definition.
Parameters of special types like
`
simple class names as variables.
Advanced
While advanced parameter binding is a very useful feature, the real power of SpEL stems from the fact, that the expressions can refer to framework abstractions or other application components. A very common scenario for SpEL is the definition of
security constraints. So it would be cool if we could restrict a query to only return results related to the currently authenticated user:
As you can see we refer to a property of Spring Security’s
So how does the Spring Data SpEL support integrate with Spring Security.
SpEL
Spring Data exposes an extension point
The interface allows implementors to customize the
a very detailed way but for convenience, we provide a
class to conveniently let you only implement the parts you’re interested in:
For our Spring Security extension we extend
override the
method and return a new
which exposes all the security properties and expressions you already know from usage in
This step also makes them available in SpEL expressions in our
The final step we need to take is to register the security extension as a bean:
Spring Data JPA will pick up all beans of type
use those to prepare the
be used to evaluate the SpEL expression defined in
The extension in place will now let you leverage the full power of the Spring Security SpEL functions. Imagine a repository query method that shall return the
which the current user is owner of or all
if the current user is admin. The query method definition would look like this:
You can find the working examples of the snippets seen here in the Spring-Data-Examplesrepository.
Spring Data JPA allows manually defining the query to be executed by a repository method using the
@Queryannotation.
Unfortunately parameter binding in JPQL is quite limited only allowing you to set a value and providing some type conversion. The latest Spring
Data JPA M1release of the Evans release train eases this pain by adding support
for using SpEL expressions to use dynamically bound parameters within statements in
@Queryannotations
which provides additional flexibility when defining queries manually. In this blog post, I am going to introduce you to the capabilities of this feature.
Method
parameter expressions
SpEL support provides access to the query method arguments. This allows you to either simply bind the parameter as is or perform additional operations before binding.@Query("select u from User u where u.age = ?#{[0]}") List<User> findUsersByAge(int age); @Query("select u from User u where u.firstname = :#{#customer.firstname}") List<User> findUsersByCustomersFirstname(@Param("customer") Customer customer);
Parameters are exposed for indexed access (
[0]in
the first method) or via the name declared using
@Param.
The actual SpEL expression binding is either triggered by
?#or
:#.
We support both types to allow you to be consistent to standard JPQL parameter bindings that also might occur in the query definition.
Parameters of special types like
Sortand
`
Pageableare exposed with their
simple class names as variables.
Advanced
SpEL expressions
While advanced parameter binding is a very useful feature, the real power of SpEL stems from the fact, that the expressions can refer to framework abstractions or other application components. A very common scenario for SpEL is the definition ofsecurity constraints. So it would be cool if we could restrict a query to only return results related to the currently authenticated user:
@Query("select u from User u where u.emailAddress = ?#{principal.emailAddress}") List<User> findCurrentUserWithCustomQuery();
As you can see we refer to a property of Spring Security’s
principal.
So how does the Spring Data SpEL support integrate with Spring Security.
SpEL
EvaluationContext extension model
Spring Data exposes an extension point EvaluationContextExtension.
The interface allows implementors to customize the
EvaluationContextin
a very detailed way but for convenience, we provide a
EvaluationContextExtensionSupportbase
class to conveniently let you only implement the parts you’re interested in:
class SecurityEvaluationContextExtension extends EvaluationContextExtensionSupport { @Override public String getExtensionId() { return "security"; } @Override public SecurityExpressionRoot getRootObject() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); return new SecurityExpressionRoot(authentication) {}; } }
For our Spring Security extension we extend
EvaluationContextExtensionSupportand
override the
getRootObject()
method and return a new
SecurityExpressionRootinstance
which exposes all the security properties and expressions you already know from usage in
@PreAuthorize.
This step also makes them available in SpEL expressions in our
@Queryannotation.
The final step we need to take is to register the security extension as a bean:
@Configuration @EnableJpaRepositories class SecurityConfiguration { @Bean EvaluationContextExtension securityExtension() { return new SecurityEvaluationContextExtension(); } }
Spring Data JPA will pick up all beans of type
EvaluationContextExtensionand
use those to prepare the
EvaluationContextto
be used to evaluate the SpEL expression defined in
@Query.
The extension in place will now let you leverage the full power of the Spring Security SpEL functions. Imagine a repository query method that shall return the
BusinessObjects
which the current user is owner of or all
BusinessObjects
if the current user is admin. The query method definition would look like this:
interface SecureBusinessObjectRepository extends Repository<BusinessObject,Long>{ @Query("select o from BusinessObject o where o.owner.emailAddress like "+ "?#{hasRole('ROLE_ADMIN') ? '%' : principal.emailAddress}") List<BusinessObject> findBusinessObjectsForCurrentUser(); }
You can find the working examples of the snippets seen here in the Spring-Data-Examplesrepository.
相关文章推荐
- spring.data.jpa.query :Cannot use native queries with dynamic sorting and/or pagination in method
- Spring Data jpa @query 关于IN关键字查询
- @Query Annotation in Spring Data JPA--转
- IntelliJ IDEA can't resolve entity in spring data jpa @query annotation 报红
- spring DATA (jpa) @query 和JdbcTemplate
- SPRING IN ACTION 第4版笔记-第十一章Persisting data with object-relational mapping-004JPA例子的代码
- Spring Data JPA Using @Query
- SpringData JPA @query注解使用原生代码报错问题
- 深入浅出学Spring Data JPA toPredicate Predicate[] p = new Predicate[list.size()]; query.where(cb.and 201
- spring data jpa 利用@Query进行查询
- jpa学习5--spring data jpa 中的JpaRepository 使用 @Query 注解
- Spring Boot Data JPA support Emoji
- springboot+maven+springdata jpa +querydsl快速实现增删改查分页
- spring-data-jpa 的@Query注解的使用
- Spring Data JPA @Query
- spring jpa @Query中使用in
- Spring data jpa的OpenEntityManagerInViewFilter
- Spring Data JPA Specification Query
- 使用SpringData JPAQL获取查询结果query.getResultList()读取后EntityManager会自动关闭
- Spring Data JPA 常用注解 @Query、@NamedQuery