课程表

Spring Boot课程

工具箱
速查手册

Boot JPA自定义查询操作

当前位置:免费教程 » Java相关 » Spring Boot
注意:本页面内容为W3xue原创,未经授权禁止转载,违者必究!
来源:W3xue  发布时间:2019/8/30 17:10:37

上一节中,我们介绍了基本的数据库操作,本章节,我们将介绍更加复杂的查询和更新删除等操作。本章节分为2部分,第一部分使用使用JPA自带的查询、更新、删除等功能,可以使用特定的语法实现自定义查询,第二部分我们介绍如何使用完全自定义的SQL语句。

一、JPA的自定义操作

JPA提供了一套以接口命名方法作为其查询方式的规范,只要在我们继承了Repository接口的接口中使用JPA规范的方法命名,JPA就可以反解出对应的sql语句。

规范如下:

关键词例 子
IsNotNullfindByAgeNotNull
LikefindByNameLike
NotLikefindByNameNotLike
StartingWithfindByNameStartingWith
EndingWithfindByNameEndingWith
ContainingfindByNameContaining
OrderByfindByAgeOrderByName
NotfindByNameNot
InfindByAgeIn
NotInfindByAgeNotIn
TruefindByActiveTrue
FlasefindByActiveFalse
AndfindByNameAndAge
OrfindByNameOrAge
BetweenfindByAgeBetween
LessThanfindByAgeLessThan
GreaterThanfindByAgeGreaterThan
IsNullfindByAgeIsNull

 那么,问题就好办了。我们只要按照这个格式,结合实体类的成员变量的名字,申明相应的方法名,就可以直接使用,而无需去写SQL语句。

但是这里有个问题需要注意,JPA只支持名称首字母小写的成员变量,如果名称变量是大写的,比如我把MainBean实体类里面的name成员变量改为"Name",则会出现类似如下的错误:

  1. org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'mainRestController': Unsatisfied dependency expressed through field 'mainServiceImpl'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'mainServiceImpl': Unsatisfied dependency expressed through field 'mainDao'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mainDao': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Failed to create query for method public abstract java.util.List com.w3xue.jiaocheng.MainDao.findByNameLike(java.lang.String)! Unable to locate Attribute  with the the given name [name] on this ManagedType [com.w3xue.jiaocheng.MainBean]
  2. ......

一切准备就绪后,我们首先在MainDao类里申明2个根据命名规范来的函数:

  1. List<MainBean> findByNameLike(String Name);
  2. List<MainBean> findByAgeBetween(Integer a,Integer b);

这2个方法,一个是通过名称查找对象,一个是通过年龄的区间来查找对象,其引用也非常直接,你可以在MainRestController类里直接申明下面这个方法来引用它们:

  1. @RequestMapping(value="/jpagetdiy/{name}",method= RequestMethod.GET)
  2. public String jpaGetDiy(@PathVariable(value = "name",required = true) String pName) {
  3.     try
  4.     {
  5.         String selectName = "%" + pName + "%";
  6.         List<MainBean> mbStudents = mainDao.findByNameLike(selectName);
  7.         StringBuilder sbInfo=new StringBuilder();
  8.         for (MainBean mbSingle:mbStudents) {
  9.             sbInfo.append("名称查找结果:【ID:"+mbSingle.getId()+"】");
  10.             sbInfo.append(" 【姓名:"+mbSingle.getName()+"】");
  11.             sbInfo.append(" 【年级和班级:"+mbSingle.getGrade()+" "+mbSingle.getStudentClass()+"】");
  12.         }
  13.  
  14.         List<MainBean> mbStudents2 = mainDao.findByAgeBetween(10,15); //查找10岁至15岁之间的学生,李四符合条件
  15.         for (MainBean mbSingle:mbStudents2) {
  16.             sbInfo.append("<br />年龄区间查找结果:【ID:"+mbSingle.getId()+"】");
  17.             sbInfo.append(" 【姓名:"+mbSingle.getName()+"】");
  18.             sbInfo.append(" 【年级和班级:"+mbSingle.getGrade()+" "+mbSingle.getStudentClass()+"】");
  19.         }
  20.  
  21.         return sbInfo.toString();
  22.     }
  23.     catch (Exception e)
  24.     {
  25.         return "未查询到数据";
  26.     }
  27. }

这里引用了2个方法,一个是根据名字模糊查找学生信息,另外一个是查找年龄在10岁至15岁之间的学生信息。如果一切顺利,就会返回如下信息:

  1. 名称查找结果:【ID:1 【姓名:张三】 【年级和班级:二年级 三班】
  2. 年龄区间查找结果:【ID:2 【姓名:李四】 【年级和班级:五年级 六班】

其他的命名格式你可以自行尝试,根据名称和你的实体类成员变量名字来定义方法名就行了。


二、完全自定义SQL语句的JPA操作

让我们来看看完全自定义SQL语句的JPA操作。

首先,我们先访问如下地址:

  1. http://localhost:8080/jiaocheng/adminlogin?pwd=mypassword

访问这个页面后,就获得一个键为“user”的session,然后访问添加数据的这个接口地址:

  1. http://localhost:8080/jiaocheng/jpatest?name=李四&age=11&grade=四年级&studentclass=一班&parent_name=王老五&parent_mobilephone=12388998899

如果没有意外,就会返回“添加学生李四成功”的信息。否则,如果session为空,或有其他错误,则提示添加失败。

但是,此时我们发现之前已经添加过李四的信息了,这次是姓名弄错了,需要修改姓名,怎么办呢?我们使用完全自定义的JPA操作。首先我们在MainDao类中添加如下注释和方法体:

  1. //修改名字
  2. @Modifying
  3. @Transactional
  4. @Query(value="update t_w3xue_student set f_name=:name where f_id=:id",nativeQuery = true)
  5. public void upStudentById(@Param("name") String sName,@Param("id") Integer nId);

@Modifying注释表明这是一个有修改功能的自定义方法体,@Transactional表明这是一个事务,因为涉及到修改数据库,这2个注解少一不可。第三个注解@Query里面包含自定义的SQL语句,但是这个“SQL”语句跟传统的SQL语句还是有不同的地方,你可以发现多了“:name”、“:id”这样的语句,前面带冒号表明,这2个参数是从底下的方法体引用的,实际上,它一般被称为HQL。“nativeQuery = true”表明,里面对应的是原始的表名,如果设置nativeQuery = false”则对应的实体名。比如,我们设置这个方法体如下,效果是一模一样的

  1. //修改名字
  2. @Modifying
  3. @Transactional
  4. @Query(value="update MainBean set f_name=:name where f_id=:id",nativeQuery = false)
  5. public void upStudentById(@Param("name") String sName,@Param("id") Integer nId);

方法申明中,@Param注解里的值,必须和上面一行HQL里面的冒号后面的变量名一致,但是在接受外来参数的时候,可以不必设置为和HQL里面的冒号后面的变量名一样,例如,本例中我们就把接受的2个参数分别申明为sName和nId。

我们在MainRestController类中添加如下方法:

  1. @RequestMapping(value="/jpadiymodicomplete",method= RequestMethod.GET)
  2. public String jpaDiyModiComplete(@RequestParam(value = "id",defaultValue = "") Integer pId,@RequestParam(value = "name",defaultValue = "") String pName, HttpSession session)
  3. {
  4.     try
  5.     {
  6.         if (session.getAttribute("admin").toString().length()>0) {
  7.             mainDao.upStudentById(pName,pId); //将ID为“参数id”的数据,姓名修改为“参数name”的值
  8.             return "操作成功";
  9.         }
  10.         else
  11.         {
  12.             return "操作失败,没有权限";
  13.         }
  14.     }
  15.     catch (Exception e)
  16.     {
  17.         return "操作失败,无权限";
  18.     }
  19. }

首先,我们先访问如下地址:

  1. http://localhost:8080/jiaocheng/adminlogin?pwd=mypassword

访问这个页面后,就获得一个键为“user”的session,然后访问添加数据的这个接口地址:

  1. http://localhost:8080/jiaocheng/jpadiymodicomplete?name=%E7%8E%8B%E9%BA%BB%E5%AD%90&id=3

如果之前登陆了,就会返回操作成功的提示。这时我们再查看数据库,就会发现,我们刚刚添加的ID为3的学生记录,名字已经被修改为“王麻子”了。

我们不但可以使用这个完全自定义的方法update数据,而且也可以用来delete、insert操作,因为方法一模一样,此处不再赘述。

但自定义查询的办法有所不同,这里简要介绍一下。首先我们在MainDao类中添加如下注释和方法体:

  1. @Query(value = "SELECT * FROM t_w3xue_student where f_name like %:name%", nativeQuery = true)
  2. public List<MainBean> getStudentByName(@Param("name") String sName);

然后,在MainRestController类中添加如下方法:

  1. @RequestMapping(value="/jpadiygetcomplete",method= RequestMethod.GET)
  2. public String jpaDiyGetComplete(@RequestParam(value = "name",defaultValue = "") String pName, HttpSession session)
  3. {
  4.     try {
  5.         StringBuilder sbInfo = new StringBuilder();
  6.         List<MainBean> mbStudents = mainDao.getStudentByName(pName);
  7.         sbInfo.append("完全模糊查找结果:");
  8.         for (MainBean mbSingle : mbStudents) {
  9.             sbInfo.append("<br />【ID:" + mbSingle.getId() + "】");
  10.             sbInfo.append(" 【姓名:" + mbSingle.getName() + "】");
  11.             sbInfo.append(" 【年级和班级:" + mbSingle.getGrade() + " " + mbSingle.getStudentClass() + "】");
  12.         }
  13.         return sbInfo.toString();
  14.     }
  15.     catch (Exception e)
  16.     {
  17.         return "查询失败";
  18.     }
  19. }

然后,我们访问如下地址:

  1. http://localhost:8080/jiaocheng/jpadiygetcomplete?name=%E7%8E%8B

模糊查询一个“王”字,我们就会GET到如下的结果:

  1. 完全模糊查找结果:
  2. ID:3 【姓名:王麻子】 【年级和班级:四年级 一班】

现在,完全自定义的操作,包括update、insert、delete、select都已经实现了。

注意:本页面内容为W3xue原创,未经授权禁止转载,违者必究!
来源:W3xue  发布时间:2019/8/30 17:10:37
 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号