Spring,springdata jpa框架集成
sssdj:SpringMVC + Spring + SpringDataJpa(JPA规范的再次封装抽象)底层还是使用了Hibernate的JPA技术实现,引用JPQL的查询语句 ,是属于Spring的生成体系中的一部分。
一.新建maven项目,导包
二.创建实体类
Domain实体类对应实体表,抽取各个实体,id自动生成的部分
注意父类需要打上注解告诉jpa不持久化该类
父类:BaseDomain
package cn.itsource.pss.domain;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
@MappedSuperclass
// 在JPA里面就表示是父类,不持久化到表
public class BaseDomain {
@Id
@GeneratedValue
protected Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
子类Employee
@Entity
@Table(name="employee")
public class Employee extends BaseDomain {
private String username;
private String password;
private String email;
private Integer age;
//省略getter,setter与toString(注意:Alt+Insert可以自动生成)
}
三.简单crud
四.分页排序功能
//进行分页功能
//进行分页功能
@Test
public void testPage() {
//1.需要先创建一个page对象(注意:页数是从0开始计算【0就是第1页】)
Pageable pageable = new PageRequest(0, 10);
//2.进行查询
Page<Employee> page = employeeRepository.findAll(pageable);
System.out.println(page.getTotalElements()); //总条数
System.out.println(page.getTotalPages()); //总页数
System.out.println(page.getContent()); //当前页数据
System.out.println(page.getNumber()); //第几页
System.out.println(page.getNumberOfElements()); //当前页有多少个数据
System.out.println(page.getSize()); //每页条数
}
//进行排序功能
@Test
public void testSort() {
//排序 :第一个参数是排序的规则(DESC/ASC) 后面参数是排序的字符
Sort sort = new Sort(Sort.Direction.DESC,"username");
List<Employee> emps = employeeRepository.findAll(sort);
for (Employee emp : emps) {
System.out.println(emp);
}
}
//分页与排序的集成
@Test
public void testPageAndSort() {
//排序 :第一个参数是排序的规则(DESC/ASC) 后面参数是排序的字符
Sort sort = new Sort(Sort.Direction.DESC,"username");
Pageable pageable = new PageRequest(0, 10,sort);
//2.进行查询
Page<Employee> page = employeeRepository.findAll(pageable);
for (Employee employee : page) {
System.out.println(employee);
}
}
@Test
public void testPage() {
//1.需要先创建一个page对象(注意:页数是从0开始计算【0就是第1页】)
Pageable pageable = new PageRequest(0, 10);
//2.进行查询
Page<Employee> page = employeeRepository.findAll(pageable);
System.out.println(page.getTotalElements()); //总条数
System.out.println(page.getTotalPages()); //总页数
System.out.println(page.getContent()); //当前页数据
System.out.println(page.getNumber()); //第几页
System.out.println(page.getNumberOfElements()); //当前页有多少个数据
System.out.println(page.getSize()); //每页条数
}
//进行排序功能
@Test
public void testSort() {
//排序 :第一个参数是排序的规则(DESC/ASC) 后面参数是排序的字符
Sort sort = new Sort(Sort.Direction.DESC,"username");
List<Employee> emps = employeeRepository.findAll(sort);
for (Employee emp : emps) {
System.out.println(emp);
}
}
//分页与排序的集成
@Test
public void testPageAndSort() {
//排序 :第一个参数是排序的规则(DESC/ASC) 后面参数是排序的字符
Sort sort = new Sort(Sort.Direction.DESC,"username");
Pageable pageable = new PageRequest(0, 10,sort);
//2.进行查询
Page<Employee> page = employeeRepository.findAll(pageable);
for (Employee employee : page) {
System.out.println(employee);
}
}
四.根据条件进行查询
按照规范创建查询方法,一般按照java驼峰式书写规范加一些特定关键字,例如我们想通过员工的名来获取到对应的员工的对象。
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
//根据名称模糊查询
List findByUsernameLike(String username);
//根据名称进行查询
List findByUsername(String username);
}
规则参照官网
五.@Query注解查询
原生sql和jpql都支持
//写jpql查询。。
@Query("select o from Employee o where o.age>?1")
List<Employee> query1(int age);
//写原生的sql
@Query(nativeQuery =true,value = "SELECT * FROM employee WHERE email LIKE %1%")
List<Employee> query2(String email);
六.高级查询的功能
要想同时使用高级加分页就得继承
JpaSpecificationExecutor的认识
package org.springframework.data.jpa.repository;
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
public interface JpaSpecificationExecutor<T> {
T findOne(Specification<T> spec);
List<T> findAll(Specification<T> spec);
Page<T> findAll(Specification<T> spec, Pageable pageable);
List<T> findAll(Specification<T> spec, Sort sort);
long count(Specification<T> spec);
}
七.让我们的持久化接口继承JpaSpecificationExecutor
使用方式一 匿名内部类自己实现
Root 获取元素要操作的字段。。
cb对象调方法cb.like(元素, “%1%”)
相当于条件 元素。。Like…?
返回的Predicate 对象相当于高级查询的条件对象
@Test
public void testFind() {
* 非官方理解:
* 查询的时候就需要给一个标准(规范)
* -》 根据规范(这个规范我们可以先简单理解为查询的条件)进行查询
* Root:查询哪个表(定位到表和字段-> 用于拿到表中的字段)
* 可以查询和操作的实体的根
* Root接口:代表Criteria查询的根对象,Criteria查询的查询根定义了实体类型,能为将来导航获得想要的结果,它与SQL查询中的FROM子句类似
* Root<Employee> 相当于 from Employee
* Root<Product> 相当于 from Product
* CriteriaQuery:查询哪些字段,排序是什么(主要是把多个查询的条件连系起来)
* CriteriaBuilder:字段之间是什么关系,如何生成一个查询条件,每一个查询条件都是什么方式
* 主要判断关系(和这个字段是相等,大于,小于like等)
* Predicate(Expression):单独每一条查询条件的详细描述 整个 where xxx=xx and yyy=yy ...
*/
List<Employee> emps = employeeRepository.findAll(
new Specification<Employee>() {
@Override
public Predicate toPredicate(Root<Employee> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
Path path = root.get("username");//拿到要做查询的字段
Predicate p = cb.like(path, "%1%");//like代表做模糊查询,后面就是它的条件值
return p;
}
}
);
for (Employee emp : emps) {
System.out.println(emp);
}
}
@Test
public void testJpaSpecificationExecutor() throws Exception {
List<Employee> list = employeeRepository.findAll(new Specification<Employee>() {
@Override
public Predicate toPredicate(Root<Employee> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
//ROOT 1.相当于得到元素 。。要操作的字段。。age..username。。 root.get("元素")
//cb.like(元素,条件)。。
Path path = root.get("username");
Predicate predicate1 = cb.like(path, "%1%");
Path agepath = root.get("age");
Predicate predicate2 = cb.ge(agepath, 30);
Predicate predicate = cb.and(predicate1, predicate2);
return predicate;
}
});
list.forEach(e-> System.out.println(e));
}
八.方式二使用jpa-spec插件
在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>
九.功能测试
1.单个条件查询
@Test
public void testSpecFind01() {
Specification<Employee> spec = Specifications.<Employee>and().like("username", "%1%").build();
List<Employee> emps = employeeRepository.findAll(spec);
for (Employee emp : emps) {
System.out.println(emp);
}
}
2.多个条件查询
@Test
public void testSpecFind02() {
Specification spec = Specifications.and().like(“username”, “%1%”)
.like(“email”,"%2%").lt(“age”, 20).build();
List emps = employeeRepository.findAll(spec);
for (Employee emp : emps) {
System.out.println(emp);
}
}
3.条件+排序分页功能
//条件集成+分页
@Test
public void testSpecFind03() {
Specification<Employee> spec = Specifications.<Employee>and().like("username", "%1%").build();
//排序 :第一个参数是排序的规则(DESC/ASC) 后面参数是排序的字符
Sort sort = new Sort(Sort.Direction.DESC,"username");
Pageable pageable = new PageRequest(0, 10,sort);
Page<Employee> page = employeeRepository.findAll(spec, pageable);
for (Employee emp : page) {
System.out.println(emp);
}
}
错误总结
。。一般主要是包没导对。。数据库和实体类的字段类型不匹配