Spring Boot微服务项目实战(第2版)学习笔记-第3章集成Spring Data JPA

本章主要介绍Spring Data JPA核心接口及继承关系,在Spring Boot中集成Spring Data JPA,以及如何通过Spring Data JPA实现增删改查及自定义查询等内容。

1.Spring Data JPA

本节主要介绍Spring Data JPA是什么、Spring Data JPA核心接口Repository、核心接口间的继承关系图等内容。

1.1 Spring Data JPA介绍

JPA(Java Persistence API)是Sun公司官方提出的Java持久化规范所谓规范是指只定义标准规则,不提供实现,而JPA的主要实现有Hibernate、EclipseLink、OpenJPA等。JPA是一套规范,不是一套产品,Hibernate是一套产品,如果这些产品实现了JPA规范,那么我们可以把它们叫作JPA的实现产品。

Spring Data JPA是Spring Data的一个子项目,它通过提供基于JPA的Respository,极大地减少了JPA作为数据访问方案的代码量。通过Spring Data JPA框架,开发者可以省略实现持久层业务逻辑的工作,唯一要做的,就只是声明持久层的接口,其他都交给Spring Data JPA来帮你完成。

1.2 核心接口Repository

Spring Data JPA的最顶层接口是Repository,该接口是所有Repository类的父类,具体代码如下:

package org.springframework.data.repository;
import java.io.Serializable;
public interface Repository<T,ID extends Serializable> {
}

Repository类下没有任何的接口,只是一个空类。Repository接口的子类有CrudRepository、PagingAndSortingRepository、JpaRepository等。其中CrudRepository类提供了基本的增删改查等接口,PagingAndSortingRepository类提供了基本的分页和排序等接口,而JpaRepository是CrudRepository和PagingAndSortingRepository的子类,继承了它们的所有接口。在真实的项目当中,我们都是通过实现JpaRepository或者其子类进行基本的数据库操作,JpaRepository的具体代码如下:

 @NoRepositoryBean
public interface JpaRepository extends PagingAndSortingRepository<T,ID> {
	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);
}

@NoRepositoryBean:使用该注解标明,此接口不是一个Repository Bean。

1.3 接口继承关系图

Repository接口间的继承关系如图所示。通过该继承图,可以清楚地知道接口间的继承关系。在项目中,一般都是实现JapRepository类,加上自己定义的业务方法,来完成我们的业务开发。

2.集成Spring Data JPA

本节主要介绍如何在Spring Boot中集成Spring Data JPA,服务层类开发,如何通过Spring Data JPA实现基本增删改查功能,以及自定义查询方法等内容。

2.1 引入依赖

在Spring Boot中集成Spring Data JPA,首先需要在pom.xml文件中引入所需的依赖,具体代码如下:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

在之前的章节中,我们已经在开发工具中安装好Maven Helper插件,所以可以通过该插件查看目前引入的所有依赖,具体如图所示。

2.2 继承JpaRepository

在pom.xml文件中引入依赖之后,我们在目录/src/main/java/com.example.demo.repository下开发一个AyUserRepository类,具体代码如下:

public interface AyUserRepository extends JpaRepository<AyUser,String> {
}

与此同时,我们需要在AyUser实体类下添加@Entity和@Id注解,具体代码如下:

@Entity
@Table(name = "ay_user")
public class AyUser {
	//主键
	@Id
	private String id;
	//用户名
	private String name;
	//密码
	private String password;
}
  • @Entity:每个持久化POJO类都是一个实体Bean,通过在类的定义中使用@Entity注解来进行声明。
  • @Table:声明此对象映射到数据库的数据表。该注释不是必需的,如果没有则系统使用默认值(实体的短类名)。
  • @Id:指定表的主键。

2.3 服务层类实现

们在项目继续开发服务层接口类和实现类:AyUserServiceAyUserServiceImpl类,它们分别存放在目录/src/main/java/com.example.demo.service和/src/main/java/com.example.demo.service.impl下。具体代码如下:

public interface AyUserService {
	AyUser findById(String id);
	List<AyUser> findAll();
	AyUser save(AyUser ayUser);
	void delete(String id);
}

接口类AyUserService定义了4个接口,findById和findAll用来查询单个和所有数据,Delete用来删除数据,Save同时具备保存和更新数据的功能。

@Service
public class AyUserServiceImpl implements AyUserService{
	@Resource
	private AyUserRepository ayUserRepository:
	@Override
	public AyUser findById(String id){
		return ayUserRepository.findById(id).get();
	}
	@Override
	public List<AyUser> findAll(){
		return ayUserRepository.findAll()}
	@Override
	public AyUser save(AyUser ayUser) {
		return ayUserRepository.save(ayUser);
	}
	@override
	public void delete(String id){
		ayUserRepository.deleteById(id);
	}
}
  • @Service:Spring Boot会自动扫描到@Component注解的类,并把这些类纳入进Spring容器中管理。也可以用@Component注解,只是@Service注解更能表明该类是服务层类。
  • @Component:泛指组件,当组件不好归类的时候,可以使用这个注解进行标注。
  • @Repository:持久层组件,用于标注数据访问组件,即DAO组件。
  • @Resource:这个注解属于J2EE的,默认按照名称进行装配,名称可以通过name属性进行指定。如果没有指定name属性,当注解写在字段上时,默认取字段名进行查找。如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。具体代码如下:
@Resource(name = "ayUserRepository")
private AyUserRepository ayUserRepository;
  • @Autowired:这个注解是属于Spring的,默认按类型装配。默认情况下要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,如:@Autowired(required=false),如果想使用名称装配可以结合@Qualifier注解进行使用。
@Autowired
@Qualifier("ayUserRepository")
private AyUserRepository ayUserRepository;

2.4 增删改查分页简单实现

上一节,我们已经在服务层类AyUserService中开发完增删改查方法,这一节,我们将继续在类中添加分页接口,具体代码如下:

public interface AyUserService {
	AyUser findById(String id);
	List<AyUser> findAll();
	AyUser save(AyUser ayUser);
	void delete(String id);
	// 分页
	Page<AyUser> findAll(Pageable pageable);
}
  • Pageable:这是一个分页接口,查询时只需要传入一个Pageable接口的实现类,指定pageNumber和PageSize即可。pageNumber为第几页,而PageSize为每页大小。
  • Page:分页查询结果会封装在该类中,Page接口实现Slice接口,通过查看其源代码可知。通过调用getTotalPages和getContent等方法,可以方便获得总页数和查询的记录。Page接口和Slice接口的源代码如下:
public interface Page<T> extends Slice<T>{
	int getTotalPages();
	long getTotalElements();
	<S> Page<S> map(Converter<? super T, ? extends s> var1);
}
public interface Slice<T> extends Iterable<T>{
	int getNumber();
	int getsize();
	int getNumberOfElements();
	List<T> getContent();
	boolean hasContent();
	Sort getSort();
	boolean isFirst();
	boolean isLast();
	boolean hasNext();
	boolean hasPrevious();
	Pageable nextPageable();
	Pageable previousPageable();
	<S> Slice<S> map(Converter<? super T,? extends S> var1);
}

分页方法定义好之后,在类AyUserServiceImpl中实现该方法,具体代码如下:

@Override
public Page<AyUser> findAll(Pageable pageable) {
	return ayUserRepository.findAll(pageable);
}

2.5 自定义查询方法

我们除了使用JpaRepository接口提供的增删改查分页等方法之外,还可以自定义查询方法。下面在AyUserRepository类中添加几个自定义查询方法,具体代码如下:

public interface AyUserRepository extends JpaRepository<AyUser,String> {
	List<AyUser> findByName(String name);
	List<AyUser> findByNameLike(String name);
	List<AyUser> findByIdIn(Collenction<String> ids);
}

在AyUserRepository中,我们自定义了3个查询的方法。从代码可以看出,Spring Data JPA为我们约定了一系列的规范,只要按照规范编写代码,Spring Data JPA就会根据代码翻译成相关的SQL语句,进行数据库查询。比如,可以使用findBy、Like、In等关键字,其中findBy可以用read、readBy、query、queryBy、get、getBy来代替。关于查询关键字的更多内容,可以到官方网站查看,里面有详细的内容介绍,这里就不一一列举了。

AyUserRepository类中自定义查询方法开发完成之后,可分别在类AyUserService和类AyUserServiceImpl中调用它们。

在AyUserService类中继续添加这3个方法,具体代码如下:

List<AyUser> findByName(String name);
List<AyUser> findByNameLike(String name);
List<AyUser> findByIdIn(Collenction<String> ids);

在AyUserServiceImpl类中添加这3个方法,具体代码如下:

@Override
public List<AyUser> findByName(String name){
	return ayUserRepository.findByName(name);
}
@Override
public List<AyUser> findByNameLike(String name){
	return ayUserRepository.findByNameLike(name);
}
@Override
public List<AyUser> findByIdIn(Collenction<String> ids){
	return ayUserRepository.findByIdIn(ids);
}

Tips:@Override注解不可去掉,它可以帮助校验接口方法是否被误改。

3.集成测试

3.1 测试用例开发

我们在测试类MySpringBootApplicationTests中添加如下代码:

@Resource
private AyUserService ayUserService;

@Test
public void testRepository(){
	//查询所有数据
	List<AyUser> userList = ayUserService. findAll();
	System.out.printIn("findAll:"+ userList.size());
	//通过name查询数据
	list<AyUser> userList2 = ayUserService.findByName("阿毅");
	System.out.printIn("findByName():"+ userList2.size();
	Assert.isTrue(userList2.get(0).getName().equals"阿毅"),"data error!");
	//通过name模糊查询数据
	list<AyUser> userList3 = ayUserService.findByNameLike("%毅%");
	System.out.printIn("findByNameLike):"+ userList3.size());
	Assert.isTrue(userList3.get(0).getName().equals("阿毅"),"data error!");
	//通过ID列表查询数据
	List<String> ids = new ArrayList<String>();
	ids.add("1");
	ids.add("2");
	List<AyUser> userList4 = ayUserSer.findByIdIn(ids);
	System.out.printIn("findByIdIn():" userList4.size());
	//分页查询数据
	PageRequest pageRequest = new PageRequest(0, 10):
	page<AyUser> userList5 = ayuserService.findAll(pageRequest);
	System.out.printIn("page findAll):"+ userList5.getTotalPages()+"/"+userList5. getSize());
	//新增数据
	AyUser ayuser = new AyUser();
	ayUser.setId("3");
	ayUser.setName("test");
	ayUser.setPassword("123");
	ayUserService.save(ayUser);
	//删除数据
	ayUserService.delete("3");
}

Assert:添加Assert断言,在软件开发中是一种常用的调试方式。从理论上来说,通过Assert断言方式可以证明程序的正确性,在现在项目中被广泛使用,这是需要掌握的基本知识。Assert提供了很多好用的方法,比如isNull和isTrue等。

3.2 测试

通过运行3.1节中的单元测试用例,我们可以在控制台看到如下的打印信息:

findAll():2
findByName():1
findByNameLike():1
findByIdIn():2
page findAll():1/10

通过上面的打印信息,可以看出Spring Boot集成Spring Data JPA已经成功,同时代码中的所有Assert断言都全部通过,说明增删改查分页以及自定义查询方法都可以正常运行。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值