什麼是JPA
SpringData是Spring提供的一個資料操作架構,而SpringData JPA則是該架構下基于JPA标準進行資料操作的子產品。
SpringData JPA簡化了持久層代碼的操作,隻需編寫接口即可實作。
JPA,全稱Java Persistence API,是Spring Data的子項目之一。它是JDK 5.0的注解或XML描述對象與關系表映射關系的工具,可以将運作時的實體對象持久化到資料庫中。
JPA和Mybatis都是持久層架構,具有相同的功能。然而,由于Mybatis的廣泛使用,現在了解和使用JPA的人較少。
JPQL 是從 Hibernate 的 HQL 演變而來的,其文法與 HQL 非常相似。HQL,即 Hibernate Query Language(Hibernate查詢語言),而 SQL 是 Structure Query Language(結構化查詢語言)。
它們的主要差別在于:SQL 直接操作資料庫中的表和字段,而 HQL 則操作實體對象和屬性。
需要注意的是,我們編寫的 JPQL 最終仍會被轉換成 SQL 語句進行執行。
接口繼承關系
Repository<T, ID>接口 最頂層接口 作用自定義JPQL語句
java複制代碼/**
* 使用@Query注解,自定義JPQL語句
* JPQL語句中,使用的不是表名,而是實體類名,不是列名,而是屬性名,
* 例如SQL語句:select * from user JPQL語句是:select User from User
* 如果是條件查詢,之前語句中的占位符?可以使用(:xxx)進行表示
* 此時xxx會根據方法中同名的形參自動綁定值
*/
public interface UsersRepositoryByQuery extends Repository<User, Integer> {
//如果是查詢所有列,可以省略select ....,從from開始寫
@Query("from User where name=:name")
List<User> selectByName(String name); //select * from user where name=?
@Query("select u from User u where name=:name and age=:age")
List<User> selectByNameAndAge(String name, Integer age); //select * from user where name=? and age=?
@Query("from User where name=:name and age=:age")
List<User> selectByNameLike(String name);//select * from user where name like ?
//除了使用JPQL語句,也是可以使用sql原生語句,在注解中設定參數nativeQuery = true,不推薦!
@Query(value = "select * from user where name=:name",nativeQuery = true)
List<User> selectByNameSQl(String name);//select * from user where name=?
}
CrudRepository接口 繼承了Repository接口,内置類增删改查的方法
PagingAndSortingRepository接口繼承了CrudRepository接口 增加了分頁和排序方法
java複制代碼 @Autowired
private UserRepositoryPage userRepositoryPage;
/**
* 分頁
*/
@Test
void testPage(){
//第一個參數是頁碼數,0表示第一頁;第二參數是分頁機關;
Pageable Pageable = PageRequest.of(0, 2);
Page<User> page = userRepositoryPage.findAll(Pageable);
System.out.println("總資料量"+page.getTotalElements());
System.out.println("總頁數"+page.getTotalPages());
List<User> content = page.getContent();
for (User user : content) {
System.out.println(user);
}
}
/**
* 排序
*/
@Test
void testSort(){
//根據id排序
Sort sort = Sort.by(Sort.Order.desc("id"));
Iterable<User> all = userRepositoryPage.findAll(sort);
for (User user : all) {
System.out.println(user);
}
}
JpaRepository<T, ID> 接口
繼承了 PagingAndSortingRepository<T, ID>
和查詢接口 QueryByExampleExecutor
特點是可以幫助我們将其他接口的方法的傳回值做适配處理。可以使得我們在開發時更友善的使用這些方法
JpaSpecificationExecutor 接口 主要提供了多條件查詢的支援,并且可以在查詢中添加分頁與排序
JpaSpecificationExecutor接口與以上接口沒有關系,完全獨立。 不能單獨使用,需要配合着JPA 中的其他接口一起使用。
java複制代碼//接口
public interface UserRepositoryExJPA extends JpaRepository<User,Integer>,JpaSpecificationExecutor<User> {
}
//使用
@Autowired
private UserRepositoryExJPA userRepositoryExJPA;
/**
* 自定義規則,可以多條件查詢
*/
@Test
void testExJPA2() {
Specification<User> specification = new Specification<User>() {
@Override
public Predicate toPredicate(Root<User> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
//模糊查詢
Predicate predicate = criteriaBuilder.like(root.get("name"), "張%");
//模糊查詢+性别篩選+年齡篩選
Predicate predicate2 = criteriaBuilder.and(criteriaBuilder.like(root.get("name"), "張%"),
criteriaBuilder.equal(root.get("sex"), "男"), criteriaBuilder.gt(root.get("age"), 24));
return predicate2;
}
};
//進行排序年齡進行倒序排列
Sort sort = Sort.by(Sort.Order.desc("age"));
//分頁+追加排序
Pageable pageable = PageRequest.of(0, 2, sort);
Page<User> page = userRepositoryExJPA.findAll(specification, pageable);
System.out.println("根據條件查詢到" + page.getTotalElements() + "條資料");
System.out.println("根據條件查詢到" + page.getTotalPages() + "頁資料");
System.out.println("當頁資料");
for (User user : page) {
System.out.println(user);
}
}
JpaRepositoryImplementation<T, ID> 接口
繼承了 JpaRepository<T, ID>, JpaSpecificationExecutor 接口
實作類為SimpleJpaRepository<T, ID> 接口 功能最強大
關鍵命名查詢
根據 Spring Data 的規範,查詢方法應以 find、read 或 get 開頭(例如 find、findBy、read、readBy、get、getBy)。當涉及到查詢條件時,應使用條件關鍵字連接配接屬性,并確定條件屬性的首字母大寫。在解析方法名時,架構會先去除多餘的字首,然後對剩餘部分進行解析。
你可以直接在接口中定義查詢方法,隻要符合規範,就無需編寫實作或 SQL。目前支援的關鍵字寫法如下: