SpringDataJPA使用jpql 原生sql 方法命名规则 实现多表联查和分页

这个也是我本次要写的过程中最想着重说的一个点,应为在写这个SQL 中遇到了很多坑,比如要进行多表联查的过程中就需要返回一个VO对象,在返回对象的时候需要进行相关的考虑和相关的设计,所以在进行相关的查询过程中,还要遵循JPA的语法规范,所以这些就比较难

这个是GItee地址想学的可以参考一下

SpringBootDataJpaDemo: 学习SpringBoot-Data-Jpa的demo工程,包含了jpa基本查询 ,example对象查询,Specification动态查询 以及分页等案例 - Gitee.com

jpql查询

jpql多表联查方式有两种

  • 使用VO(view object)做映射与投影; 即建立一个vo类,该类中包含了要查询的字段,然后在jpql中使用new 类名(属性1,属性2.......) from 的方式查询

    注意:一定要使用new 的方式 且最好使用类名的完全限定名 ,字段的位置必须一致

  • 使用接口方式接收 属性分命名为 getXXX ,****如 getMenuId() 方式 ;

推荐使用VO方式查询

1.VO方式查询

  • 新建一个vo实体
less 复制代码
@Data
@NoArgsConstructor
@AllArgsConstructor
public class SysMenuRoleDTO {
    private Long menuId;
    private String menuName;
    private Long roleId;
    private String roleName;
}
  • 写查询接口
less 复制代码
 @Query("select new com.lonni.dtos.SysMenuRoleDTO(menu.menuId,menu.menuName,ro.roleId,ro.roleName) from SysMenu  menu join SysRoleMenu ru on menu.menuId=ru.menuId " +
            "join  SysRole ro on ro. roleId=ru.roleId")
    Page<SysMenuRoleDTO> getMenuRoleDto(Pageable pageable);

注意这个地方是用了一个LEFT JOIN进行了一个多表的关联查询,查询的时候可以关联处理多个对象可以通过一种 new 的方式进行使用,但是这样代码看起来很难看

注意这里: new com.lonni.dtos.SysMenuRoleDTO(menu.menuId,menu.menuName,ro.roleId,ro.roleName)

这里一定要是new 的方式 且最好使用完全限定名,否则会找不到

  • 调用接口
csharp 复制代码
 @Test
    public void  testJpqlJoinVo(){
        Page<SysMenuRoleDTO> menuRoleDto = dao.getMenuRoleDto(PageRequest.of(0, 1));
        System.out.println(menuRoleDto);
        System.out.println(menuRoleDto.getTotalElements());
        System.out.println(menuRoleDto.getContent());
        System.out.println(menuRoleDto.getTotalPages());
    }

2.使用接口方式

这个方式就使用JPA的代理类来实现的使用此次方式可以更好的简化代码

  • 新建一个接口

注意格式,一定要是getXXX的方式

csharp 复制代码
/**
 * 使用接口方式接收返回值
 */
public interface SysMenuRole {

     Long getMenuId();
     String getMenuName();
     Long getRoleId();
     String getRoleName();
}
  • 写dao层接口
less 复制代码
//使用jpql多表查询 使用接口查询方式
    //案列 :角色拥有的菜单
    @Query("select menu.menuId,menu.menuName,ro.roleId,ro.roleName from SysMenu  menu join SysRoleMenu ru on menu.menuId=ru.menuId " +
            "join  SysRole ro on ro. roleId=ru.roleId")
    Page<SysMenuRole> getMenuRoleDtoByInterface(Pageable pageable);

这里直接就可以使用字段属性方式绑定了

  • 调用
scss 复制代码
 //测试jpql 多表查询 使用接口方式

    @Test
    public void  testJpqlJoinInterface(){
        Page<SysMenuRole> menuRoleDto = dao.getMenuRoleDtoByInterface(PageRequest.of(0, 1));
        System.out.println(menuRoleDto);
        System.out.println(menuRoleDto.getTotalElements());
        System.out.println(menuRoleDto.getContent());
        System.out.println(menuRoleDto.getTotalPages());
        List<SysMenuRole> content = menuRoleDto.getContent();
        for (SysMenuRole sysMenuRole : content) {
            System.out.println(sysMenuRole.getMenuId());
            System.out.println(sysMenuRole.getMenuName());
        }

    }

原生sql查询

基本语法

原生sql查询和jpql一样,只是需要设置query注解的 *nativeQuery=true*

语法:

@Query(value = "select * from sys_menu menu ",nativeQuery=true)

注意:使用原生sql查询就是查询表了 ,而不是查询实体 所以from后面的一定是数据库表名,且属性一定是数据库字段

分页

  • 分页的返回值不能是javaBean,因为使用原生sql查询了,就不会有字段映射了,最好使用Page<Map>
  • 分页直接加上 Pageable 参数
  • 原生sql****分页时不能使用别名 ,否则报错 (折腾了很久o.o)

接口定义 :

less 复制代码
//测试原生sql是否支持分页
    //jpql 分页查询
    @Query(value = " select * from  sys_menu   ",nativeQuery = true)
    Page<Map> getSysPage(Pageable pageable);
csharp 复制代码
//测试原生sql是否支持分页
    @Test
    public  void testSqlPage(){
        Page<Map> sysPage = dao.getSysPage(PageRequest.of(0, 2));
        System.out.println(sysPage.getTotalPages());
        System.out.println(sysPage.getContent());

    }

方法命名规则查询

只需要按照jpa提供的方法名称规则定义方法,不需要自定义jpql

约定:

  • findBy :标识查询操作

    对象中的属性(首字母大写):查询条件,如:findByMenuId 标识根据菜单id查询数据

    • 模糊查询 findByMenuNameLike( "测试%"); 传值必须使用sql模糊匹配语法,否则还是全匹配查询
    • 多条件查询 findByMenuIdOrMenuName ;使用and or

注意:使用方法命名规则查询参数的顺序必须和findBy后的一致

  • 使用方法定义查询 全匹配查询
    List<SysMenu> findByMenuIdOrMenuName(long menuId, String menuName);

  • 使用方法定义查询 模糊查询
    List<SysMenu> findByMenuNameLike(String menuName);

相关推荐
morris1316 分钟前
【SpringBoot】Xss的常见攻击方式与防御手段
java·spring boot·xss·csp
七星静香31 分钟前
laravel chunkById 分块查询 使用时的问题
java·前端·laravel
Jacob程序员32 分钟前
java导出word文件(手绘)
java·开发语言·word
ZHOUPUYU32 分钟前
IntelliJ IDEA超详细下载安装教程(附安装包)
java·ide·intellij-idea
stewie635 分钟前
在IDEA中使用Git
java·git
Elaine2023911 小时前
06 网络编程基础
java·网络
G丶AEOM1 小时前
分布式——BASE理论
java·分布式·八股
落落鱼20131 小时前
tp接口 入口文件 500 错误原因
java·开发语言
想要打 Acm 的小周同学呀1 小时前
LRU缓存算法
java·算法·缓存
镰刀出海1 小时前
Recyclerview缓存原理
java·开发语言·缓存·recyclerview·android面试