继承jpa Repository 写自定义方法查询的实例分析

2023-05-22,

这篇文章给大家介绍继承jpa Repository 写自定义方法查询的实例分析,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

    继承jpa Repository写自定义方法查询

    今天在写jpa查询的时候,遇到了添加自定义方法,项目启动报错原因,现总结如下:

    首先定义实体类

    @Entity
    @Table(name = "user")
    Class User{
         @Id
        @GeneratedValue 
          int id;
          @Column
          String age;
          @Column
          String school;
          @Column
          String userName;
      set,get方法 (省略)
     
    }
    public interface UserRepository extends JpaRepository<User, Long> {
          List<User> findByUsernameLike(String username);
         List<User> aaa();
    }

    启动项目时,

    项目报错提示信息为

    org.springframework.data.mapping.PropertyReferenceException: No property aaa found for type com.fpi.safety.common.entity.po.User

    再将List<User> aaa();方法去掉后,项目又可以正常启动运行

    是什么原因呢?

    经查找,原来是继承jpa,必须满足一些规则,规则如下

    Spring Data JPA框架在进行方法名解析时,会先把方法名多余的前缀截取掉,比如find,findBy,read,readBy,get,getBy,然后对剩下的部分进行解析。

    假如创建如下的查询:findByUserName(),框架在解析该方法时,首先剔除findBy,然后对剩下的属性进行解析,假设查询实体为User

    1:先判断userName(根据POJO规范,首字母变为小写)是否为查询实体的一个属性,如果是,则表示根据该属性进行查询;如果没有该属性,继续第二步;

    2:从右往左截取第一个大写字母开头的字符串此处是Name),然后检查剩下的字符串是否为查询实体的一个属性,如果是,则表示根据该属性进行查询;如果没有该属性,则重复第二步,继续从右往左截取;最后假设用户为查询实体的一个属性;

    3:接着处理剩下部分(UserName),先判断用户所对应的类型是否有userName属性,如果有,则表示该方法最终是根据“User.userName”的取值进行查询;否则继续按照步骤2的规则从右往左截取,最终表示根据“User.userName”的值进行查询。

    4:可能会存在一种特殊情况,比如User包含一个的属性,也有一个userNameChange属性,此时会存在混合。可以明确在属性之间加上“_”以显式表达意思,比如“findByUser_NameChange )“或者”findByUserName_Change()“

    从上面,我们可以得知,jap在解析是,aaa在user类中是没有属性的,所以报错No property aaa found.

    如果我们想要使用jap框架,又不想再多增加一个自定义类,则必须符合其命名规则

    如果,你记不住jpa的规则也没关系,你可以自己再多写一个类来实现自定义查询方法

    如下:

    1. 自定义一个接口,该接口用来声明自己额外定义的查询。

    public interface UseerRepositoryTwo {
        public List<User> searchUser(String name, int id);
    }

    2. 创建一个接口,该接口 extends JpaRepository 或者 CurdRepository, 以及上面自己定义的接口 UseerRepositoryTwo

    public interface UserRepositoryTwoService extends CrudRepository<LogDTO, Integer>, CustomizedLogRepository {
    }

    3. 实现UserRepositoryTwoService

    注意此处的类名,必须以 2 中创建的接口的名字UserRepositoryTwoService,后面加上 Impl 来声明,而不是写成 UseerRepositoryTwoImpl

    public class UserRepositoryTwoServiceImpl implements UserRepositoryTwoService {
        @Autowired
        @PersistenceContext
        private EntityManager entityManager;
        @Override
        public List<User> searchLogs(int Id, String name) {
            ......
        }
    }

    自己在写自定义实现即可~

    JpaRepository 命名规范

    Keyword Sample JPQL
    And findByLastnameAndFirstname where x.lastname=?1 and x.firstname=?2
    Or findByLastnameOrFirstname where x.lastname=?1 or x.firstname=?2
    Between findByStartDateBetween where x.startDate between ?1 and ?2
    LessThan findByAgeLessThan where x.startDate < ?1
    GreaterThan findByAgeGreaterThan where x.startDate >?1
    After findByStartDateAfter where x.startDate >n ?1
    Before findByStartDateBefore where x.startDate < ?1
    IsNull findByAgeIsNull where x.age is null
    IsNotNull,NotNull findByAge(Is)NotNull where x.age not null
    Like findByFirstnameLike where x.firstname like ?1
    notLike findByFirstnameNotLike where x.firstname not like ?1
    StartingWith findByFirstnameStartingWithXXX where x.firstname like ?1(parameter bound with appended %)
    EndingWith findByFirstnameEndingWithXXX where x.firstname like ?1(parameter bound with appended %)
    Containing findByFirstnameContaining where x.firstname like ?1(parameter bound wrapped in %)
    OrderBy findByAgeOrderByLastname where x.age = ?1 order by x.lastname desc
    Not findByLastnameNot where x.lastname <> ?1
    NotIn findByAgeNotIn(Collection age ) where x.age not in ?1
    True findByActiveTrue() where x.active = true
    False findByActiveFalse()

    where x.active = false

    例:

    @RepositoryDefinition(domainClass = Employee.class, idClass = Integer.class)
    public interface EmployeeRepository { //extends Repository<Employee,Integer>{
        public Employee findByName(String name);
        // where name like ?% and age <?
        public List<Employee> findByNameStartingWithAndAgeLessThan(String name, Integer age);
        // where name like %? and age <?
        public List<Employee> findByNameEndingWithAndAgeLessThan(String name, Integer age);
        // where name in (?,?....) or age <?
        public List<Employee> findByNameInOrAgeLessThan(List<String> names, Integer age);
        // where name in (?,?....) and age <?
        public List<Employee> findByNameInAndAgeLessThan(List<String> names, Integer age);
        @Query("select o from Employee o where id=(select max(id) from Employee t1)")
        public Employee getEmployeeByMaxId();
        @Query("select o from Employee o where o.name=?1 and o.age=?2")
        public List<Employee> queryParams1(String name, Integer age);
        @Query("select o from Employee o where o.name=:name and o.age=:age")
        public List<Employee> queryParams2(@Param("name")String name, @Param("age")Integer age);
        @Query("select o from Employee o where o.name like %?1%")
        public List<Employee> queryLike1(String name);
        @Query("select o from Employee o where o.name like %:name%")
        public List<Employee> queryLike2(@Param("name")String name);
        @Query(nativeQuery = true, value = "select count(1) from employee")//这个使用了原生sql
        public long getCount();
        @Modifying
        @Query("update Employee o set o.age = :age where o.id = :id")
        public void update(@Param("id")Integer id, @Param("age")Integer age);
    }

    关于继承jpa Repository 写自定义方法查询的实例分析就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

    《继承jpa Repository 写自定义方法查询的实例分析.doc》

    下载本文的Word格式文档,以方便收藏与打印。