@Query Annotation in Spring Data JPA--转
原文地址:http://javabeat.net/spring-data-jpa-query/
In my previous post on Spring Data, I have explained the basic concepts and configurations for Spring Data JPA. In this tutorial, I am going to explain @Queryannotation and how to create custom query using the @Query annotation.
The greatest advantage of using Spring Data is that it implements the repositories at run time for creating the queries. Developer need not worry about the SQL knowledge and writing error prone SQL queries. Query methods implemented in spring data repositories will be used for creating the dynamic queries.
But, if you want to write very complex queries with multiple conditions to filter the data, then the query method name would become awful. To avoid this situation, one can comfortably use the JPQL / SQL queries inside the @Query annotation. This annotation supports both, JPA Query Language (JPQL) and SQL. I am going to explain how to write query using query annotation in Spring Data JPA.
- @Query Annotation
- Like Expressions
- How to use Native SQL Query
- Named Parameters using @Param
- SpEL Expressions
- Example Application
- Source Code
- Conclusion
@Query Annotation
- When you can not use the query methods to perform database operations,
@Querycould be used to write the more flexible query to fetch data. @Queryannotation supports both JPQL and native SQL queries.- By default,
@Queryannotation will be using JPQL to execute the queries. If you try to use the normal SQL queries, you would get the query syntax error exceptions. - If you want to write native SQL queries, set the
nativeQueryflag totrue. Also pagination and dynamic sorting for native queries are not supported in spring data jpa. - If you are using the query methods with
@Queryannotation, this will take the precedence over@NamedQuery, named queries in orm.xml and method names. - For example, if we create a query method called findByName() and annotate it with the
@Queryannotation, Spring Data JPA will not find the entity with name property is equal then the given method parameter. It would invoke the query that is configured by using the@Queryannotation.
A simple example snippet for using the query annotation.
@Query(value = "select name,author,price from Book b where b.price>?1 and b.price<?2")
List<Book> findByPriceRange(long price1, long price2);
It is a simple example for query annotation. In the above snippet, we are having to parameters to compare the prices and filter the results. The parameter in the query is preceded by ? character to indicate that this is the parameter to be bind with method arguments.
Like Expressions
One can use the advanced like mechanism inside the @Query definition. The example for using the like expressions inside query as below:
@Query(value = "select name,author,price from Book b where b.name like %:name%")
List<Book> findByNameMatch(@Param("name") String name);
In the above query, we are using the like expression to filter the results.
How to use Native SQL Query
As I have pointed out in the previous section, query annotation supports the definition of native SQL query by enabling the nativeQuery flag in the query annotation. This feature is very handy when you want to try just the normal database query syntax instead of JPQL syntax.
Here is the example code for how to use the native SQL query in @Query annotation:
@Query(value = "select * from #{#entityName} b where b.name=?1", nativeQuery = true)
List<Book> findByName(String name);
In the above example code snippet, we are using the nativeQuery=true for telling spring data jpa to use the native query execution. By default the value for this flag is false.
Named Parameters using @Param
- By default, Spring Data query parameters are substituted based on its position. This is error prone when you are refactoring the code and updating the parameter positions.
@Paramannotation can be used in the method parameter to bind the query parameter names.- Inside query, you have to use
:paramNameto indicate that the same paramName has to be bind with the method parameter.
Here is the example code:
@Query(value = "select name,author,price from Book b where b.name = :name AND b.author=:author AND b.price=:price")
List<Book> findByNamedParam(@Param("name") String name, @Param("author") String author,
@Param("price") long price);
In the above query, we are using the named parameters to bind the query parameter and method arguments. This is the most recommended way for binding the parameters. When we have multiple parameters, this option is good instead of position based binding.
SpEL Expressions
Support for SpEL expression in the query is limited and it is introduced from the release Spring Data JPA 1.4. When query execution happens, the query is evaluated with the pre-determined value using the SpEL expressions.
Here is the example code for SpEL expressions.
@Query(value = "select * from #{#entityName} b where b.name=?1", nativeQuery = true)
List<Book> findByName(String name);
#{#entityName} is the SpEL expression used to get the entity name. At this time SpEL expressions are used only for the entity name, in the future version there could be more expressions.
@Query Annotation Example Application
Note that here I am not listing the entire code used for this tutorial. If you want to browser the whole project, please download the source code in the download section.
The only extra class I have added for this example is a new repository interface to define the query methods with @Query annotation.
BookQueryRepositoryExample.java
Here is the new repository class for demonstrating the @Query annotation.
public interface BookQueryRepositoryExample extends Repository<Book, Long> {
@Query(value = "select * from Book b where b.name=?1", nativeQuery = true)
List<Book> findByName(String name);
@Query(value = "select name,author,price from Book b where b.price>?1 and b.price<?2")
List<Book> findByPriceRange(long price1, long price2);
@Query(value = "select name,author,price from Book b where b.name like %:name%")
List<Book> findByNameMatch(@Param("name") String name);
@Query(value = "select name,author,price from Book b where b.name = :name AND b.author=:author AND b.price=:price")
List<Book> findByNamedParam(@Param("name") String name, @Param("author") String author,
@Param("price") long price);
}
Apart from the above class, I have modified the controller class, service implementation access this repository from the REST API.
Also I have newly added data.sql and schema.sql to initialize the data at the time of spring boot application startup.
data.sql
INSERT INTO book(id,name,author,price) VALUES (1,'Spring In Action:Covers Spring 3.0','Craig Walls', 400);
INSERT INTO book(id,name,author,price) VALUES (2,'Spring Batch In Action','Arnaud Cogoluegnes', 500);
INSERT INTO book(id,name,author,price) VALUES (3,'Spring Book','Rod', 300);
INSERT INTO book(id,name,author,price) VALUES (4,'Java Book','test', 100);
INSERT INTO book(id,name,author,price) VALUES (5,'Spring Boot Application','test', 200);
INSERT INTO book(id,name,author,price) VALUES (6,'Learn Spring Data JPA','test', 300);
INSERT INTO book(id,name,author,price) VALUES (7,'Hibernat in Action','Gavin King', 300);
INSERT INTO book(id,name,author,price) VALUES (8,'JSF in Action','Kit', 400);
INSERT INTO book(id,name,author,price) VALUES (9,'Java Interview Questions','Subramanian', 450);
INSERT INTO book(id,name,author,price) VALUES (10,'Java Complete Reference','Herbert', 450);
schema.sql
create table book(
id int not null primary key,
name varchar_ignorecase(50) not null,
author varchar_ignorecase(50) not null,
price int);
Download Source Code
Here is the complete source code used for this tutorial available for the download. This source code is not only for the query annotation example, but it contains the all other Spring Data JPA examples.
Conclusion
I hope this tutorial have provided more insight on how to use the query annotation. If you are working on Spring Data, understanding the features of query annotation is important since most of the times using query methods won’t be sufficient. In this tutorial I have explained about how to use @Query annotation in the query methods, using like expressions, using named parameters for the binding and SpEL expression inside query. If you are interested in reading the basics of Spring Data JPA, please read our more detailed tutorial about Spring Data JPA.
Exceptions
QuerySyntaxException : unexpected token / Validation failed for query for method
When you are trying to execute the native SQL queries, you may encounter the below exception. If you are happen to see the below exception, there is most likely chance is that you are using native SQL query without the attribute nativeQuery=true. If you are using the SQL query without the attribute nativeQuery=true, Spring Data JPA will try to validate the query against the JPQL format. You will get the below exception.
Note that, this same exception would be thrown even if there is a syntax error in the query.
Caused by: java.lang.IllegalArgumentException: Validation failed for query for method public abstract java.util.List net.javabeat.spring.data.service.BookQueryRepositoryExample.findByName(java.lang.String)!
at org.springframework.data.jpa.repository.query.SimpleJpaQuery.validateQuery(SimpleJpaQuery.java:92)
at org.springframework.data.jpa.repository.query.SimpleJpaQuery.<init>(SimpleJpaQuery.java:62)
Caused by: java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: * near line 1, column 8 [select * from net.javabeat.spring.data.domain.Book b where b.name=?1]
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1750)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1677)
To avoid the above exception, add the nativeQuery attribute as below:
@Query(value = "select * from #{#entityName} b where b.name=?1", nativeQuery = true)
List<Book> findByName(String name);
If this tutorial is useful, we are happy. If you could find the information what you are looking for, please request us to update the tutorial in the comments section.
@Query Annotation in Spring Data JPA--转的更多相关文章
- spring data jpa 利用@Query进行查询
参照https://blog.csdn.net/yingxiake/article/details/51016234#reply https://blog.csdn.net/choushi300/ar ...
- Spring data jpa中Query和@Query分别返回map结果集
引用: http://blog.csdn.net/yingxiake/article/details/51016234 http://blog.csdn.net/yingxiake/article/d ...
- Spring Data JPA教程, 第八部分:Adding Functionality to a Repository (未翻译)
The previous part of my tutorial described how you can paginate query results with Spring Data JPA. ...
- Spring Data JPA教程, 第七部分: Pagination(未翻译)
The previous part of my Spring Data JPA tutorialdescribed how you can sort query results with Spring ...
- Spring Data JPA教程, 第六部分: Sorting(未翻译)
The fifth part of my Spring Data JPA tutorialdescribed how you can create advanced queries with Spri ...
- Spring Data JPA实体详解
1. Spring Data JPA实体概述 JPA提供了一种简单高效的方式来管理Java对象(POJO)到关系数据库的映射,此类Java对象称为JPA实体或简称实体.实体通常与底层数据库中的单个关系 ...
- Spring Data JPA教程, 第三部分: Custom Queries with Query Methods(翻译)
在本人的Spring Data JPA教程的第二部分描述了如何用Spring Data JPA创建一个简单的CRUD应用,本博文将描述如何在Spring Data JPA中使用query方法创建自定义 ...
- 在Spring Data JPA 中使用Update Query更新实体类
对于 Spring Data JPA 使用的时间不长,只有两年时间.但是踩过坑的却不少. 使用下列代码 @Modifying @Query("update User u set u.firs ...
- spring data jpa @query的用法
@Query注解的用法(Spring Data JPA) 参考文章:http://www.tuicool.com/articles/jQJBNv . 一个使用@Query注解的简单例子 @Query( ...
随机推荐
- ROS-单目摄像头标定
前言:由于摄像图内部与外部的原因,生成的图像往往会发生畸变,为了避免数据源造成的误差,需要针对摄像头的参数进行标定. ros官方提供了camera_calibration软件包进行摄像头标定. 一.安 ...
- vue路由钩子拦截器beforeEach和afterEach及页面路由变化路由监听
在路由跳转的时候,我们需要一些权限判断或者其他操作.这个时候就需要使用路由的钩子函数. 定义:路由钩子主要是给使用者在路由发生变化时进行一些特殊的处理而定义的函数. 总体来讲vue里面提供了三大类钩子 ...
- LA 3635 Pie
题意:给出n个圆,分给n+1个人,求每个人最多能够得到多大面积的圆 二分每个人得到的圆的面积 #include<iostream> #include<cstdio> #incl ...
- thinkphp5 模板中截取中文字符串
TP5模板页截取中文字符串 {$vo.task_detail|mb_substr=###,0,15,'utf-8'}
- RabbitMQ学习笔记(2)----RabbitMQ简单队列(Hello World)的使用
1. 简单队列结构图 2. 引入依赖 pom.xml文件 <dependency> <groupId>com.rabbitmq</groupId> <arti ...
- MobilNnet
一.参数数量和理论计算量 1.定义 参数数量(params):关系到模型大小,单位通常为M,通常参数用 float32 表示,也就是每个参数占4个字节,所以模型大小是参数数量的 4 倍 理论计算量(F ...
- HDU 5918 Sequence I
题目来源:2016 CCPC 长春站 题意:给出两个序列 a[] , b[] ,如果b1,b2....bm能够与aq,aq+p,aq+2p...aq+(m-1)p对应( q+(m-1)p<=n ...
- BZOJ 4012 [HNOI2015]开店 (树分治+二分)
题目大意: 给你一棵树,边有边权,点有点权,有很多次询问,求点权$\in[l,r]$的所有节点到某点$x$的距离之和,强制在线 感觉这个题应该放在动态点分之前做= = 套路方法和动态点分是一样的 每次 ...
- [USACO18JAN] MooTube (离线并查集)
题目大意:给你一棵边权树,定义两点间距离为它们唯一路径上的最小路权,求与某点距离不大于K(k为已知)的点的数量 带权并查集维护集合内元素总数 路和问题 都按权值大到小排序,枚举问题, 建权值不小于K的 ...
- CF833B The Bakery (线段树+DP)
题目大意:给你一个序列(n<=35000),最多分不大于m块(m<=50),求每个块内不同元素的数量之和的最大值 考试的时候第一眼建图,没建出来,第二眼贪心 ,被自己hack掉了,又随手写 ...