1:SpringDataJPA是JPA规范的再次封装抽象,底层还是使用了Hibernate的JPA技术实现,是属于Spring的生成体系中的一部分
2:SpringData的结构(七个接口)
操作数据库的方式一:继承JpaRepository口后操作数据库
1:在Repository层新建一个基础接口
1 @NoRepositoryBean //告诉JPA不要创建对应接口的bean对象
2 public interface BaseReposittory extends JpaRepository{3 }
2:再建一个你所要操作的类型的接口去继承 这里以实体类Employee举例 这里Long是数据库中主键的类型 完成后就已经具备了基础的CRUD 和分页排序的功能
1 public interface EmployeeRepository extends BaseReposittory{
注意:在操作数据库时 添加和修改所使用的都是save()方法 ;可以自行测试 这里测试一个分页排序
1 @Test//分页排序
2 public void pageAndSort() throwsException{3 Sort sort = new Sort(Sort.Direction.DESC,"age");4 Pageable page = new PageRequest(0,10,sort);5 Page employees =employeeRepository.findAll(page);6 employees.forEach(e->{7 System.out.println(e);8 });9 }
基础查询和分页排序底层已经定义好可以直接使用 现在我们来自定义查询; 查询方法写在EmployeeRepository中
自定义查询
方式一:按照规范创建查询方法,一般按照java驼峰式书写规范加一些特定关键字
例:
1 //根据名称模糊查询
2 ListfindByUsernameLike(String username);3 //根据名称进行查询
4 List findByUsername(String username);
查询规则如下:
表达式
例子
hql查询语句
And
findByLastnameAndFirstname
… where x.lastname = ?1 and x.firstname = ?2
Or
findByLastnameOrFirstname
… where x.lastname = ?1 or x.firstname = ?2
Is,Equals
findByFirstname,findByFirstnameIs,findByFirstnameEqual
… where x.firstname = 1?
Between
findByStartDateBetween
… where x.startDate between 1? and ?2
LessThan(lt)
findByAgeLessThan
… where x.age < ?1
LessThanEqual(le)
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)
方式二:@Query注解查询
在EmployeeRepository按照查询方法的命名规则,其实是比较麻烦的如果我们想不遵循 查询方法的命名规则,还可以使用@Query的方法进行查询。只需要将@Query定义在Respository的方法之上即可
1:使用jpql语句操作数据库
例:
1 //根据用户名查询(这里写必需在问号后加顺序)
2 @Query("select e from Employee e where e.username = ?1")3 Employee query01(String name);4 //根据用户名模糊查询(这里写必需在问号后加顺序)
5 @Query("select e from Employee e where e.username like ?1")6 Listquery02(String name);7 //根据用户名与邮件进行模糊查询(这里写必需在问号后加顺序)
8 @Query("select e from Employee e where e.username like ?1 and e.email like ?2")9 List query03(String name, String email);
2:如果想用原生sql操作数据库只需在注解@Query中加nativeQuery =true
例:
1 //查询所有
2 @Query(nativeQuery =true,value = "select * from employee where username=?;")3 Employee query04(String name);
方式三:继承接口JpaSpecificationExecutor
JpaSpecificationExecutor的认识
JpaSpecificationExecutor(JPA规则执行者)是JPA2.0提供的CriteriaAPI的使用封装,可以用于动态生成Query来满足我们业务中的各种复杂场景。
Spring Data JPA为我们提供了JpaSpecificationExecutor接口,只要简单实现toPredicate方法就可以实现复杂的查询。所有查询都要求传入一个Specification对象
1:BaseReposittory的操作
@NoRepositoryBean //告诉JPA不要创建对应接口的bean对象
public interface BaseReposittory extends JpaRepository,JpaSpecificationExecutor{
}
2:测试:直接来个多条件查询
1 /**
2 * 根据相应的规则(Specification) 查询对应数据3 * Predicate: where username=? and email =?4 * root : 根 -> 可以获取到类中的属性(username,email)5 * criteriaQuery: 如select,from,where,group by ,order by 等6 * criteriaBuilder:解决 username=? / username like ? / age > ?7 * 多个条件结合 username=? and/or age > ?8 */
9 @Test//多条件查询+分页+排序
10 public void testJpaSpecificationExecutor() throwsException{11 //先定义规范
12 Specification spec= new Specification() {13 @Override14 public Predicate toPredicate(Root root, CriteriaQuery>cq, CriteriaBuilder cd) {15 Path usernamePath = root.get("username");16 Predicate p1 = cd.like(usernamePath, "%1%");17 Path emailPath = root.get("email");18 Predicate p2 = cd.like(emailPath, "%2%");19 Path agePath = root.get("age");20 Predicate p3 = cd.ge(agePath, 18);//le 表示小于 ge表示大于21 //多个条件连接起来
22 Predicate p =cd.and(p1, p2, p3);23 returnp;24 }25 };26 //进行排序
27 Sort sort = new Sort(Sort.Direction.ASC,"username");28 //进行分页
29 Pageable page=new PageRequest(0,10,sort);30 //查询数据库
31 Page p =employeeRepository.findAll(spec, page);32 p.forEach(e->{33 System.out.println(e);34 });35 }
Root:查询哪个表(定位到表和字段->用于拿到表中的字段)
* 可以查询和操作的实体的根
* Root接口:代表Criteria查询的根对象,Criteria查询的查询根定义了实体类型,能为将来导航获得想要的结果,它与SQL查询中的FROM子句类似
* Root 相当于from Employee
* Root 相当于from Product
* CriteriaQuery:查询哪些字段,排序是什么(主要是把多个查询的条件连系起来)
* CriteriaBuilder:字段之间是什么关系,如何生成一个查询条件,每一个查询条件都是什么方式
* 主要判断关系(和这个字段是相等,大于,小于like等)
* Predicate(Expression):单独每一条查询条件的详细描述 整个where xxx=xx and yyy=yy ...
方式四:使用jpa-spec插件的前提是要实现JpaSpecificationExecutor接口(我这里是接口继承了接口)
1:在Maven项目中pom.xml引入包
com.github.wenhao
jpa-spec
3.1.1
*
*
2:功能测试:
1 @Test//多个条件查询 +分页+排序
2 public void testSpec() throwsException{3 Specification spec = Specifications.and()4 .like("username","%1%")5 .like("email","%2%")6 .ge("age", 20)7 .build();8 Sort sort = new Sort(Sort.Direction.DESC,"age");//根据年龄排序9 Pageable page = new PageRequest(0,10,sort);10 Page list =employeeRepository.findAll(spec, page);11 list.forEach(e->{12 System.out.println(e);13 });14 }