天天看点

JPA声明式查询关键字及使用方法

分享知识 传递快乐

使用JPA自定义声明式查询方法

凡是继承了JpaRepository的或继承其子接口的,都可以使用自定义的声明式查询方法。

声明式查询方法可以分3大类:

  • 计数类:以count开头,返回数值类型。
  • 查询类:以get/find/stream/query/read开头,返回实体类或其集合。
  • 删除类:以delete/remove开始,返回int类型。

示例:

public interface WebTaskRepository extends JpaRepository<WebTask, Integer> {
    // declare query method
    // 声明式查询方法 

    // 1. count 计数 
    long countByName(String name); 
    
    // 2. get/find/stream/query/read 查询 
    public List<WebTask> findByTaskName(String name);
    
    // 3. delete/remove 删除 
    int deleteById(long id);
 }      

在以上方法之后还有可以加入下面的关键词。

JPA声明式查询方法名称关键词

查询方法可以由我们声明的命名查询生成,也可以像前面那样由方法名解析。

  • 方法名以find…By, read…By, query…By, count…By和 get…By做开头。在By之前可以添加Distinct表示查找不重复数据。By之后是真正的查询条件。
  • 可以查询某个属性,也可以使用条件进行比较复杂的查询,例如Between, LessThan, GreaterThan, Like,And,Or等。
  • 字符串属性后面可以跟IgnoreCase表示不区分大小写,也可以后跟AllIgnoreCase表示所有属性都不区分大小写。
  • 可以使用OrderBy对结果进行升序或降序排序。
  • 可以查询属性的属性,直接将几个属性连着写即可,如果可能出现歧义属性,可以使用下划线分隔多个属性。
Keyword Sample JPQL snippet

​And​

​findByLastnameAndFirstname​

​… where x.lastname = ?1 and x.firstname = ?2​

​Or​

​findByLastnameOrFirstname​

​… where x.lastname = ?1 or x.firstname = ?2​

​Is,​

​​

​Equals​

​findByFirstname​

​,

​findByFirstnameIs​

​,

​findByFirstnameEquals​

​… where x.firstname = ?1​

​Between​

​findByStartDateBetween​

​… where x.startDate between ?1 and ?2​

​LessThan​

​findByAgeLessThan​

​… where x.age < ?1​

​LessThanEqual​

​findByAgeLessThanEqual​

​… where x.age <= ?1​

​GreaterThan​

​findByAgeGreaterThan​

​… where x.age > ?1​

​GreaterThanEqual​

​findByAgeGreaterThanEqual​

​… where x.age >= ?1​

​After​

​findByStartDateAfter​

​… where x.startDate > ?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​

​findByFirstnameStartingWith​

​… where x.firstname like ?1​

​​ (parameter bound with appended ​

​%​

​)

​EndingWith​

​findByFirstnameEndingWith​

​… where x.firstname like ?1​

​​ (parameter bound with prepended ​

​%​

​)

​Containing​

​findByFirstnameContaining​

​… where x.firstname like ?1​

​​ (parameter bound wrapped in ​

​%​

​)

​OrderBy​

​findByAgeOrderByLastnameDesc​

​… where x.age = ?1 order by x.lastname desc​

​Not​

​findByLastnameNot​

​… where x.lastname <> ?1​

​In​

​findByAgeIn(Collection<Age> ages)​

​… where x.age in ?1​

​NotIn​

​findByAgeNotIn(Collection<Age> ages)​

​… where x.age not in ?1​

​True​

​findByActiveTrue()​

​… where x.active = true​

​False​

​findByActiveFalse()​

​… where x.active = false​

​IgnoreCase​

​findByFirstnameIgnoreCase​

​… where UPPER(x.firstame) = UPPER(?1)​

具体语法规则和对应的sql都在代码中给出来了,这边需要和大家说的是UserRepository接口的特点。我们通过继承JpaRepository《对应的实体类,主键属性值》来编写findBy等相关的函数来查询数据库。继承JpaRepository的接口在使用的时候,通过@Autowired会自动创建接口的实现类,不需要怎么去实现这个接口,这也是jpa最方便的地方。如果需要详细说明的话可以查看官方文档​​Appendix C: Repository query keywords​​一节。

实例说明:

实体类

@Entity
@Table(name="user")
public class User {
  @Id
  @GenericGenerator(name = "PKUUID", strategy = "uuid2")
  @GeneratedValue(generator = "PKUUID")
  @Column(length = 36)
  protected String id;
  
  @Column(name = "name", nullable = true, length = 30)
  private String name;
  
  @Column(name = "height", nullable = true, length = 10)
  private Integer height;
  
  public User() {
  }
  
  public String getId() {
    return id;
  }
  public void setId(String id) {
    this.id = id;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public Integer getHeight() {
    return height;
  }
  public void setHeight(Integer height) {
    this.height = height;
  }
}      

JPA

public interface UserRepository extends JpaRepository<User,String>{
  /**
  * 相当于 select *from user where name=?
  * @param name
  * @return
  */
  public List<User> findByName(String name);
  
  /**
  * 相当于select *from user where name like ?
  * 但是有一点需要注意的是,%需要我们自己来写
  * @param name
  * @return
  */
  public List<User> findByNameLike(String name);
  
  /**
  * 相当于select *from user where name not like ?
  * 但是有一点需要注意的是,%需要我们自己来写
  * @param name
  * @return
  */
  public List<User> findByNameNotLike(String name);
  
  /**
  * 相当于 select *from user where name <> ?
  * @param name
  * @return
  */
  public List<User> findByNameNot(String name);
  
  /**
  * 相当于 select *from user where id in (?)
  * @param ids
  * @return
  */
  public List<User> findByIdIn(List<String> ids);
  
  /**
  * 相当于 select *from user where id not in ()
  * @param ids
  * @return
  */
  public List<User> findByIdNotIn(List<String> ids);
  
  /**
  * 相当于 select *from user where name=? order by height desc
  * @param name
  * @return
  */
  public List<User> findByNameOrderByHeightDesc(String name);
  
  /**
  * 相当于 select *from user where name=? order by height asc
  * @param name
  * @return
  */
  public List<User> findByNameOrderByHeightAsc(String name);
  
  /**
  * 相当于 select *from user where name is null
  * @return
  */
  public List<User> findByNameIsNull();
  
  /**
  * 相当于 select *from user where name is not null
  * @return
  */
  public List<User> findByNameIsNotNull();
  
  /**
  * 相当于 select *from user where name =? and height=?
  * @param name
  * @param height
  * @return
  */
  public List<User> findByNameAndHeight(String name,int height);
  
  /**
  * 相当于 select *from user where name =? or height=?
  * @param name
  * @param height
  * @return
  */
  public List<User> findByNameOrHeight(String name,int height);
  
  /**
  * 相当于 select *from user where height between ? and ?
  * 需要注意的是mysql是有包含两个端点值的
  * @param start
  * @param end
  * @return
  */
  public List<User> findByHeightBetween(int start,int end);
  
  /**
  * 相当于 select *from user where height < ?
  * 需要注意的是mysql是没有包含端点值的
  * @param less
  * @return
  */
  public List<User> findByHeightLessThan(int less);
  
  /**
  * 相当于 select *from user where height > ?
  * 需要注意的是mysql是没有包含端点值的
  * @param greater
  * @return
  */
  public List<User> findByHeightGreaterThan(int greater);
  
  //计数
  public Long countByName(String name);

  // 唯一查询,findDistinctByTaskName == findDistinctUserByTaskName
  List<User> findDistinctTaskNameByTaskName(String name);

  // 启用静态排序
  List<User> findByNameOrderByIdDesc(String name);

  // 查询符合查询条件的前1条数据
  User findFirst1ByName(String name);

  // 获得符合查询条件的前2条数据
  List<User> findTop2ByName(String name);
}      

扩展:

JPA写操作时需要注意,无论是更新,还是删除都需要加上@Transactional 和 @Modifying两个注解。

@Modifying
@Transactional
@Query(value="DELETE FROM DS_IPAY_PAY T WHERE T.BILL_ID = ?1",nativeQuery=true)
public void delete(Long billId);