1:SpringDataJPA是JPA规范的再次封装抽象,底层还是使用了HibernateJPA技术实现,是属于Spring的生成体系中的一部分

2:SpringData的结构(七个接口)

 

 

操作数据库的方式一:继承JpaRepository口后操作数据库

 

  1:在Repository层新建一个基础接口

 

 

 
1 @NoRepositoryBean //告诉JPA不要创建对应接口的bean对象
2 public interface BaseReposittory <T,ID extends Serializable> extends JpaRepository<T,ID>{
3 }

  2:再建一个你所要操作的类型的接口去继承 这里以实体类Employee举例  这里Long是数据库中主键的类型   完成后就已经具备了基础的CRUD 和分页排序的功能

 1 public interface EmployeeRepository extends BaseReposittory<Employee,Long>{ 

  注意:在操作数据库时 添加和修改所使用的都是save()方法 ;可以自行测试   这里测试一个分页排序

1 @Test//分页排序
2     public void pageAndSort() throws Exception{
3         Sort sort = new Sort(Sort.Direction.DESC,"age");
4          Pageable page = new PageRequest(0,10,sort);
5         Page<Employee> employees = employeeRepository.findAll(page);
6         employees.forEach(e->{
7             System.out.println(e);
8         });
9     }

  基础查询和分页排序底层已经定义好可以直接使用 现在我们来自定义查询; 查询方法写在EmployeeRepository

自定义查询

方式一:按照规范创建查询方法,一般按照java驼峰式书写规范加一些特定关键字

  例:  

1  //根据名称模糊查询
2     List<Employee> findByUsernameLike(String username);
3     //根据名称进行查询
4     List<Employee> 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     List<Employee> query02(String name);
7     //根据用户名与邮件进行模糊查询(这里写必需在问号后加顺序)
8     @Query("select e from Employee e where e.username like ?1 and e.email like ?2")
9     List<Employee> 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提供的Criteria API的使用封装,可以用于动态生成Query来满足我们业务中的各种复杂场景。

 

    Spring Data JPA为我们提供了JpaSpecificationExecutor接口,只要简单实现toPredicate方法就可以实现复杂的查询。所有查询都要求传入一个Specification对象

  1:BaseReposittory的操作

@NoRepositoryBean //告诉JPA不要创建对应接口的bean对象
public interface BaseReposittory <T,ID extends Serializable> extends JpaRepository<T,ID>,JpaSpecificationExecutor<T> {
}

 

  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() throws Exception{
11         //先定义规范
12         Specification spec= new Specification<Employee>() {
13             @Override
14             public Predicate toPredicate(Root<Employee> 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                 return p;
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<Employee> 相当于 from Employee
 *             Root<Product> 相当于  from Product
 *        CriteriaQuery:查询哪些字段,排序是什么(主要是把多个查询的条件连系起来)
 *        CriteriaBuilder:字段之间是什么关系,如何生成一个查询条件,每一个查询条件都是什么方式
 *                      主要判断关系(和这个字段是相等,大于,小于like等)
 *        PredicateExpression):单独每一条查询条件的详细描述 整个 where xxx=xx and yyy=yy ...

 

 

方式四:使用jpa-spec插件的前提是要实现JpaSpecificationExecutor接口(我这里是接口继承了接口)

  1:在Maven项目中pom.xml引入包

 

<!--  jpa的SpecificationSpecification功能封装 -->
<dependency>
  <groupId>com.github.wenhao</groupId>
  <artifactId>jpa-spec</artifactId>
  <version>3.1.1</version>
  <!-- 把所有依赖都过滤 -->
  <exclusions>
    <exclusion>
      <groupId>*</groupId>
      <artifactId>*</artifactId>
    </exclusion>
  </exclusions>
</dependency>

  2:功能测试:

 

 1 @Test// 多个条件查询 +分页+排序
 2     public void testSpec() throws Exception{
 3         Specification<Employee> spec = Specifications.<Employee>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<Employee> list = employeeRepository.findAll(spec, page);
11         list.forEach(e->{
12             System.out.println(e);
13         });
14     }