Spring Data JPA 通过不同的方式实现查询操作

  • 测试jpql的更新操作

*/

@Test

@Transactional//添加注解支持

@Rollback(value =false)

public void testUpdateCustomer(){

customerDao.updateCustomer(1l,“黑马程序员”);

}

4. 使用sql语句形式进行查询

使用@Query注解,配置sql查询,添加nativeQuery属性修改查询方式:true:sql查询、 false:jpql查询

sql语句 :sql:select * from cst_customer

/**

  • 在CustomerDao接口中添加查询全部的客户的方法

*/

@Query(value = “select * from cst_customer”,nativeQuery = true)

public List<Object []> findSql();

//测试sql查询

@Test

public void testFindSql(){

List<Object[]> list = customerDao.findSql();

for (Object []obj:list) {

System.out.println(Arrays.toString(obj));

}

}

5. 使用sql语句实现模糊查询

/**

  • 在CustomerDao接口中添加查询全部的客户的方法

*/

@Query(value = “select * from cst_customer where cust_name like ?”,nativeQuery = true)

public List<Object []> findLikeSql(String name);

//测试sql模糊查询

@Test

public void testFindLikeSql(){

List<Object[]> list = customerDao.findLikeSql(“%程序员”);

for (Object []obj:list) {

System.out.println(Arrays.toString(obj));

}

SimpleJpaRepository s=null;

}

按照方法命名规则查询


我们在Dao层定义方法时,可以根据方法命名规则编写方法。这是我们只需要根据方法的名字,就能执行相应的查询语句。(前提是需要按照Spring Data JPA提供的方法命名规则定义方法的名称)

Spring Data JPA在程序执行的时候会根据方法名称进行解析,并自动生成查询语句进行查询

按照Spring Data JPA 定义的规则,查询方法以findBy开头,涉及条件查询时,条件的属性用条件关键字 (AND|OR) 连接,要注意的是:条件属性首字母需大写。框架在进行方法名解析时,会先把方法名多余的前缀截取掉,然后对剩下部分进行解析。

1. 测试通过客户名称查询

语法:findBy +属性名称(根据属性名称进行完成匹配的查询)

//按照命名规则定义方法,不在需要添加注解

public Customer findByCustName(String name);

//测试方法

@Test

public void testNaming(){

Customer customer = customerDao.findByCustName(“黑马程序员”);

System.out.println(customer);

}

2. 测试模糊查询

语法:findBy +属性名称 + 方式(like|isnull)

//按照命名规则定义方法,实现模糊查询

public List findByCustNameLike(String name);

//测试方法

@Test

public void testFindByCustNameLike(){

List byCustNameLike = customerDao.findByCustNameLike(“%程序员”);

for (Customer customer:byCustNameLike){

System.out.println(customer);

}

}

3. 测试复合查询

语法: findBy +属性名称 + 查询方式 + 多条件连接符(AND|OR)+属性名+ 查询方式

//使用客户名称模糊匹配,和客户所属行业精准匹配

public List findByCustNameLikeAndCustIndustry(String custName,String custIndustry);

//测试方法

@Test

public void testFindByCustNameLikeAndCustIndustry(){

List byCustNameLike = customerDao.findByCustNameLikeAndCustIndustry(“%程序员”,“程序员”);

for (Customer customer:byCustNameLike){

System.out.println(customer);

}

}

具体的关键字,使用方法和生产成SQL如下表所示:

| Keyword | Sample | JPQL |

| — | — | — |

| And | findByLastnameAndFirstname | … where x.lastname = ?1 and x.firstname = ?2 |

| Or | findByLastnameOrFirstname | … where x.lastname = ?1 or x.firstname = ?2 |

| Is,Equals | 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 ages) | … where x.age in ?1 |

| NotIn | findByAgeNotIn(Collection age) | … 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) |

Specifications动态查询


有时我们在查询某个实体的时候,给定的条件是不固定的,这时就需要动态构建相应的查询语句,在Spring Data JPA中可以通过JpaSpecificationExecutor接口查询。相比JPQL,其优势是类型安全,更加的面向对象。

/**

  • JpaSpecificationExecutor中定义的方法

**/

public interface JpaSpecificationExecutor {

//根据条件查询一个对象

T findOne(Specification spec);

//根据条件查询集合

List findAll(Specification spec);

//根据条件分页查询

Page findAll(Specification spec, Pageable pageable);

//排序查询查询

List findAll(Specification spec, Sort sort);

//统计查询

long count(Specification spec);

}

对于JpaSpecificationExecutor,这个接口基本是围绕着Specification接口来定义的。我们可以简单的理解为,Specification构造的就是查询条件。

/**Specification接口

  • root :比较的属性

  • query :用来自定义查询

  • cb :查询的方式public interface Specification {

*/

public interface Specification {

Predicate toPredicate(Root var1, CriteriaQuery<?> var2, CriteriaBuilder var3);

}

1.通过Specification实现条件查询

实现步骤:

  • 1.通过匿名内部类的方式实现Specification接口(提供泛型,查询对象的类型)

  • 2.实现toPredicate方法(构造查询条件)

  • 3.通过控制参数(root:比较的属性,cb:查询的方式),实现匹配,获得Predicate对象

  • 4.返回Predicate对象

@Test

public void testSpecFindByName(){

/**

  • 自定义查询条件

  • 案例:根据客户名称查询

*/

Specification spec= new Specification() {

public Predicate toPredicate(Root root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {

//1.获取比较的属性

Path custName = root.get(“custName”);

//2.构造查询: select * from where cust_name=‘程序员’

/**

  • 第一个参数:需要比较的属性(path对象)

  • 第二个参数:当前需要比较的值

*/

Predicate predicate = criteriaBuilder.equal(custName, “黑马程序员”);//进行精准匹配

return predicate;

}

};

Customer customer=customerDao.findOne(spec);

System.out.println(customer);

}

2. 通过Specification实现多条件查询

实现步骤:

  • 1.通过匿名内部类的方式实现Specification接口(提供泛型,查询对象的类型)

  • 2.实现toPredicate方法(构造查询条件)

  • 3.通过控制参数(root:比较的属性,cb:查询的方式),实现匹配,获得Predicate对象

  • 4.将匹配到的两个结果结合起来

  • 5.返回Predicate对象

@Te
st

public void testSpecFindByNameAndIndustry(){

/**

  • 将两个查询结果联系起来,实现多条件查询

*/

Specification spec= new Specification() {

public Predicate toPredicate(Root root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {

//1.获取客户名的属性

Path custName = root.get(“custName”);

//2.获取所属行业的属性

Path custIndustry = root.get(“custIndustry”);

//2.构造查询

//1.构造客户名的精准匹配查询

Predicate p1 = criteriaBuilder.equal(custName, “黑马程序员”);//进行精准匹配

Predicate p2 = criteriaBuilder.equal(custIndustry, “程序员”);//进行精准匹配

//2.组合条件(AND、OR)

Predicate predicate = criteriaBuilder.and(p1, p2);

return predicate;

}

};

Customer customer=customerDao.findOne(spec);

System.out.println(customer);

}

3. 通过Specification实现模糊查询

实现步骤:

  • 1.通过匿名内部类的方式实现Specification接口(提供泛型,查询对象的类型)

  • 2.实现toPredicate方法(构造查询条件)

  • 3.通过控制参数(root:比较的属性,cb:查询的方式),实现匹配,获得Predicate对象

对于equal方法:直接得到path对象,然后进行比较即可,但是对于gt,lt,ge,le,like想要得到path对象,需要根据path指定比较参数的类型,指定参数类型:path.as(类型的字节码对象)

  • 4.返回Predicate对象

@Test

public void testSpecFindByNameLike(){

/**

  • 实现模糊查询

*/

Specification spec= new Specification() {

public Predicate toPredicate(Root root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {

//1.获取客户名的属性

Path custName = root.get(“custName”);

//2.构造查询

Predicate like = criteriaBuilder.like(custName.as(String.class), “%程序员”);

return like;

}

};

Listlist=customerDao.findAll(spec);

for (Customer customer:list) {

System.out.println(customer);

}

}

方法对应关系:

| 方法名称 | Sql对应关系 |

| — | — |

| equle | filed = value |

| notEqule | filed != value |

| like | filed like value |

| notLike | filed not like value |

| gt greaterThan ) | filed> value |

| ge (greaterThanOrEqualTo) | filed >= value |

| lt(lessThan ) | filed< value |

| le( lessThanOrEqualTo) | filed <= value |

3. 通过Specification实现模糊查询

实现步骤:

  • 1.添加排序,创建排序对象,需要调用构造方法实例化sort对象

  • 2.设置两个参数:第一个参数:排序的顺序(升序、降序)

Sort.Direction.DESC:倒序、Sort.Direction.ASC:升序

  • 3.设置两个参数:第二个参数:排序的属性名称

  • 4.结合Specification实现带条件的将查询结果排序

@Test

public void testSpecDESC(){

Specification spec= null;

//添加排序

Sort sort =new Sort(Sort.Direction.DESC,“custId”);

Listlist=customerDao.findAll(spec,sort);

for (Customer customer:list) {

System.out.println(customer);

}

}

4. 通过Specification实现分页查询

实现步骤:

  • 1.使用Pageable实现分页,通过PageRequest对象实现Pageable接口

  • 2.设置两个参数:第一个参数:当前查询的页数(从0开始)

  • 3.设置两个参数:第二个参数:每页查询的数量

  • 4.结合Specification实现带条件的将查询结果排序

findAll(Pageable) //无条件分页、findAll(Specification,Pageable)//带条件分页

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值