zoukankan      html  css  js  c++  java
  • Spring Data Jpa 自定义查询定义规则 及事务、分页

    关于SpringData JPA查询的定义

    1. spring data 对于定义方法的查询策略

    查询策略是spring data 根据方法名称取解析用户的查询意图,

    第一种,根据方法的命名规则解析,
    第二种是通过Query去解析,

    如果两种同时存在时,springdata按照那种解析方法名,这就是spring data的查询策略,查询策略可以在jpa:repositorys/ 属性query-lookup-strategy 配置

    CREATE: 通过解析方法的名称来创建查询,也就是下面的规则1

    USE_DECLARED_QUERY:根据定义好的语句去查询,如果找不到,抛出异常信息。查询语句定义在某个注解或者方法上。

    CREATE_IF_NOT_FOUND:优先查询方法上是否有定义好的查询语句,如果没有,则按照方法名称解析,这是默认的策略。

    public interface UserRepository extends JpaRepository<User,Integer>, JpaSpecificationExecutor<User> {
        //根据springData的关键字命名方法名称,可以不用写实现类
        List<User> findByNameAndAge(String name, Integer age);
     
        List<User> findByNameLikeAndAge(String name, Integer age);
        //@Query注解里面写JPQL语句,定义查询
        @Query(nativeQuery = false,value = " SELECT p FROM User p WHERE id = ?1")
        User readId(Integer id);
        //Query注解也可以定义SQL语句,只要将nativeQuery属性改为true
        @Query(nativeQuery = true, value = "select name from user where id = :id")
        String findNamebyId(@Param("id")Integer id);
        //@Modifying修饰方法,告知SpringData,这是一个UPATE或者DELETE操作
        //在service层的方法上添加事务操作
        @Modifying
        @Query(nativeQuery = true,value = "update user set name = ?1  where id = ?2 ")
        int updateUserNameById(String name,Integer id);
     
    }
    

    规则1:根据SpringData JPA的关键字定义方法名,方法的参数顺序和关键字的顺序一致,名称可以不一致。

    Spring Data JPA对方法名称进行解析的时候,会将一些无用的前缀名自动去除,比如find、findBy、read、readBy,然后根据关键字解析成对应JPQL语句。也要注意方法的参数顺序和定义的关键字的顺序一致。

    规则2:定义方法时候,上面加上注解@Query,默认nativeQuery是false,此时value填入的是JPQL语句,修改nativeQuery是true,就能够写入SQL语句

    //@Query注解里面写JPQL语句,定义查询
        @Query(nativeQuery = false,value = " SELECT p FROM User p WHERE id = ?1")
        User readId(Integer id);
        //Query注解也可以定义SQL语句,只要将nativeQuery属性改为true
        @Query(nativeQuery = true, value = "select name from user where id = :id")
        String findNamebyId(@Param("id")Integer id);
    

    注意参数注入的方式有两种:

    1. [?][方法参数索引],索引从1开始,例 ?1,?2
        @Query(nativeQuery = false,value = " SELECT p FROM User p WHERE id = ?1")
        User readId(Integer id);
    
    1. [:][],[...:][参数名],参数名必须是实体的属性名,并且方法参数上加上对应的注解@Param("xxx")@Param('yyy')
        @Query(nativeQuery = true, value = "select name from user where id = :id")
        String findNamebyId(@Param("id")Integer id);
    

    @Modify和事务

    可以通过JPQL语句定义update/delete,此时在@Query注解中定义,必须加上@Modify,告诉spring data 这是一个update/delete操作。

    update/delete操作需要事务支持,必须在service层,添加事务,因为spring data,默认情况下每个方法是只读事务,不能完成update/delete操作。

    public interface UserRepository extends JpaRepository<User,Integer>, JpaSpecificationExecutor<User> {
        //根据springData的关键字命名方法名称,可以不用写实现类
        List<User> findByNameAndAge(String name, Integer age);
        List<User> findByNameLikeAndAge(String name, Integer age);
        //@Query注解里面写JPQL语句,定义查询
        @Query(nativeQuery = false,value = " SELECT p FROM User p WHERE id = ?1")
        User readId(Integer id);
        //Query注解也可以定义SQL语句,只要将nativeQuery属性改为true
        @Query(nativeQuery = true, value = "select name from user where id = :id")
        String findNamebyId(@Param("id")Integer id);
        //@Modifying修饰方法,告知SpringData,这是一个UPATE或者DELETE操作
        //在service层的方法上添加事务操作
        @Modifying
        @Query(nativeQuery = true,value = "update user set name = ?1  where id = ?2 ")
        int updateUserNameById(String name,Integer id);
    }
    
    @Service
    public class UserServiceImpl implements  UserService {
        @Autowired
        private UserRepository repository;
        //对于SpringData jpa的update或者delete操作,必须在service层使用事务,直接使用仓库的方法会报错
        //另外,SpringData jpa 的 JPQL语法不支持insert
        @Transactional(propagation = Propagation.REQUIRED)
        public int updateUserNameById(String name,Integer id){
            return repository.updateUserNameById(name,id);
        }
     
    }
    
    @RunWith(value = SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = {"classpath:applicationContext.xml"})
    public class SpringDataTest {
        @Autowired
        private UserRepository repository;
        @Autowired
        private UserService service;
     
        @Test
        public void test(){
            service.updateUserNameById("张三",1);
        }
    }
    

    分页和模糊查询

    模糊查询

    需要注意的是%%外面不需要再加上''

    //模糊查询
        @Query(nativeQuery = true,value = " select  * from user where name like %?1% ")
        User findUserByLikeName(String name);
    

    分页对象

    1. 要求自定义的Repository必须继承了PagingAndSortingRepository或者他的子类JpaRepository

    2. 分页对象是Pageable接口的实现类PageRequest

    public class PageRequest implements Pageable, Serializable {
        private static final long serialVersionUID = 8280485938848398236L;
        private final int page;//页码,从0开始,0表示第一页,1表示第二页,以此类推
        private final int size;//每页显示的记录数
        private final Sort sort;//排序规则
    

    Sort对象,定义排序规则,常用的是下面这种构造函数,支持可变参数的

    public Sort(Sort.Direction direction, String... properties) {
            this(direction, (List)(properties == null ? new ArrayList() : Arrays.asList(properties)));
        }
    

    定义分页查询,只需要将查询的参数和分页对象作为参数。

    Page<User> findByNameLike(String str , Pageable pageable);
    
    @RunWith(value = SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = {"classpath:applicationContext.xml"})
    public class SpringDataTest {
        @Autowired
        private UserRepository repository;
        @Test
        public void test(){
           /**
            * SpringData jpa 的分页
            * Pageable接口的实现类是PageRequest,Page接口的实现类是PageImpl。
            */
           Pageable page = new PageRequest(0,2,new Sort(Sort.Direction.DESC,"id"));
           Page<User> personList =  repository.findByNameLike("张%",page);
            System.out.println("总记录数" + personList.getTotalElements());
            System.out.println("当前第几页: " + (personList.getNumber() + 1));
            System.out.println("总页数: " + personList.getTotalPages());
            System.out.println("当前页面的记录数:" + personList.getContent());
            System.out.println("当前页面的记录数: " + personList.getNumberOfElements());
        }
    }
    
  • 相关阅读:
    填坑!!!virtualenv 中 nginx + uwsgi 部署 django
    树的遍历与递归
    Python 函数的参数
    virtualbox安装增强功能时【未能加载虚拟光盘】
    深入理解Python中的生成器
    Genymotion下载慢或者下载失败的解决办法
    Python3 多线程的两种实现方式
    Java 多线程
    关于"裁员与面试"的个人感悟吧
    三、由简单对象组装复杂实例的模式:建造者模式
  • 原文地址:https://www.cnblogs.com/eedc/p/13042076.html
Copyright © 2011-2022 走看看