一、使用Spring Data Repositories
Spring Data JPA为Java Persistence API(JPA)提供了支持。它简化了需要访问JPA数据源的应用程序的开发。
Spring Data的中央接口是Repository。它将实体类以及实体类的ID类型作为参数进行管理。此接口主要用作标记接口,捕获要使用的类型,并帮助扩展。
CrudRepository为管理的实体类提供复杂的CRUD功能:
public interface CrudRepository<T, ID extends Serializable>
extends Repository<T, ID> {
<S extends T> S save(S entity);
Optional<T> findById(ID primaryKey);
Iterable<T> findAll();
long count();
void delete(T entity);
boolean existsById(ID primaryKey);
// … more functionality omitted.
}
PagingAndSortingRepository添加了额外的方法来简化对实体的分页访问:
public interface PagingAndSortingRepository<T, ID extends Serializable>
extends CrudRepository<T, ID> {
Iterable<T> findAll(Sort sort);
Page<T> findAll(Pageable pageable);
}
- 声明扩展Repository或其子接口之一的接口,并将其键入它应处理的域类和ID类型,如以下示例所示:
interface PersonRepository extends Repository<Person, Long> { … }
- 在接口上声明查询方法。
interface PersonRepository extends Repository<Person, Long> {
List<Person> findByLastname(String lastname);
}
设置Spring以使用JavaConfig或XML配置为这些接口创建代理实例。
注入实例并使用它。要访问User页面大小为20 的第二页,可以执行以下操作:
PagingAndSortingRepository<User, Long> repository = // … get access to a bean
Page<User> users = repository.findAll(PageRequest.of(1, 20));
二、查询创建
构建到Spring Data存储库基础结构中的查询构建器机制对于构建对存储库实体的约束查询很有用。该机制条前缀find…By,read…By,query…By,count…By,和get…By从所述方法和开始分析它的其余部分。introduction子句可以包含其他表达式,例如Distinct在要创建的查询上设置不同的标志。但是,第一个By用作分隔符以指示实际条件的开始。在最基本的层面上,您可以在实体属性上定义条件,并将它们与And和它们连接起来Or。
interface PersonRepository extends Repository<User, Long> {
List<Person> findByEmailAddressAndLastname(EmailAddress emailAddress, String lastname);
// Enables the distinct flag for the query
List<Person> findDistinctPeopleByLastnameOrFirstname(String lastname, String firstname);
List<Person> findPeopleDistinctByLastnameOrFirstname(String lastname, String firstname);
// Enabling ignoring case for an individual property
List<Person> findByLastnameIgnoreCase(String lastname);
// Enabling ignoring case for all suitable properties
List<Person> findByLastnameAndFirstnameAllIgnoreCase(String lastname, String firstname);
// Enabling static ORDER BY for a query
List<Person> findByLastnameOrderByFirstnameAsc(String lastname);
List<Person> findByLastnameOrderByFirstnameDesc(String lastname);
}
三、特殊参数处理
要处理查询中的参数,请定义方法参数,如前面示例中所示。除此之外,基础设施承认某些特定的类型,如Pageable和Sort,动态地应用分页和排序,以查询。
Page<User> findByLastname(String lastname, Pageable pageable);
Slice<User> findByLastname(String lastname, Pageable pageable);
List<User> findByLastname(String lastname, Sort sort);
List<User> findByLastname(String lastname, Pageable pageable);
四、限制查询结果
查询方法的结果可以通过使用first或top关键字来限制,这些关键字可以互换使用。可以附加一个可选的数值,top或者first指定要返回的最大结果大小。如果省略该数字,则假定结果大小为1。
User findFirstByOrderByLastnameAsc();
User findTopByOrderByAgeDesc();
Page<User> queryFirst10ByLastname(String lastname, Pageable pageable);
Slice<User> findTop3ByLastname(String lastname, Pageable pageable);
List<User> findFirst10ByLastname(String lastname, Sort sort);
List<User> findTop10ByLastname(String lastname, Pageable pageable);
五、流式查询结果
可以使用Java 8 Stream
@Query("select u from User u")
Stream<User> findAllByCustomQueryAndStream();
Stream<User> readAllByFirstnameNotNull();
@Query("select u from User u")
Stream<User> streamAllPaged(Pageable pageable);
六、保存实体-实体状态检测策略
Spring Data JPA提供以下策略来检测实体是否是新实体:
1、Id-Property检查(默认):默认情况下,Spring Data JPA检查给定实体的identifier属性。如果标识符属性为null,则假定该实体是新的。否则,它被认为不是新的。
2、实现Persistable:如果实体实现Persistable,Spring Data JPA会将新检测委托给isNew(…)实体的方法。
3、实现EntityInformation:通过创建相应的方法的子类并重写该方法来自定义实现EntityInformation。
七、运用@Query
```
public interface UserRepository extends JpaRepository<User, Long> {
// 参数查询
@Query(“select u from User u where u.emailAddress = ?1”)
User findByEmailAddress(String emailAddress);
// 使用like
@Query(“select u from User u where u.firstname like %?1”)
List
// 本地查询,使用原生sql
@Query(value = “SELECT * FROM USERS WHERE EMAIL_ADDRESS = ?1”, nativeQuery = true)
User findByEmailAddress(String emailAddress);
// 排序
@Query(“select u from User u where u.lastname like ?1%”)
List
// 命名参数
@Query(“select u from User u where u.firstname = :firstname or u.lastname = :lastname”)
User findByLastnameOrFirstname(@Param(“lastname”) String lastname,
@Param(“firstname”) String firstname);
// 使用SpEL表达式
// 它插入entityName与给定存储库关联的域类型。
// 如果域类型已设置的name属性@Entity的注释,它被使用。否则,使用域类型的简单类名。
@Query(“select u from #