SpringDataJPA的接口学习
前言:本篇文章只是对SpringDataJpa的简单功能做一些整理,比较粗糙。
什么是SpringDateJpa
它是JPA规范的再次封装抽象,底层还是使用了Hibernate的JPA技术实现,引用JPQL的查询语句 ,是属于Spring的生成体系中的一部分。
SpringDataJpa使用起来比较方便,加快了开发的效果,使开发人员不需要关心和配置更多的东西。
SpringDataJpa上手简单,开发效率高,对对象的支持非常好,还十分的灵活。
Spring Data JPA的七个Repository接口:
Repository(org.springframework.data.repository.Repository)
CrudRepository(org.springframework.data.repository.CrudRepository)
PagingAndSortingRepository(org.springframework.data.repository.PagingAndSortingRepository)
JpaRepository (org.springframework.data.jpa.repository.JpaRepository)
QueryByExampleExecutor(org.springframework.data.repository.query.QueryByExampleExecutor)
JpaSpecificationExecutor (org.springframework.data.jpa.repository.JpaSpecificationExecutor)
QueryDslPredicateExecutor (org.springframework.data.querydsl.QueryDslPredicateExecutor)
两大Repository实现类:
SimpleJpaRepository(org.springframework.data.jpa.repository.support.SimpleJpaRepository)
QueryDslJpaRepository(org.springframework.data.jpa.repository.support.QueryDslJpaRepository)
结构图
Repository 接口
Repository 接口是 Spring Data 的一个核心接口,它不提供任何方法,开发者需要在自己定义的接口中声明需要的方法
说明:
User 表示实体类
t_user 表示数据库中表名
简单条件查询
查询某一个实体类或者集合,按照 Spring Data 的规范,查询方法以 find | read | get 开头, 涉及条件查询时,条件的属性用条件关键字连接。要注意的是:条件属性以首字母大写。
简单增删改查
添加:
public void testSave() throws Exception {
Employee employee = new Employee();
employee.setUsername("666");
employee.setAge(66);
employeeRepo.save(employee);
}
删除:
public void testDelete() throws Exception {
employeeRepo.delete(274);
}
修改:
public void testupdate() throws Exception {
Employee employee = new Employee();
employee.setId(274);
employee.setUsername("666");
//修改方法一样用保存,上面给一个id,根据id去查找,找到了就修改,没找到就添加一个
employeeRepo.save(employee);
}
查询一个:
public void testFindOne() throws Exception {
Employee one = employeeRepo.findOne(1);
System.out.println(one);
}
查询所有:
public void testFindAll() throws Exception{
List<Employee> emps = employeeRepository.findAll();
for (Employee emp :emps){
System.out.println(emp);
}
}
Query自定义查询
在实现了JpaRepository的接口里写
//Query注解里面写查询语句(jpql)
@Query("select o from Employee o where username like ?1")
public List<Employee> query(String username);
//Query注解里面写查询语句(sql) 原生写法
@Query(value = "select * from Employee o where o.username like ?1",nativeQuery = true)
public List<Employee> query2(String username);
//测试
//test query
@Test
public void testAnnoQuery() throws Exception {
List<Employee> query = employeeRepo.query("%6%");
System.out.println(query.size());
for (Employee employee : query) {
System.out.println(employee);
}
}
//test Query 原生写法
@Test
public void testAnnoQueryNative() throws Exception {
List<Employee> employees = employeeRepo.query2("%6%");
System.out.println(employees.size());
for (Employee employee : employees) {
System.out.println(employee);
}
}
索引参数与命名参数
1.索引参数如上所示,索引值从1开始,查询中 ?X 个数需要与方法定义的参数个数相一致,并且顺序也要一致
2.命名参数:可以定义好参数名,赋值时采用@Param(“参数名”),而不用管顺序。
根据自己习惯选择
模糊查询
在实现了JpaRepository的接口里写
//根据用户名模糊查询
public List<Employee> findByUsernameLike(String username);
测试
public void testQueryLike() throws Exception {
List<Employee> list = employeeRepo.findByUsernameLike("%6%");
System.err.println(list.size());
for (Employee employee : list) {
System.out.println(employee);
}
}
分页
//分页
@Test
public void testPage() throws Exception {
Pageable pageable = new PageRequest(0, 5);
Page<Employee> all = employeeRepo.findAll(pageable);
for (Employee employee : all) {
System.out.println(employee.getId());
}
}
分页排序
//分页 排序
@Test
public void testPageSort() throws Exception {
//设置排序 两个参数 第一个:设置升降序,根据什么东西排序
Sort sort = new Sort(Sort.Direction.ASC,"id");
//分页加排序 三个参数:第一个起始页,第二个,几条数据一页,第三个排序对象
PageRequest pageRequest = new PageRequest(0, 5, sort);
Page<Employee> all = employeeRepo.findAll(pageRequest);
for (Employee employee : all) {
System.out.println(employee.getId());
}
}
JpaSpecificationExecutor接口
实现这个接口只要简单实现toPredicate方法就可以实现复杂的查询
public void testSpec() throws Exception {
Specification<Employee> specification = new Specification<Employee>() {
@Override
public Predicate toPredicate(Root<Employee> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
Path username = root.get("username");
Path email = root.get("email");
Predicate like1 = criteriaBuilder.like(username, "1%");
Predicate like2 = criteriaBuilder.like(email, "1%");
return criteriaBuilder.and(like1, like2);
}
};
Sort sort = new Sort(Sort.Direction.ASC, "username");
Pageable pageable = new PageRequest(0, 5, sort);
Page<Employee> all = employeeRepo.findAll(specification, pageable);
for (Employee employee : all) {
System.out.println(employee);
}
}
参数解析
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插件
1.兼容Spring Data Jpa 和JPA2.1接口。
2.Equal/NotEqual/Like/NotLike/In/NotIn支持可变参数, Equal/NotEqual 支持空(Null)值。
3.每个条件支持关联查询。
4.支持自定义条件查询。
5.条件构建器。
6.支持分页和排序。
在Maven中引入相应的包
<!-- 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>
测试
@Test
public void testSpecext() throws Exception {
Specification<Employee> specification = Specifications.<Employee>and()
.like("username", "1%")
.like("email", "1%")
.build();
employeeRepo.findAll(specification);
}