SpEL support in Spring Data JPA @Query definitions

来源:互联网 发布:qq旋风mac 迅雷下载 编辑:程序博客网 时间:2024/05/23 15:41

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 @Query annotation. 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 Sort and `Pageable are 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 of security 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 EvaluationContext in a very detailed way but for convenience, we provide a EvaluationContextExtensionSupport base 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 EvaluationContextExtensionSupport and override the getRootObject()
method and return a new SecurityExpressionRoot instance 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 @Query annotation.

The final step we need to take is to register the security extension as a bean:

@Configuration@EnableJpaRepositoriesclass SecurityConfiguration {    @Bean    EvaluationContextExtension securityExtension() {        return new SecurityEvaluationContextExtension();    }}

Spring Data JPA will pick up all beans of type EvaluationContextExtension and use those to prepare the EvaluationContext to 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.


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 7岁儿童不吃饭怎么办 天热宝宝不好好吃饭怎么办 天热宝宝不爱吃饭怎么办 天热宝宝不想吃饭怎么办 夏天天热宝宝不爱吃饭怎么办 3岁宝宝吃饭不香怎么办 胃ca吃饭反胃没食欲怎么办 12岁儿童脸色发黄怎么办 胃饿 但是没食欲不想吃饭怎么办 牙缝大经常塞西怎么办 吃肉老是塞牙缝怎么办 宝宝光喝奶粉不吃饭怎么办 九个月宝宝缺维c怎么办 九个月宝宝缺维d怎么办 9个月大宝宝缺锌怎么办 三周岁宝宝不爱吃饭怎么办 一周岁宝宝不爱吃饭怎么办 两岁半宝宝不自己吃饭怎么办 3岁宝宝不会吃饭怎么办 节食减肥胃疼怎么办呢 减肥不吃饭胃疼怎么办 过度节食伤了胃怎么办 3岁宝宝啥也不吃怎么办 1岁多宝宝不吃饭怎么办 胃口吃辣的难受怎么办 空腹吃辣椒胃疼怎么办 吃东西辣的胃口疼怎么办 吃辣的东西胃烧怎么办 吃母乳的宝宝不爱喝水怎么办 三个月宝宝不肯吃奶粉怎么办 三个月宝宝不肯喝奶粉怎么办 三个月的宝宝不肯喝奶粉怎么办 三个月的宝宝不肯吃奶粉怎么办 饿了还是没食欲怎么办 3岁半幼儿便秘怎么办 小孩字写得难看怎么办 小孩的字写的丑怎么办 小孩字写的太差怎么办 小孩很多字不会写怎么办 食欲不好吃不多怎么办 中班小孩子子不肯写字怎么办