1、導(dǎo)入jar包。
org.springframework.boot
spring-boot-starter-data-jpa
2、配置文件
#spring data jpa
spring.jpa.generate-ddl=true
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
3、實體的定義

4、定義Repository接口,繼承Repository接口。
/**
* 1、Repository是一個空接口,即是一個標(biāo)記接口
* 2、若我們定義的接口繼承了Repository,則該接口會被IOC容器識別為一個Repository Bean,納入到IOC容器中,
* 進(jìn)而可以在該接口中定義滿足一些規(guī)范的方法。
*3、實際上,也可以通過@RepositoryDefinition()注解的方式來替代繼承Repository接口
*@RepositoryDefinition(domainClass= Person.class,idClass = Integer.class)
*/
public interfacePersonRepositoryextendsRepository {
Person findByLastName(String lastName);
}
說明:Repository接口中,泛型是對應(yīng)的實體,類型是對應(yīng)實體的主鍵。
5、Repository的子接口。
CrudRepository接口:繼承Repository接口,實現(xiàn)了增刪改查方法。
JpaRepository接口:繼承PagingAndStoringRepository,實現(xiàn)了一組JPA規(guī)范的相關(guān)方法。
PagingAndStoringRepository接口:繼承CrudRepository接口,實現(xiàn)了分頁排序相關(guān)的方法。
SimpleJpaRepository接口:
JpaSpecificationExcutor接口:不屬于Repository體系,實現(xiàn)一組Criteria查詢相關(guān)方法。
6、Repository接口中聲明方法的規(guī)范
1、查詢方法以 find | read | get 開頭;
2、涉及條件查詢時,條件的屬性用條件關(guān)鍵字連接,要注意的是:條件屬性以首字母大寫
例如:定義一個 Entity 實體類?class User{
private String firstName;
private String lastName;?}
使用And條件連接時,應(yīng)這樣寫:?findByLastNameAndFirstName(String lastName,String firstName);?條件的屬性名稱與個數(shù)要與參數(shù)的位置與個數(shù)一一對應(yīng)
3、直接在接口中定義查詢方法,如果是符合規(guī)范的,可以不用寫實現(xiàn),目前支持的關(guān)鍵字寫法如下:


4、支持級聯(lián)查詢
若當(dāng)前類有符合條件的屬性,則優(yōu)先使用,而不使用級聯(lián)屬性。若要使用級聯(lián)屬性,則屬性之間使用下劃線進(jìn)行分割。

使用關(guān)鍵字進(jìn)行查詢例子:
//where lastName like ?%
List findByLastNameStartingWith(String lastName);
//where lastName like ?% and id< ?
List getByLastNameStartingWithAndIdLessThan(String lastName,Integer id);
//where lastName in (?,?) or birth
List findByEmailIOrBirthLessThan(List email, Date birth);
//where a.id>?
List findByAddress_IdGreaterThan(Integer id);
5、@Query注解(查詢)
//查詢Id最大的那個Person(注意:from后面跟著的實體名Person)
//使用@Query注解可以自定義JPQL,語句實現(xiàn)更靈活的查詢
@Query("select p from Person p where p.id=(select max(p2.id) from Person p2)")
Person findMaxIdPerson();;
//為Query注解傳遞參數(shù)方式1:使用占位符(參數(shù)有順序)
@Query("select p from Person p where p.lastName=?1 and p.email=?2")
List testQueryAnnotationParams(String lastName,String email);
//為Query注解傳遞參數(shù)方式2:命名參數(shù)的方式(參數(shù)無順序)
@Query("select p from Person p where p.lastName=:lastName and p.email=:email")
List testQueryAnnotationParams2(@Param("email") String email,@Param("lastName") String lastName);
//Like參數(shù)的傳遞(在占位符上使用%)
@Query("select p from Person p where p.lastName like %?1% or p.email like %?2%")
List testQueryAnnotationLikeParam(String lastName,String email);
//Like參數(shù)的傳遞(在占位符上使用%)
@Query("select p from Person p where p.lastName like %?% or p.email like %?%")
List testQueryAnnotationLikeParam2(@Param("lastName") String lastName,@Param("email ") String email);
//使用原生的SQL注解
@Query(value ="select count(id) from person",nativeQuery =true)
intgetPersonCount();
6、Modifying注解
//可以通過自定義的JPQL完成update和delete操作,注意:JPQL不支持插入語句(insert)
//在Query注解中,編寫JPQL語句,但必須使用@Modiying進(jìn)行修飾,以通知spring data,這是一個update或者是delete
//update或者是delete操作需要使用事物,此時需要定義Service層,在Service層上添加事物操作
//默認(rèn)情況下,springdata的每個方法上都是有事物的,但都是一個只讀事物,他們不能完成修改操作
@Modifying
@Query("update Person p set p.email=?1 where id=?2")
intupdatePersonLastName(String email,Integer id);
Service層的事物:
@Service
public classPersonServiceImplimplementsPersonService {
@Autowired
privatePersonRepositorypersonRepository;
@Override
@Transactional
public intupdateLastName(String email, Integer id) {
intcount=personRepository.updatePersonLastName("dd",1);
returncount;
}
}
7、CrudRepository子接口
public interfacePersonRepositoryextendsCrudRepository
Service接口:
public interfacePersonService {
intupdateLastName(String email,Integer id);
voidsavePersons(List list);
}
Service接口實現(xiàn):
@Service
public classPersonServiceImplimplementsPersonService {
@Autowired
privatePersonRepositorypersonRepository;
@Override
@Transactional
public intupdateLastName(String email, Integer id) {
intcount=personRepository.updatePersonLastName("dd",1);
returncount;
}
@Transactional
@Override
public voidsavePersons(List list) {
personRepository.save(list);
}
}
批量添加測試:
@Test
public voidtestSave() {
List persons =newArrayList<>();
for(inti ='a'; i >='z'; i++) {
Person person =newPerson();
person.setBirth(newDate());
person.setLastName("彩虹"+(char)i);
person.setEmail((char)i+"836908728@qq.com"+(char)i);
person.setId(i +10);
persons.add(person);
}
personService.savePersons(persons);
}
8、PageAndSortingRepository子接口
(是一個只讀操作,不需要事物)
//pageNo的記錄是從1開始
intpageNo =6-1;
intpageSize =5;
//Pageable接口通常使用的其PageRequest實現(xiàn)類,其中封裝了分頁的相關(guān)信息(page,size,sort)
//排序相關(guān),Sort封裝了排序的信息
//Order是針對于某一個屬性進(jìn)行升序還是降序
Order order1=newSort.Order(Direction.DESC,"id");
Order order2=newSort.Order(Direction.ASC,"email");
//sort可以包含多個
Sort sort=newSort(order1,order2);
PageRequest pageable =newPageRequest(pageNo, pageSize,sort);
Page page =personRepository.findAll(pageable);
System.out.println("總記錄數(shù):"+ page.getTotalElements());
System.out.println("當(dāng)前第幾頁:"+ (page.getNumber()+1));
System.out.println("總頁數(shù):"+ page.getTotalPages());
System.out.println("當(dāng)前頁面的list:"+ page.getContent());
System.out.println("當(dāng)前頁面的記錄數(shù):"+ page.getNumberOfElements());
9、JpaRepository接口:是PagingAndSortingRepository的子接口
public interfacePersonRepositoryextendsJpaRepository
@Test
public voidtestJpaRepository() {
Person person =newPerson();
person.setBirth(newDate());
person.setLastName("云南");
person.setEmail("836908728@qq.com");
person.setId(27);
Person person1 =personRepository.saveAndFlush(person);
System.out.println(person == person1);
}
9、JpaSpecificationExecutor接口,不屬于Repository體系
(實現(xiàn)帶查詢條件的分頁)
public interfacePersonRepositoryextendsJpaRepository,JpaSpecificationExecutor
@Test
/**
* 實現(xiàn)帶查詢條件的分頁:
* 使用JpaSpecificationExecutor的PagefindAll(Specificationspec,Pageable pageable)
* Specification:封裝了JPA Criteria查詢的查詢條件
* Pageable:封裝了請求分頁的信息,例如:pageNo,pageSize,Sort
*/
public voidtestJpaSpecificationExecutor(){
intpageNo=3-1;
intpageSize=5;
PageRequest pageRequest=newPageRequest(pageNo,pageSize);
Specification specification=newSpecification() {
/**
*
*@paramroot:代表查詢的實體類
*@paramcriteriaQuery:可以從中得到root對象,即告知JPA Criteria查詢要查詢哪一個實體類,還可以添加查詢條件
*? ? ? ? ? ? ? ? ? ? 還可以結(jié)合EntityManager對象得到最終查詢的TypeQuery對象
*@paramcriteriaBuilder:CriteriaBuilder 用于創(chuàng)建Criteria相關(guān)對象的工廠,當(dāng)然可以從中獲取到Predicate對象
*@returnPredicate類型,代表一個查詢條件
*/
@Override
//如:實現(xiàn)id>5
publicPredicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
Path path=root.get("id");
Predicate predicate=criteriaBuilder.gt(path,5);
returnpredicate;
}
};
Page page=personRepository.findAll(specification,pageRequest);
System.out.println("總記錄數(shù):"+ page.getTotalElements());
System.out.println("當(dāng)前第幾頁:"+ (page.getNumber() +1));
System.out.println("總頁數(shù):"+ page.getTotalPages());
System.out.println("當(dāng)前頁面的list:"+ page.getContent());
System.out.println("當(dāng)前頁面的記錄數(shù):"+ page.getNumberOfElements());
}
10、自定義Repository接口
?步驟:
–定義一個接口: 聲明要添加的, 并自實現(xiàn)的方法
–提供該接口的實現(xiàn)類: 類名需在要聲明的 Repository 后添加 Impl, 并實現(xiàn)方法
–聲明 Repository 接口, 并繼承 1) 聲明的接口
–使用.
–注意: 默認(rèn)情況下, Spring Data 會在 base-package 中查找 "接口名Impl" 作為實現(xiàn)類. 也可以通過 repository-impl-postfix 聲明后綴.
如:定義一個接口:

2、實現(xiàn)接口

3、繼承自定義接口
public interfacePersonRepositoryextendsJpaRepository,JpaSpecificationExecutor,TestRepository