Spring data JPA的简单用法

1、导入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、实体的定义


Spring data JPA的简单用法_第1张图片

4、定义Repository接口,继承Repository接口。

/**

* 1、Repository是一个空接口,即是一个标记接口

* 2、若我们定义的接口继承了Repository,则该接口会被IOC容器识别为一个Repository Bean,纳入到IOC容器中,

* 进而可以在该接口中定义满足一些规范的方法。

*3、实际上,也可以通过@RepositoryDefinition()注解的方式来替代继承Repository接口

*@RepositoryDefinition(domainClass= Person.class,idClass = Integer.class)

*/

public interfacePersonRepositoryextendsRepository {

Person findByLastName(String lastName);

}

说明:Repository接口中,泛型是对应的实体,类型是对应实体的主键。

5、Repository的子接口。

CrudRepository接口:继承Repository接口,实现了增删改查方法。

JpaRepository接口:继承PagingAndStoringRepository,实现了一组JPA规范的相关方法。

PagingAndStoringRepository接口:继承CrudRepository接口,实现了分页排序相关的方法。

SimpleJpaRepository接口:

JpaSpecificationExcutor接口:不属于Repository体系,实现一组Criteria查询相关方法。

6、Repository接口中声明方法的规范

1、查询方法以 find | read | get 开头;

2、涉及条件查询时,条件的属性用条件关键字连接,要注意的是:条件属性以首字母大写

例如:定义一个 Entity 实体类 class User{

private String firstName;

private String lastName; }

使用And条件连接时,应这样写: findByLastNameAndFirstName(String lastName,String firstName); 条件的属性名称与个数要与参数的位置与个数一一对应

3、直接在接口中定义查询方法,如果是符合规范的,可以不用写实现,目前支持的关键字写法如下:


Spring data JPA的简单用法_第2张图片
Spring data JPA的简单用法_第3张图片

4、支持级联查询

若当前类有符合条件的属性,则优先使用,而不使用级联属性。若要使用级联属性,则属性之间使用下划线进行分割。


Spring data JPA的简单用法_第4张图片

使用关键字进行查询例子:

//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,语句实现更灵活的查询

@Query("select p from Person p where p.id=(select max(p2.id) from Person p2)")

Person findMaxIdPerson();;

//为Query注解传递参数方式1:使用占位符(参数有顺序)

@Query("select p from Person p where p.lastName=?1 and p.email=?2")

List testQueryAnnotationParams(String lastName,String email);

//为Query注解传递参数方式2:命名参数的方式(参数无顺序)

@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参数的传递(在占位符上使用%)

@Query("select p from Person p where p.lastName like %?1% or p.email like %?2%")

List testQueryAnnotationLikeParam(String lastName,String email);

//Like参数的传递(在占位符上使用%)

@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进行修饰,以通知spring data,这是一个update或者是delete

//update或者是delete操作需要使用事物,此时需要定义Service层,在Service层上添加事物操作

//默认情况下,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接口实现:

@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+"[email protected]"+(char)i);

person.setId(i +10);

persons.add(person);

}

personService.savePersons(persons);

}

8、PageAndSortingRepository子接口

(是一个只读操作,不需要事物)

//pageNo的记录是从1开始

intpageNo =6-1;

intpageSize =5;

//Pageable接口通常使用的其PageRequest实现类,其中封装了分页的相关信息(page,size,sort)

//排序相关,Sort封装了排序的信息

//Order是针对于某一个属性进行升序还是降序

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("总记录数:"+ page.getTotalElements());

System.out.println("当前第几页:"+ (page.getNumber()+1));

System.out.println("总页数:"+ page.getTotalPages());

System.out.println("当前页面的list:"+ page.getContent());

System.out.println("当前页面的记录数:"+ page.getNumberOfElements());

9、JpaRepository接口:是PagingAndSortingRepository的子接口

public interfacePersonRepositoryextendsJpaRepository

@Test

public voidtestJpaRepository() {

Person person =newPerson();

person.setBirth(newDate());

person.setLastName("云南");

person.setEmail("[email protected]");

person.setId(27);

Person person1 =personRepository.saveAndFlush(person);

System.out.println(person == person1);

}

9、JpaSpecificationExecutor接口,不属于Repository体系

(实现带查询条件的分页)

public interfacePersonRepositoryextendsJpaRepository,JpaSpecificationExecutor

@Test

/**

* 实现带查询条件的分页:

* 使用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查询要查询哪一个实体类,还可以添加查询条件

*                    还可以结合EntityManager对象得到最终查询的TypeQuery对象

*@paramcriteriaBuilder:CriteriaBuilder 用于创建Criteria相关对象的工厂,当然可以从中获取到Predicate对象

*@returnPredicate类型,代表一个查询条件

*/

@Override

//如:实现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("总记录数:"+ page.getTotalElements());

System.out.println("当前第几页:"+ (page.getNumber() +1));

System.out.println("总页数:"+ page.getTotalPages());

System.out.println("当前页面的list:"+ page.getContent());

System.out.println("当前页面的记录数:"+ page.getNumberOfElements());

}

10、自定义Repository接口

•步骤:

–定义一个接口: 声明要添加的, 并自实现的方法

–提供该接口的实现类: 类名需在要声明的 Repository 后添加 Impl, 并实现方法

–声明 Repository 接口, 并继承 1) 声明的接口

–使用.

–注意: 默认情况下, Spring Data 会在 base-package 中查找 "接口名Impl" 作为实现类. 也可以通过 repository-impl-postfix 声明后缀.

如:定义一个接口:


Spring data JPA的简单用法_第5张图片

2、实现接口


Spring data JPA的简单用法_第6张图片

3、继承自定义接口

public interfacePersonRepositoryextendsJpaRepository,JpaSpecificationExecutor,TestRepository

你可能感兴趣的:(Spring data JPA的简单用法)