写点什么

JPQL 超详细介绍与 JPA 命名规则

作者:陈老老老板
  • 2022-11-25
    北京
  • 本文字数:4850 字

    阅读完需:约 16 分钟

JPQL超详细介绍与JPA命名规则

陈老老老板

说明:学习一些新的技术栈,边学习边总结,需要注意的地方都标红了, 一起加油。



1.JPA 最牛之拼接方法名自定义 SQL 语句

(1)拼接实例

说明(规则表在最下面):Hibernate 作为一个全自动的 ORM 框架,就说明不用你写 SQL 语句。但是说实话,大多是适用于简单的增删改查分页和排序,对于更加复杂的场景也是需要进行写 SQL 的这个之后介绍。 其实实现也非常简单,就是在 repository 接口中按命名规则进行拼接方法名来实现。(这里用的是 JPA 介绍中的接口代码)


<b><code class="language-java">package com.example.demo.repository;
import com.example.demo.pojo.Admin;import org.springframework.data.jpa.repository.JpaRepository;import org.springframework.data.repository.PagingAndSortingRepository;import org.springframework.stereotype.Repository;
//声明为repository@Repositorypublic interface AdminRepository extends PagingAndSortingRepository<Admin,Long> { //解释:select ... where emailaddress = ?1 and lastname = ?2; //这里的? 代表占位符,1,2, 代表方法中的第几个参数。 List<Admin> findByEmailAddressAndLastname(String emailAddress, String lastname); //模糊查询 List<Admin> findAllByUsernameLike(String username);}</code></b>
复制代码

(2)JPQL 说明及使用语法

说明: 如果复杂业务也可以自己写 JPQL 语句,这里就讲使用注解的方式,这样更加简洁方便。


简介:JPQL(Java Persistence Query Language , Java 持久化查询语言)和 SQL 之间有很多相似之处 , 它们之间主要的区别在于前者处理 JPA 实体 , 而后者则直接涉及关系数据 。 JPQL 允许我们使用 SELECT 、 UPDATE 和 DELETE 语法定义查询


语法说明:

a.查询:

1.基础查询语法: SELECT 标识符变量 FROM 实体名称 [AS] 标识符变量


示例:查询所有的雇员信息


<b><b><b><code class="language-java">@Query("SELECT E FROM Employee E")List<Employee> selectExample();</code></b></b></b>
复制代码


查询参数规范:


JPQL 支持两种查询参数 , 它们分别是命名参数和位置参数 。


命名参数注意!语法: : + 自定义的参数名称


示例:按性别和薪资范围查找雇员信息


<b><b><b><code class="language-java">@Query("SELECT E FROM Employee E WHERE E.sex = :sex AND E.salary > :salary")List<Employee> selectExample(@Param("sex") String sex, @Param("salary") Double salary);</code></b></b></b>
复制代码


在方法的参数列表中 , 需要使用 @Param 注解标注每个参数的名称 , 使之与查询语句参数名称匹配 。


位置参数注意!语法: ? + 位置编号的数值


示例:按姓名和性别查找雇员信息


<b><font color="red"><b><b><code class="language-java">@Query("SELECT E FROM Employee E WHERE E.sex = ?1 AND E.salary > ?2")//这里不需要使用@Param注解,只需要对应好位置即可List<Employee> selectExample(String sex, Double salary);</code></b></b></font></b>
复制代码


在方法的参数列表中 , 参数的顺序需要与查询语句中参数标注的编号依次对应起来 。


2.关联查询通过使用关键字 [LEFT|INNER] JOIN 联接关系属性查询 。(左右中连接)


(1)单值关联查询语法: SELECT 标识符变量 FROM 实体名称 [AS] 标识符变量 JOIN 实体名称.单值关联字段 [AS] 标识符变量 2 ...


示例:按部门名称查找该部门所有的雇员信息


<font color="red"><b><b><font color="red"><b><code class="language-java">@Query("SELECT E FROM Employee E JOIN E.department D WHERE D.name = ?1")List<Employee> selectExample(String deptName);</code></b></font></b></b></font>
复制代码


(2)多值关联查询语法: SELECT 标识符变量 FROM 实体名称 [AS] 标识符变量 JOIN 实体名称.多值关联字段 [AS] 标识符变量 2 ...


示例:查询薪资大于 10000 的所有雇员所属的部门信息


<font color="red"><b><b><font color="red"><b><code class="language-java">@Query("SELECT D FROM Department D JOIN D.employees E WHERE E.salary > 10000")List<Department> selectExample();</code></b></font></b></b></font>
复制代码


或者: SELECT 标识符变量 FROM 实体名称 [AS] 标识符变量, IN(实体名称.多值关联字段) [AS] 标识符变量 2 ...


<font color="red"><b><b><font color="red"><b><code class="language-java">@Query("SELECT D FROM Department D, IN(D.employees) E WHERE E.salary > 10000")List<Department> selectExample();</code></b></font></b></b></font>
复制代码


3.去重查询语法: SELECT DISTINCT 标识符变量 FROM 实体名称 [AS] 标识符变量 ...


示例:查询薪资大于 10000 的所有雇员所属的部门信息 , 并消除查询结果中的重复的部门


<font color="red"><b><b><font color="red"><b><code class="language-java">@Query("SELECT DISTINCT D FROM Department D JOIN D.employees E WHERE E.salary > 10000")List<Department> selectExample();</code></b></font></b></b></font>
复制代码


4.字面值 JPQL 支持的字面值有以下的 4 种:字符串,数字,布尔,枚举,字符串


(1)语法: '字符串'


示例:查询给定名字的雇员信息


<font color="red"><b><b><font color="red"><b><code class="language-java">@Query("SELECT E FROM Employee E WHERE E.name = '张三'")Employee selectExample();</code></b></font></b></b></font>
复制代码


如果字符串中含有单引号 , 则用两个单引号来表示 。 如:Li’Si -> Li’’Si


<font color="red"><b><b><font color="red"><b><code class="language-java">@Query("SELECT E FROM Employee E WHERE E.name = 'Li''Si'")Employee selectExample();</code></b></font></b></b></font>
复制代码


(2)数字整数类型:如 24 、 +24 、 -24 、 24L , 支持 Java Long 范围的数值 。


浮点数类型:如 24. 、 24.6 、 +24.6 、 -24.6 、 24.6F 、 24.6D , 支持 Java Double 范围的数值 。


示例:查询薪资大于 10000 的所有雇员


<font color="red"><b><b><font color="red"><b><code class="language-java">@Query("SELECT E FROM Employee E WHERE E.salary > 10000.0")List<Employee> selectExample();</code></b></font></b></b></font>
复制代码


(3)布尔布尔类型的可选值为: TRUE 或 FALSE , 它们不区分大小写 。


示例:查找已婚的所有雇员


<font color="red"><b><b><font color="red"><b><code class="language-java">@Query("SELECT E FROM Employee E WHERE E.married = TRUE")List<Employee> selectExample();</code></b></font></b></b></font>
复制代码


(4)枚举枚举类名必须指定为完全限定类名 。


示例:查询所有女性的雇员


<font color="red"><b><b><font color="red"><b><code class="language-java">@Query("SELECT E FROM Employee E WHERE E.sex = org.fanlychie.enums.Sex.FEMALE")List<Employee> selectExample();</code></b></font></b></b></font>
复制代码


5.模糊查询表达式 匹配 不匹配 E.name LIKE ‘张 %’ 张三 小张伟 E.name LIKE ‘张_’ 张三 张三丰 E.name LIKE ‘张_%’ 张_三 张三示例:查询张性的所有雇员


<font color="red"><b><b><font color="red"><b><code class="language-java">@Query("SELECT E FROM Employee E WHERE E.name LIKE '张%'")List<Employee> selectExample();</code></b></font></b></b></font>
复制代码


6.空集合查询通过使用关键字 IS [NOT] EMPTY 来查找关联的属性集合的值为空的记录 。


示例:查找尚无雇员的所有部门


<font color="red"><b><b><font color="red"><b><code class="language-java">@Query("SELECT D FROM Department D WHERE D.employees IS EMPTY")List<Department> selectExample();</code></b></font></b></b></font>
复制代码


7.构造器查询结果的类型如果不是持久化的实体类 , 必须使用该类的完全限定名 。


语法: SELECT NEW 类的完全限定名(参数 1, 参数 2, ...) ...


示例:查询所有的雇员信息


<font color="red"><b><b><font color="red"><b><code class="language-java">package org.fanlychie.model;
public class SimpleEmployee{
private String name;
private Sex sex;
public SimpleEmployee(String name, Sex sex){ this.name = name; this.sex = sex; }
// getters and setters }@Query("SELECT NEW org.fanlychie.model.SimpleEmployee(E.name, E.sex) FROM Employee E")List<SimpleEmployee> selectExample();</code></b></font></b></b></font>
复制代码

b.更新

示例:更新某个雇员的婚姻状态和薪资信息


<font color="red"><b><font color="red"><b><font color="red"><b><code class="language-java">@Modifying@Transactional@Query("UPDATE Employee SET married = ?2, salary = ?3 WHERE id = ?1")int updateExample(Long id, Boolean married, Double salary);</code></b></font></b></font></b></font>
复制代码


@Query 无法进行 DML (Data Manipulation Language 数据操控语言 , 主要语句有 INSERT 、 DELETE 、 UPDATE )操作 , 如需更新数据库表的数据需要标注 @Modifying 注解 , 并且需要事务的支持 @Transactional 。

c.删除

示例:删除没有雇员的部门信息


<font color="red"><b><font color="red"><b><font color="red"><b><code class="language-java">@Modifying@Transactional@Query("DELETE FROM Department D WHERE D.employees IS EMPTY")int deleteExample();</code></b></font></b></font></b></font>
复制代码


以下是实际中举例:


<font color="red"><b><font color="red"><b><font color="red"><b><code class="language-java">package com.example.demo.repository;
import com.example.demo.pojo.Admin;import org.springframework.data.jpa.repository.JpaRepository;import org.springframework.data.repository.PagingAndSortingRepository;import org.springframework.stereotype.Repository;
//声明为repository@Repositorypublic interface AdminRepository extends PagingAndSortingRepository<Admin,Long> { //自定义SQL语句必须在事务环境下运行 必须有DML支持(Modifying) //?1表示下面的形参的第1个位置,这里不对表进行操作,直接对实体类进行操作,然后实体类映射到表中。 //这个注解也可以加到测试类上面 但需要跟进一个@commit提交事务的注解 因为测试类会自动回滚事务 @Transactional @Modifying @Query("update Admin set password=?1 where id=?2") int updatePasswordById(String newPassword,int id);
}</code></b></font></b></font></b></font>
复制代码

(3)原生 SQL

说明: 如果不习惯 JQPL 可以使用原生 SQL,这就和平时写 SQL 一样就不多介绍了


<font color="red"><b><font color="red"><b><b><code class="language-java">package com.example.demo.repository;
import com.example.demo.pojo.Admin;import org.springframework.data.jpa.repository.JpaRepository;import org.springframework.data.repository.PagingAndSortingRepository;import org.springframework.stereotype.Repository;
//声明为repository@Repositorypublic interface AdminRepository extends PagingAndSortingRepository<Admin,Long> { @Transactional @Modifying //唯一不同就是多了nativeQuery参数为true,开启原生SQL @Query(value = "update account set password=?1 where name=?2",nativeQuery = true) int updatePasswordByUsername(String password,String username);

}</code></b></b></font></b></font>
复制代码


总结:JPA 的特长就是实现全自动 ORM 框架,不用动手写 SQL,但是只适用于一些简单的业务,如果更复杂的情况还是 Mybatis 更有优势。希望对您有帮助,感谢阅读结束语:裸体一旦成为艺术,便是最圣洁的。道德一旦沦为虚伪,便是最下流的。勇敢去做你认为正确的事,不要被世俗的流言蜚语所困扰。


发布于: 2022-11-25阅读数: 37
用户头像

奇安信开发工程师,有问题可以私聊我! 2019-03-16 加入

还未添加个人简介

评论

发布
暂无评论
JPQL超详细介绍与JPA命名规则_Spring JPA_陈老老老板_InfoQ写作社区