/**
- 在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) |
有时我们在查询某个实体的时候,给定的条件是不固定的,这时就需要动态构建相应的查询语句,在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对象
@Test
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实现模糊查询
实现步骤:
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
最后
面试是跳槽涨薪最直接有效的方式,马上金九银十来了,各位做好面试造飞机,工作拧螺丝的准备了吗?
掌握了这些知识点,面试时在候选人中又可以夺目不少,暴击9999点。机会都是留给有准备的人,只有充足的准备,才可能让自己可以在候选人中脱颖而出。
711990633723)]
[外链图片转存中…(img-AoMly086-1711990633723)]
[外链图片转存中…(img-1Ycdlxj1-1711990633724)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-FyYS9Fui-1711990633724)]
最后
面试是跳槽涨薪最直接有效的方式,马上金九银十来了,各位做好面试造飞机,工作拧螺丝的准备了吗?
掌握了这些知识点,面试时在候选人中又可以夺目不少,暴击9999点。机会都是留给有准备的人,只有充足的准备,才可能让自己可以在候选人中脱颖而出。
[外链图片转存中…(img-blPMQigL-1711990633724)]
[外链图片转存中…(img-OPZwcIfF-1711990633725)]