Spring Boot总结(5)---数据访问
数据访问是开发中必不可少的模块,Spring Data 是 Spring 用于解决数据访问问题的一揽字解决方案。
Spring Data 使用统一的API对 各种数据库存储技术 提供数据访问操作支持。
Spring Data Commons 让我们在使用数据访问技术时都基于Spring的统一标准。该标准包含CRUD(创建、获取、更新、删除)、查询、排序和分页的相关操作。
Spring Data Repository
Spring Data Commons有一个重要的概念:Spring Data Repository抽象 。使用Spring Data Repository 可以极大的减少数据访问层的代码。因为数据访问操作统一标准,那也必然有定义好的数据访问相关接口。 Spring Data Repository 抽象的根接口为:
Repository接口:
public interface Repository<T, ID extends Serializable>{
}
源码可知,它接受领域类和领域类的id类型作为类型参数
子接口 CrudRepository接口:
public interface CrudRepository<T, ID extends Serializable> extends Repository<T, ID> {
<S extends T> S save(S var1);
<S extends T> Iterable<S> save(Iterable<S> var1);
T findOne(ID var1);
boolean exists(ID var1);
Iterable<T> findAll();
Iterable<T> findAll(Iterable<ID> var1);
long count();
void delete(ID var1);
void delete(T var1);
void delete(Iterable<? extends T> var1);
void deleteAll();
}
CrudRepository的子接口 PagingAndSortingRepository 定义了与分页和排序相关的内容:
public interface PagingAndSortingRepository<T, ID extends Serializable> extends CrudRepository<T, ID> {
Iterable<T> findAll(Sort sort);
Page<T> findAll(Pageable pageable);
}
除此之外,Spring Data项目提供了一个非常强大的功能,可以 根据属性名 实现计数、删除、查询操作,示例如下:
public interface PersonRepository extends CrudRepository<Person,Integer> {
//按照性别计数
Long countBySexy(String sexy);
//按照id删除
void deleteById(int id);
//按照姓名和性别查询
List<Person> findByIdAndName(int id,String name);
}
Spring Data JPA
Hibernate
首先介绍下Hibernate,Hibernate是数据访问解决方案的绝对霸主,使用O/R映射技术实现数据访问。O/R映射即 将领域模型类和数据库的表进行映射,通过程序操作对象而实现表数据操作的能力,让数据访问操作无需关注数据库的相关操作。
JPA
JPA 即Java Persistence API,是一个基于O/R映射的标准规范。规范即只定义标准规则,如注解、接口,而不定义实现。JPA的主要实现有 Hibernate、EclipseLink和OpenJPA等。
Spring Data JPA
Spring Data JPA是Spring Data的一个子项目,它提供基于JPA的Repository,极大地减少了JPA作为数据访问方案的代码量。
JpaRepository接口:
public interface JpaRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
List<T> findAll();
List<T> findAll(Sort var1);
List<T> findAll(Iterable<ID> var1);
<S extends T> List<S> save(Iterable<S> var1);
void flush();
<S extends T> S saveAndFlush(S var1);
void deleteInBatch(Iterable<T> var1);
void deleteAllInBatch();
T getOne(ID var1);
<S extends T> List<S> findAll(Example<S> var1);
<S extends T> List<S> findAll(Example<S> var1, Sort var2);
}
Spring Data JPA 查询方法
1.根据属性名查询
Spring Data JPA 支持通过定义在Repository接口中国年的方法名来定义查询,而方法名是根据实体名来确定的。举例如下:
public interface PersonRepository extends JpaRepository<Person,Integer> {
//按照性别计数
Long countBySexy(String sexy);
//按照id删除
void deleteById(int id);
//按照姓名和性别查询
List<Person> findByIdAndName(int id,String name);
}
可以看出,属性名和关键字的结合即可直接实现sql语句,JPA的关键字如下表:
| Keyword | Sample | JPQL snippet |
|---|---|---|
| And | findByLastnameAndFirstname | … where x.lastname = ?1 and x.firstname = ?2 |
| Or | findByLastnameOrFirstname | … where x.lastname = ?1 or x.firstname = ?2 |
| Is,Equals | findByFirstname,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<Age> ages) | … where x.age in ?1 |
| NotIn | findByAgeNotIn(Collection<Age> 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) |
tips:限制结果数量,使用 top 和 first 关键字实现:
//前10个此名的人
List<Person> findFirst10ByName(String name);
List<Person> findTop10ByName(String name);
2.使用@Query查询
Spring Data JPA提供 @Query 注解关键字来用sql语句实现方法查询,举例如下:
@Query("select p from Person p where p.id=?1")
List<Person> findStudentById(int id);
@Query("select p from Person p where p.id=:stuId")
List<Person> findStudentByStuId(@Param("stuId")int stuId);
3.Specification
JPA提供基于准则查询的方式,即Criteria查询。而Spring Data JPA提供了一个Specification接口构造准则查询,Specification接口定义了一个toPredicate方法来构造查询条件。
示例如下:
//通过Root获得需要查询的属性,通过CriteriaBuilder构造查询条件
public static Specification<Person> personIsWeber(){
return new Specification<Person>() {
@Override
public Predicate toPredicate(Root<Person> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
return criteriaBuilder.equal(root.get("name"),"weber");
}
};
}
4.排序与分页
Spring Data JPA 提供Sort类,Page接口和Pageable接口。
我们在dao层中添加两个使用sort和page的方法:
List<Person> findByName(String name, Sort sort);
Page<Person> findByName(String name, Pageable pageable);
在service层添加方法,调用dao层方法:
@Autowired
PersonRepository personRepository;
public List<Person> findByNameAndSort(String name) {
List<Person> people = personRepository.
findByName(name,new Sort(Sort.Direction.ASC,"name"));
return people;
}
public Page<Person> findBuNameAndPage(String name) {
Page<Person> people = personRepository.
findByName(name,new PageRequest(0,10));//第一个参数为页码,第二个参数为每页行数
return people;
}
Spring Boot中的数据知识就总结到这里,可见其SPring Data JPA提供了非常强大的快速查询方法和实用的分页接口等。下篇总结会结合mysql数据库连接实战项目,熟悉这些知识,实现数据连通。