二八佳人体似酥,腰间仗剑斩愚夫。虽然不见人头落,暗里教君骨髓枯。

上一章简单介绍了SpringBoot整合JdbcTemplate(五),如果没有看过,请观看上一章

日常生活中,我们并不使用 JdbcTemplate, 而是使用 JPA和MyBatis,MyBatis-Plus. 这一章节,我们讲解一下, JPA的相关操作。

一. SpringBoot 整合 JPA前期准备

按照老蝴蝶以前讲解的方式,采用Maven 构建SpringBoot项目。

一.一 pom.xml 添加依赖

 <!--引入MySql的驱动-->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId>
</dependency>
<!--引入springboot与jpa整合的依赖-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

一.二 application.yml 添加JPA的配置

# 引入 数据库的相关配置
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/springboot?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8&useSSL=falseusername: rootpassword: abc123# JPA的相关配置jpa:# 设置数据库平台database-platform: org.hibernate.dialect.MySQLDialect# 设置数据库database: mysql# 是否展示SQL语句show-sql: truehibernate:# 持久化规则是 updateddl-auto: updatenaming:# 物理命名策略类的全限定名称physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

一.三 创建 User 表

DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(15) DEFAULT NULL,`sex` varchar(20) DEFAULT NULL,`age` int(6) DEFAULT NULL,`description` varchar(50) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8;

二. 整合JPA应用

SpringBoot整合JPA时,需要创建相应的 实体类,工厂接口。

工厂接口有 Crud接口,有 PagingAndSorting,有 Jpa接口,也有 Specification 动态查询接口。

每一种接口,都有其特殊的功能。

二.一 创建 POJO 类和业务类

在 pojo 包下,创建 User.java 类

@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "user")
@Entity
public class User implements Serializable {/*** @param id id编号* @param name 姓名* @param sex 性别* @param age 年龄* @param description 描述*/@Id//指定生成策略@GeneratedValue(strategy=GenerationType.IDENTITY)private Integer id;@Column(name = "name")private String name;@Column(name="sex")private String sex;@Column(name="age")private Integer age;@Column(name="description")private String description;
}

在 service包下,创建相应的接口和实现类

public interface UserService {}
@Service
public class UserServiceImpl implements UserService {}

二.二 Crud 工厂接口

二.二.一 接口的相关定义

org.springframework.data.repository.CrudRepository

@NoRepositoryBean
public interface CrudRepository<T, ID> extends Repository<T, ID> {}
方法签名 方法解释
<S extends T> S save(S entity); 插入或者更新一个对象
<S extends T> Iterable<S> saveAll(Iterable<S> entities); 插入或者更新多个对象,批量操作
Optional findById(ID id); 根据id 查询对象
boolean existsById(ID id); 是否存在此id的记录
Iterable findAll(); 查询所有的记录
Iterable findAllById(Iterable ids); 根据id集合查询相关的记录
long count(); 统计数目
void deleteById(ID id); 根据id进行删除
void delete(T entity); 根据实体对象进行删除
void deleteAll(Iterable<? extends T> entities); 根据实体对象集合进行删除,批量操作
void deleteAll(); 删除所有的记录

二.二.二. Crud 接口实现

在 repository 包下,创建 UserCrudRepository 接口。

public interface UserCrudRepository extends CrudRepository<User,Integer> {}

二.二.三 Crud 测试

在 test测试目录下,创建对应的测试类和测试方法,进行测试。

@SpringBootTest
@Log4j2
public class CrudRepositoryTests {@Autowiredprivate UserService userService;
}

二.二.三.一 插入 save 方法

测试方法:

  @Testpublic void addTest(){//1. 构建对象User user=new User();user.setName("欢欢");user.setAge(22);user.setSex("女");user.setDescription("一个非常可爱的女孩纸");//2. 添加方法userService.addUser(user);log.info("添加成功,{}",user);}

省略接口方法,其对应的实现方法

添加Crud接口注入

@Autowired
private UserCrudRepository userCrudRepository;
@Overridepublic void addUser(User user) {userCrudRepository.save(user);}

控制台打印输出:

二.二.三.二 更新 save 方法

测试方法

   @Testpublic void updateTest(){//1. 构建对象User user=new User();user.setId(1); //id不存在,会添加user.setName("欢欢");user.setDescription("岳泽霖最好的朋友");//2. 修改方法userService.updateUser(user);log.info("修改成功,{}",user);}

接口实现方法

 @Overridepublic void updateUser(User user) {userCrudRepository.save(user);}

控制台打印输出

先查询,发现有,就更新,如果没有的话,就插入。

二.二.三.三 删除 delete 方法

测试方法

  @Testpublic void deleteTest(){userService.deleteUser(1);}

接口实现方法

 @Overridepublic void deleteUser(Integer id) {userCrudRepository.deleteById(id);}

数据库里面,没有此条数据了。

二.二.三.四 批量更新数据 saveAll

重新执行一下, save() 方法,插入一条数据, id=2.

测试方法:

   @Testpublic void batchAddTest(){//1. 构建对象User user=new User();user.setName("小欢欢");user.setAge(22);user.setSex("女");user.setDescription("一个小坏蛋");User user1=new User();user1.setName("小泽霖");user1.setAge(25);user1.setSex("男");user1.setDescription("一个大坏蛋");//这是修改的操作,id=2已经存在这条记录了。User user2=new User();user2.setName("岳泽霖");user2.setId(2);user2.setAge(25);user2.setSex("男性");user2.setDescription("一个快乐的程序员");//2. 放置到集合里面List<User> userList=new ArrayList<>();userList.add(user);userList.add(user1);userList.add(user2);userService.batchAddUser(userList);}

接口实现方法:

 @Overridepublic void batchAddUser(List<User> userList) {userCrudRepository.saveAll(userList);}

会插入前两条,更新第三条记录。

二.二.三.五 根据id 进行查询 findById

 @Testpublic void findByIdTest(){User user=userService.findById(3);log.info(user);}

接口实现方法

  @Overridepublic User findById(Integer id) {Optional<User> optional= userCrudRepository.findById(id);if(optional.isPresent()){return optional.get();}return null;}

二.二.三.六 查询所有的数据 findAll

  @Testpublic void findAllTest(){List<User> userList=userService.findAll();userList.forEach(n->log.info(n));}

接口实现方法

  @Overridepublic List<User> findAll() {Iterable<User> iterator= userCrudRepository.findAll();List<User> userList=new ArrayList<>();//将 Iterable 转换成 listiterator.forEach(n->userList.add(n));return userList;}

二.二.三.七 根据id集合进行查询 findAllById

 @Testpublic void findByIdsTest(){List<Integer> ids= Arrays.asList(3,4,6);List<User> userList=userService.findAllByIds(ids);userList.forEach(n->log.info(n));}

接口实现方法

   @Overridepublic List<User> findAllByIds(List<Integer> ids) {Iterable<User> iterator= userCrudRepository.findAllById(ids);List<User> userList=new ArrayList<>();iterator.forEach(n->userList.add(n));return userList;}

二.二.三.八 查询数目 count

 @Testpublic void countTest(){Long count=userService.count();log.info("总数目{}",count);}

接口实现方法

 @Overridepublic Long count() {return userCrudRepository.count();}

这就是 Crud仓库接口的基本用法。

二.三 PagingAndSorting 工厂接口

二.三.一 接口的相关定义

org.springframework.data.repository.PagingAndSortingRepository

分页和排序的接口,继承了 Crud的接口。

@NoRepositoryBean
public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> {Iterable<T> findAll(Sort sort);Page<T> findAll(Pageable pageable);
}
方法签名 方法解释
Iterable findAll(Sort sort); 排序
Page findAll(Pageable pageable); 分页

二.三.二 PagingAndSorting 接口实现

在 repository 包下,创建 UserPagingAndSortingRepository 接口

public interface UserPagingAndSortingRepository extends PagingAndSortingRepository<User,Integer> {}

二.三.三 PagingAndSorting 测试

在 test目录下,创建 PagingAndSortingRepositoryTests 测试类和测试方法。

多添加几条数据,好便于分页和排序。

二.三.三.一 排序,按照性别和年龄

 @Autowiredprivate UserPagingAndSortingRepository userPagingAndSortingRepository;@Testpublic void sortTest(){List<User> userList=userService.findAllOrderBySexAndAge();userList.forEach(n->log.info(n));}

业务接口方法

 @Overridepublic List<User> findAllOrderBySexAndAge() {Sort.Order sort1= Sort.Order.desc("sex");Sort.Order sort2 = Sort.Order.asc("age");Sort sort=Sort.by(sort1,sort2);Iterable<User> userIterable=userPagingAndSortingRepository.findAll(sort);List<User> userList=new ArrayList<>();userIterable.forEach(n->userList.add(n));return userList;}

二.三.三.二 排序并分页

  @Testpublic void pageTest(){Page<User> page=userService.pageAll();log.info("总页数:{}",page.getTotalPages());log.info("总的数目:{}",page.getTotalElements());log.info("当前页数:{}",page.getNumber()+1);log.info("当前页的数目:{}",page.getNumberOfElements());List<User> userList= page.getContent();userList.forEach(n->log.info(n));}

业务接口方法

@Overridepublic Page<User> pageAll() {Sort sort=Sort.by(Sort.Direction.DESC,"id");// 默认从0开始的Pageable pageable= PageRequest.of(2-1, 4, sort);Page<User> userPage=userPagingAndSortingRepository.findAll(pageable);return userPage;}

这就是 PageAndSorting仓库接口的基本用法。

二.四 JpaRepository 工厂接口

二.四.一接口的相关定义

@NoRepositoryBean
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {}

继承了分页,还有一个查询的接口。

方法签名 方法解释
List findAll(); 查询所有,返回对象集合
List findAll(Sort sort); 查询所有,可排序,返回对象集合
List findAllById(Iterable ids); 根据id集合,查询所有的记录,返回对象集合
<S extends T> List*lt;S> saveAll(Iterable<S> entities); 批量保存数据
void flush(); 刷新缓存
S saveAndFlush(S entity); 保存并刷新
void deleteInBatch(Iterable entities); 根据对象集合
void deleteAllInBatch(); 批量删除所有
T getOne(ID id); 根据id查询当前对象,如果没有的话,返回null
<S extends T> List<S> findAll(Example<S> example); 根据条件,查询数据,返回对象集合
<S extends T> List<S> findAll(Example<S> example, Sort sort); 根据条件,支持排序,查询数据,返回对象集合

二.四.二 Jpa 接口实现

在repository包下,创建 UserJpaRepository 接口。 通常使用的是这个Jpa的接口,会在这接口内添加相应的接口定义。

当接口的方法名称定义符合相应的规范的时候,不用写相应的实现,Jpa会帮我们自动匹配生成相应的sql语句。

public interface UserJpaRepository extends JpaRepository<User,Integer> {}

二.四.三 JPA测试

在test目录下,创建JpaRepositoryTests 进行测试。

二.四.三.一 查询全部

 @Testpublic void findAllTest(){List<User> userList=userService.jpaFindAll();userList.forEach(n->log.info(n));}

业务方法

@Autowiredprivate UserJpaRepository userJpaRepository;@Overridepublic List<User> jpaFindAll() {return userJpaRepository.findAll();}

不用往 UserJpaRepository 添加方法。

二.四.三.二 Example 查询 (通常不用)

测试方法

@Testpublic void findByExampleTest(){User user=new User();user.setName("泽霖");user.setAge(25);user.setSex("男");//1.创建匹配器ExampleMatcher exampleMatcher=ExampleMatcher.matching().withMatcher("sex",matcher -> matcher.contains()).withMatcher("age",matcher -> matcher.exact()).withMatcher("name",matcher ->matcher.contains());//2. 生成Example 对象Example example=Example.of(user,exampleMatcher);//3. 进行查询List<User>userList=userService.findByExample(example);userList.forEach(n->log.info(n));}

业务实现接口

 @Overridepublic List<User> findByExample(Example example) {return userJpaRepository.findAll(example);}

不用往 UserJpaRepository 添加方法。

二.四.三.三 根据名称进行查询

 @Testpublic void findByNameTest(){List<User> userList=userService.findByName("小欢欢");userList.forEach(n->log.info(n));}

业务方法

 @Overridepublic List<User> findByName(String name) {return userJpaRepository.findByName(name);}

需要往 UserJpaRepository 里面添加方法,需要符合一定的规则

 List<User> findByName(String name);

二.四.三.四 根据性别和年龄

@Testpublic void findBySexAndAgeTest(){List<User> userList=userService.findBySexAndAge("男",25);userList.forEach(n->log.info(n));}

业务方法

@Overridepublic List<User> findBySexAndAge(String sex, Integer age) {return userJpaRepository.findBySexAndAge(sex,age);}

需要往 UserJpaRepository 里面添加方法,需要符合一定的规则

List<User> findBySexAndAge(String sex, Integer age);

二.四.三.五 根据性别查询,年龄排序

 @Testpublic void findAllOrderByTest(){List<User> userList=userService.findBySexOrderByAge("女");userList.forEach(n->log.info(n));}

业务方法

  @Overridepublic List<User> findBySexOrderByAge(String sex) {return userJpaRepository.findBySexOrderByAgeDesc(sex);}

需要往 UserJpaRepository 里面添加方法,需要符合一定的规则

List<User> findBySexOrderByAgeDesc(String sex);

二.四.三.六 使用原始SQL进行查询部分字段

 @Testpublic void findQueryNameTest(){List<Map<String,Object>> userMapList=userService.findQueryByName("小欢欢");for(Map<String,Object> map:userMapList){log.info("id是:{},name是{}",map.get("id"),map.get("name"));}}

业务方法

 @Overridepublic  List<Map<String,Object>> findQueryByName(String name) {return userJpaRepository.findQueryByName(name);}

需要往 UserJpaRepository 里面添加方法,需要符合一定的规则

@Query(value="select id as id,name as name from user where name=:name",nativeQuery = true)List<Map<String,Object>> findQueryByName(@Param("name") String name);

二.四.三.七 使用原始SQL进行查询全部字段

 @Testpublic void findQueryNameTest(){List<Map<String,Object>> userMapList=userService.findQueryByName("小欢欢");for(Map<String,Object> map:userMapList){log.info("id是:{},name是{}",map.get("id"),map.get("name"));}}

业务方法

 @Overridepublic List<User> jpaFindAllSql(String name) {return userJpaRepository.findAllSql(name);}

需要往 UserJpaRepository 里面添加方法,需要符合一定的规则

  @Query(value="select * from user where name=:name",nativeQuery = true)List<User> findAllSql(@Param("name")String name);

这就是 jpa的一些基本的用法。

二.五 JpaSpecificationExecutor 动态查询接口

二.五.一 接口的相关定义

public interface JpaSpecificationExecutor<T> {}
方法签名 方法解释
Optional findOne(@Nullable Specification spec); 根据条件,查询最多只有一条记录
List findAll(@Nullable Specification spec); 根据条件,查询多条记录
Page findAll(@Nullable Specification spec, Pageable pageable); 根据条件,分页查询,可包含排序
List findAll(@Nullable Specification spec, Sort sort); 根据条件,排序查询
long count(@Nullable Specification spec); 查询数目

二.五.二. JpaSpecificationExecutor实现

通常都是与 JpaRepository 一起使用的。

public interface UserSpecificationRepository extends JpaRepository<User, Integer>,JpaSpecificationExecutor<User>{}

二.五.三 Specification 动态查询测试

 @Testpublic void nameAndSexAndDescTest(){User user=new User();user.setName("小欢欢1");user.setSex("女");user.setAge(27);user.setDescription("小坏蛋");List<User> userList=userService.findByNameSexAndDesc(user);userList.forEach(n->log.info(n));}

业务接口方法

@Overridepublic List<User> findByNameSexAndDesc(User user) {//1. 根据条件创建 Specification 对象信息Specification<User> specification=new Specification<User>(){@Overridepublic Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {//1. 用于接收封装的查询对象List<Predicate> predicateList = new ArrayList<>();if(user!=null){//1.如果name 不为空的话,对name 进行精确匹配if(!StringUtils.isEmpty(user.getName())){Predicate namePredicate = criteriaBuilder.equal(root.get("name"), user.getName());predicateList.add(namePredicate);}//2.如果sex 不为空的话,也是精确匹配if(!StringUtils.isEmpty(user.getSex())){Predicate sexPredicate=criteriaBuilder.equal(root.get("sex"),user.getSex());predicateList.add(sexPredicate);}//3.如果age不为空的话,就是 < 匹配if(!StringUtils.isEmpty(user.getAge())){Predicate agePreDicate=criteriaBuilder.lt(root.get("age"),user.getAge());predicateList.add(agePreDicate);}//4. 如果description 不为空的话,进行模糊匹配if(!StringUtils.isEmpty(user.getDescription())){Predicate descPredicate=criteriaBuilder.like(root.get("description"),"%"+user.getDescription()+"%");predicateList.add(descPredicate);}}return criteriaBuilder.and(predicateList.toArray(new Predicate[predicateList.size()]));}};//传入条件,也可以传入分页信息。这儿就不举例分页了。return userSpecificationRepository.findAll(specification);}

如果将 user条件的属性全部去掉,是一种sql查询,sex去掉,又是一种sql查询,会根据属性的不同,动态的处理。

动态查询,也可以传入分页和排序的相关信息。
这个非常重要,需要重点掌握一下。

本章节的代码放置在 github 上:

https://github.com/yuejianli/springboot/tree/develop/Jpa

谢谢您的观看,如果喜欢,请关注我,再次感谢 !!!

SpringBoot整合JPA(六)相关推荐

  1. (二)SpringBoot 整合 JPA

    一.JPA简介 JPA(java persistence api)并不是一个框架,而是一组规范.Hibernate.TopLink.OpenJPA都实现了JPA规范,不过Hinernate最成功).所 ...

  2. Springboot整合JPA多数据源(Oracle+Mysql)

    Springboot整合JPA多数据源 1. Maven 2. 基本配置 2.1 DataSource 3. 多数据源配置 3.1 JpaConfigOracle 3.2 JpaConfigMysql ...

  3. Springboot整合JPA

    文章目录 JPA技术 常用注解 Springboot整合JPA 1.引入JPA依赖 2.配置 3.启动类 4.实体类 5.定义接口和数据库交互(dao) 6.JPA中使用原生态的SQL语句 7.Tes ...

  4. springboot整合JPA+MYSQL+queryDSL数据增删改查

    Spring Boot Jpa 是 Spring 基于 ORM 框架.Jpa 规范的基础上封装的一套 Jpa 应用框架,可使开发者用极简的代码即可实现对数据的访问和操作.它提供了包括增删改查等在内的常 ...

  5. SpringBoot整合JPA 数据库自动增加字段问题记录

    Spring整合JPA启动的时候忽然发现,数据增加了两个字段,我当时就很纳闷了,我自己写的有实体有字段,并且跟数据一致,为什么要给我增加两个字段哪? 我的实体如下: 启动的时候就变成这样了 然后就找度 ...

  6. springboot整合jpa+h2

    JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中. JPA的主要目标之一 ...

  7. 【idea】Springboot整合jpa

    第一步快速搭建springboot项目:在你建立的工程下创建 Module 选择Spring initializr创建. 第二步:修改包名.项目名.web项目打成war包.在Type处选择: Mave ...

  8. java版spring cloud+spring boot+redis社交电子商务平台(四)SpringBoot 整合JPA

    java b2b2c电子商务社交平台源码请加企鹅求求:一零三八七七四六二六.JPA全称Java Persistence API.JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行 ...

  9. springboot整合jpa之连接MySql实现crud

    整体思路:搭建springboot一定要注意版本问题,各个jar包之间是否兼容.搭建可以从上往下进行,是一个从Controller层和Service层-->Dao层的一个过程. 1.添加mave ...

  10. 七十三、SpringBoot整合Jpa

    @Author:Runsen 来源:尚硅谷 下面建议读者学习尚硅谷的B站的SpringBoot视频,我是学雷丰阳视频入门的. 具体链接如下:B站尚硅谷SpringBoot教程 这里需要注意的是:jpa ...

最新文章

  1. 从源码分析DEARGUI之add_slider_float-4和add_slider_int-4
  2. java文件复制速度_java中文件复制得速度测试
  3. 【PhotoScan精品教程】任务一:新建工程、导入照片、设置坐标系、导入控制点(POS)、自由空三
  4. 【入门5】字符串(今天刷洛谷了嘛)
  5. pb string 接收dll按值返回_JavaScript 是如何工作的:JavaScript 的共享传递和按值传递...
  6. SpringBoot项目集成Mybatis Plus(三)分页插件
  7. Java中url传递中文参数取值乱码的解决方法
  8. ionic Toggle(开关控件)
  9. requestIdleCallback函数
  10. jqGrid获取数据库数据的方式
  11. java json 多余属性,fastjson支持JSON字符串解析到指定类型的JavaBean时的多余属性么?...
  12. 从ISO 文件制作U盘启动盘.
  13. Hadoop组件及功能
  14. 元器件的温度特性(电容、电感、晶振等)
  15. 实战1 - 空气质量数据的校准
  16. 电驴提示“该内容尚未提供权利证明,无法提供下载”之解决办法
  17. c语言比率分布 函数 rate(m),R语言中统计分布和模拟_R语言培训
  18. monaco-editor(code编辑器插件)使用及常用配置与方法
  19. python周末吃什么_中午不知道吃什么,用Python爬取美团外卖评论帮你选餐
  20. 5分钟学会如何制样(XPS测试)

热门文章

  1. PS怎么把人物扣的更干净_PS抠图技巧
  2. 【原型图设计工具】墨刀使用说明
  3. Rayman的绝顶之路——Leetcode每日一题打卡17
  4. 《梦幻西游手游》分析报告
  5. 2018 最新 cnki账号 中国知网账号 帐号 免费入口 用户名 密码 万方 维普
  6. 最容易月薪过万城市排名出炉!
  7. NSOperation
  8. linux 配置compoer
  9. 01英语语法-基本句型及补语
  10. 第1章:基本句型及补语