SpringBoot第四集:整合JdbcTemplate和JPA(2020最新最易懂)

微信扫一扫,分享到朋友圈

SpringBoot第四集:整合JdbcTemplate和JPA(2020最新最易懂)

SpringBoot第四集:整合JdbcTemplate和JPA(2020最新最易懂)

当前环境说明:

Windows10_64

Maven3.x

JDK1.8

MySQL5.6

SpringToolSuite4(Spring官方提供的开发工具,实际就是一个Eclipse)

一.整合JdbcTemplate

1.概述

在实际项目中,在对数据库访问层对数据库进行操作时,大部分时候我们都用的MyBatis/Hibernate,但是偶尔会有用到使用JDBC的时候,一般使用JDBC的话要么就自己封装一个JDBC连接池进行使用,要么就是使用Apache Common 提供的 DbUtils 工具类,还有个就是Spring JDBC ,提供的JdbcTemplate 工具类。

Spring属于一栈式框架,针对 JAVAEE 三层中的每一层,都提供了解决技术。在 DAO 层中 Spring 中使用 JdbcTemplate 完成技术需求。(详情请关注后续发表Spring集)

1 JdbcTemplate中常用类介绍:
2 DriverManagerDataSource类:DataSource连接池的实现子类
3 作用:主要是设置连接数据库的相关信息。如:连接地址、用户名、密码等
4 常用方法:
5 setDriverClassName(……):设置驱动类
6 setUsername(……):设置用户名
7 setPassword(……):设置密码
8 setUrl(……):设置连接地址
9 JdbcTemplate类:
10 作用:由Spring提供的JDBC操作模板类。用于完成CURD操作
11 常用构造方法:
12 JdbcTemplate(DataSource dataSource):创建对象并指定连接管理源
13 常用其他方法:
14 update(……):执行增、删、改。返回值为int类型,表示结果影响行数。
15 queryXXX(……);执行查询。更多请关注博主Spring全集案例

2.准备工作

  1. 创建数据库。
  2. 新增对应数据库实体类。
    1 @Data
    2 @AllArgsConstructor
    3 @NoArgsConstructor
    4 public class Person {
    5     private Integer id;
    6     private String name;
    7     private String password;
    8 }
    
  3. 修改pom.xml引入依赖
    SpringBoot引入MySQL驱动默认版本为8.x,可以手动配置版本。
    1 <!-- SpringBoot整合JdbcTemplate -->
    2 <dependency>
    3     <groupId>org.springframework.boot</groupId>
    4     <artifactId>spring-boot-starter-jdbc</artifactId>
    5 </dependency>
    6
    7 <!-- MySQL驱动(SpringBoot默认引入版本为8.x)手动配置版本 -->
    8 <dependency>
    9     <groupId>mysql</groupId>
    10     <artifactId>mysql-connector-java</artifactId>
    11     <scope>runtime</scope>
    12 </dependency>
    
  4. 修改application.yml文件添加数据源配置
    1 spring:
    2   datasource:
    3     #根据MySQL版本配置驱动类5.x----8.x 驱动类“com.mysql.jdbc.Driver” 或 “com.mysql.cj.jdbc.Driver”。
    4     driver-class-name: com.mysql.cj.jdbc.Driver
    5     #useSSL:SSL协议提供服务主要作用:(不建议在没有服务器身份验证的情况下建立SSL连接。)
    6     #   1)认证用户服务器,确保数据发送到正确的服务器;    .
    7     #   2)加密数据,防止数据传输途中被窃取使用;
    8     #   3)维护数据完整性,验证数据在传输过程中是否丢失;
    9     #serverTimezone:设置时区,不设置会报错。GMT%2B8:东八区北京时间  Asia/Shanghai:上海时间
    10     #useServerPrepStmts:在url中给出useServerPrepStmts=true参数,开启预编译(默认PS是关闭的)
    11     #allowMultiQueries:设置为true,开启批量执行sql的开关。更多请持续关注博主文档
    12     url: jdbc:mysql://localhost:3306/springboot?useSSL=false&serverTimezone=GMT%2B8
    13     username: root
    14     password: xsge
    

3.整合实现

  1. 编写DAO层基础的CURD。
    使用注解@Repository标注为Spring–DAO层组件。注入JdbcTemplate对象
    BeanPropertyRowMapper是JdbcTemplate提供的一个结果集处理器类,是RowMapper结果集处理器接口的实现。
    注意:两个查询方法不一样
    1 @Repository    // Spring注解标注DAO层组件
    2 public class PersonDao{
    3
    4     @Autowired // 注入jdbcTemplate
    5     private JdbcTemplate jdbcTemplate;
    6
    7     /**
    8      * 插入数据
    9      */
    10     public void insertPerson(Person p) {
    11         jdbcTemplate.update("INSERT INTO person(name,password) VALUES (?,?)",
    12                 p.getName(),p.getPassword());
    13     }
    14     /**
    15      * 根据ID查询
    16      * 方法queryForObject可以查询单行单列,也可以查询单行多列
    17      * 参数1:SQL
    18      * 参数2:一个类型 或者 一个结果集处理器(取决于查询的结果和需求)
    19      * 参数3:可变参数
    20      */
    21     public Person selectPersonById(Integer id) {
    22         Person person = jdbcTemplate.queryForObject("SELECT *  FROM person WHERE id =?",
    23                 new BeanPropertyRowMapper<Person>(Person.class), id);
    24         return person;
    25     }
    26     /**
    27      * 查询所有
    28      * 方法query可以查询多行多列。
    29      * 参数1:SQL
    30      * 参数2:一个结果集处理器(取决于查询的结果和需求)
    31      * 参数3:可变参数
    32      */
    33     public List<Person> selectPersonList() {
    34         List<Person> personList = jdbcTemplate.query("SELECT * FROM person",
    35                 new BeanPropertyRowMapper<Person>(Person.class));
    36         return personList;
    37     }
    38
    39 }
    
  2. 编写Service接口
    1 public interface PersonService {
    2     /**
    3      * 新增
    4      */
    5     void insertPerson(Person p);
    6     /**
    7      * 查询一个
    8      */
    9     Person selectPersonById(Integer id);
    10     /**
    11      * 查询多个
    12      */
    13     List<Person> selectPersonList();
    14
    15 }
    
  3. 编写Service实现类
    使用注解@Service标注为Spring组件。注入DAO对象
    1 @Service
    2 public class PersonServiceImpl implements PersonService {
    3
    4     @Autowired
    5     private PersonDao personDao;
    6
    7     @Override
    8     public void insertPerson(Person p) {
    9         personDao.insertPerson(p);
    10     }
    11
    12     @Override
    13     public Person selectPersonById(Integer id) {
    14         return personDao.selectPersonById(id);
    15     }
    16
    17     @Override
    18     public List<Person> selectPersonList() {
    19         return personDao.selectPersonList();
    20     }
    21
    22 }
    
  4. 编写Controller,提供一组restFUL风格的接口
    使用注解@RestController标注控制器类,使其返回数据结果都是JSON格式。注入Service对象,使用RestFUL风格提供访问接口
    1 @RestController
    2 public class PersonController {
    3
    4     @Autowired
    5     private PersonService personService;
    6
    7     /**
    8      * 接口地址:http://localhost:8080/insertPerson
    9      * 请求方式:PUT 入参:JSON数据
    10      */
    11     @RequestMapping(value = "/insertPerson", method = RequestMethod.PUT)
    12     public void insertPerson(@RequestBody Person p) {
    13         personService.insertPerson(p);
    14     };
    15     /**
    16      * 接口地址:http://localhost:8080/selectPersonById/1
    17      * 请求方式:GET 入参:id
    18      */
    19     @GetMapping(value = "/selectPersonById/{id}")
    20     public Person selectPersonById(@PathVariable Integer id) {
    21         System.err.println("id值为:"+id);
    22         return personService.selectPersonById(id);
    23     };
    24     /**
    25      * 接口地址:http://localhost:8080/selectPersonList
    26      * 请求方式:POST 入参:无
    27      */
    28     @PostMapping("/selectPersonList")
    29     public List<Person> selectPersonList(){
    30         return personService.selectPersonList();
    31     };
    32 }
    
  5. 安装Postman工具,访问测试接口。
    启动SpirngBoot项目主程序,请求接口测试!
    Postman是一款常用的接口测试工具,可以测试发送不同请求,传递不同参数,具体操作请关注博主尽情期待。

    PostMan下载地址

二.整合JPA

JPA Java Persistence API 的简称,中文名 Java 持久层 API SUN 公司推出的一套基于 ORM 的规范 。Hibernate 框架中提供了 JPA 的实现, Spring Data JPASpring 基于 Hibernate 开发的一个 JPA 框架。可以极大的简化 JPA 的写法,可以在几乎不用写具体代码的情况下,实现对数据的访问和操作。除了 CRUD 外,还包括如 分页排序 等一些常用的功能。此外更强大的是,它还 可以通过 方法命名规则 进行数据库查询操作

Spring Data JPA提供的接口:

  1. Repository :最顶层的接口,是一个空的接口,目的是为了统一所有Repository的类型,且能让组件扫描的时候自动识别。
  2. CrudRepository  :是Repository的子接口,提供CRUD的功能(内置默认的简单的CURD方法,可以直接引用)
  3. PagingAndSortingRepository :是CrudRepository的子接口,添加分页和排序的功能。
  4. JpaRepository :是PagingAndSortingRepository的子接口,增加了一些实用的功能,比如:批量操作等。(相对最完整的内置方法:简单的CURD/分页/批量)
  5. JpaSpecificationExecutor :用来做负责查询的接口
  6. Specification :是 Spring Data JPA 提供的一个查询规范,要做复杂的查询,只需围绕这个规范来设置查询条件即可。

其中,自定义查询,方法名命名规范如下:

命名可选关键字 方法命名举例 执行方法时对应产生的SQL,Where子句
And findByNameAndPwd where name= ? and pwd =?
Or findByNameOrSex where name= ? or sex=?
Is,Equals findById,findByIdEquals where id= ?
Between findByIdBetween where id between ? and ?
LessThan findByIdLessThan where id < ?
LessThanEquals findByIdLessThanEquals where id <= ?
GreaterThan findByIdGreaterThan where id > ?
GreaterThanEquals findByIdGreaterThanEquals where id > = ?
After findByIdAfter where id > ?
Before findByIdBefore where id < ?
IsNull findByNameIsNull where name is null
isNotNull,NotNull findByNameNotNull where name is not null
Like findByNameLike where name like ?
NotLike findByNameNotLike where name not like ?
StartingWith findByNameStartingWith where name like ‘?%’
EndingWith findByNameEndingWith where name like ‘%?’
Containing findByNameContaining where name like ‘%?%’
OrderBy findByIdOrderByXDesc where id=? order by x desc
Not findByNameNot where name <> ?
In findByIdIn(Collection<?> c) where id in (?)
NotIn findByIdNotIn(Collection<?> c) where id not in (?)
True findByAaaTue where aaa = true
False findByAaaFalse where aaa = false
IgnoreCase findByNameIgnoreCase where UPPER(name)=UPPER(?)

这个确实,够强大!但查询条件一多,这个方法名就也会很长了哦……

Spring Data JPA简单总结:

  1. 提供了基本的CURD方法,批处理,分页方法等。
  2. 允许自定义方法名,根据指定命名规则实现查询。
  3. 允许使用@Query注解,自定义更高级,更复杂的SQL

1.准备工作

  1. 引入
    spring-data-jap依赖
    
    1 <!-- SpringBoot整合JPA -->
    2 <dependency>
    3     <groupId>org.springframework.boot</groupId>
    4     <artifactId>spring-boot-starter-data-jpa</artifactId>
    5 </dependency>
    
  2. 修改yml配置文件设置JPA配置及数据库配置
    1 spring:
    2   datasource:
    3     #根据MySQL版本配置驱动类5.x----8.x 驱动类“com.mysql.jdbc.Driver” 或 “com.mysql.cj.jdbc.Driver”。
    4     driver-class-name: com.mysql.cj.jdbc.Driver
    5     #useSSL:SSL协议提供服务主要作用:(不建议在没有服务器身份验证的情况下建立SSL连接。)
    6     #   1)认证用户服务器,确保数据发送到正确的服务器;    .
    7     #   2)加密数据,防止数据传输途中被窃取使用;
    8     #   3)维护数据完整性,验证数据在传输过程中是否丢失;
    9     #serverTimezone:设置时区,不设置会报错。GMT%2B8:东八区北京时间  Asia/Shanghai:上海时间
    10     #useServerPrepStmts:在url中给出useServerPrepStmts=true参数,开启预编译(默认PS是关闭的)
    11     #allowMultiQueries:设置为true,开启批量执行sql的开关。更多请持续关注博主文档
    12     url: jdbc:mysql://localhost:3306/springboot?useSSL=false&serverTimezone=GMT%2B8
    13     username: root
    14     password: xsge
    15   #JPA配置——————————————————————————————————————————————————————————————————————————
    16   jpa:
    17     #是否显示SQL
    18     show-sql: true
    19     hibernate:
    20       #表结构处理方式方式。update表示,第一次执行时根据实体类创建表结构,之后的操作只做数据更新
    21       ddl-auto: update
    
  3. 新增实体类对应数据库表

    配置实体常用注解:(这里仅仅列举,更多详情请关注博主Hibernate文章)

    @Entity

    作用:标识当前实体为数据实体类

    @Table name= 值)

    作用:标识当前实体对应的是数据库表

    属性:Name :指定当前实体对应数据库表名称

    @Id

    作用:标识当前属性为主键列属性

    @Column

    作用:标识当前属性对应数据库的字段

    属性:Name :指定当前属性所对应的数据库字段列名称

    @GeneratedValue

    作用:指定字段列的主键策略

    属性:Generator :该属性值,指定 Hibernate 中提供的主键策略声明别名

    Strategy :该属性,标注 JPA 提供的主键生成策略(即主键生成方式)。

    取值GenerationType:

    AUTO: 自适应,选择一下三种,默认选择 TABLE

    IDENTITY:Mysql 自增长,要判断是否支持

    SEQUENCE:Oracle 自增长,要判断是否支持

    TABLE :类似于 Helw 高低位算法,无需判断,因为使用的是固定格式的算法生成。

    1 @Entity    // 标识当前实体为数据实体类
    2 @Data    // 自动生成get/set等
    3 @AllArgsConstructor    // 全参构造函数
    4 @NoArgsConstructor // 无参构造函数
    5 @Table(name = "student") // 标识实体对应的表名
    6 @EntityListeners(AuditingEntityListener.class) // spring-data-jap实体类数据更新的监听器注解
    7 public class Student {
    8     // 标识当前属性为主键列属性
    9     @Id
    10     // 标识字段列的主键策略(主键生成方式)GenerationType.IDENTITY表示shiyongMySQL默认自增长生成主键值
    11     @GeneratedValue(strategy = GenerationType.IDENTITY)
    12     private Integer sid;
    13
    14     // 标识当前属性对应数据库的字段
    15     @Column(name = "name")
    16     private String name;
    17     @Column(name = "age")
    18     private Integer age;
    19
    20     // spring-data-jap中提供的自动填充,新增时自动填充时间(配合SPRING-DATA-JPA监听注解使用)
    21     @CreatedDate
    22     private Date createTime;
    23
    24     // spring-data-jap中提供的自动填充,有更新时自动填充更新时间(配合SPING-DATA-JPA监听注解使用)
    25     @LastModifiedDate
    26     private Date updateTime;
    27 }
    

    这里需要注意,在《Mybatis-Plus使用全解》中,介绍过如何设置公共字段自动填充功能。比如创建时间和修改时间,创建人和修改人等等,都是可以一进行赋值的。在 spring-data-jap 中,是使用 @CreatedDate@LastModifiedDate 标记,同时,需要在实体类上,加 @EntityListeners(AuditingEntityListener.class) ,然后 在启动类上加入注解 @EnableJpaAuditing(开启JPA自动填充) ,这样就实现类似公共字段自动填充的功能了。(JPA自动填充注解如下图)

  4. 修改SpringBoot主程序

    在启动类上加入注解 @EnableJpaAuditing

    1 @SpringBootApplication
    2 @EnableJpaAuditing  // 开启JPA自动填充功能
    3 @Slf4j
    4 public class AnnotaticSpringBootApplication {
    5     // 主函数
    6     public static void main(String[] args) {
    7         // 启动App
    8         SpringApplication.run(AnnotaticSpringBootApplication.class, args);
    9         log.info("主程序启动了………………");
    10     }
    11 }
    

2.整合实现CURD

在Spring-Data-Jpa概述中,简单总结了JPA操作的方法,概括有三种:调用原接口方法实现简单CURD,自定义方法名实现简单CURD,自定义SQL实现CURD。通常情况下,三者结合使用,如果功能需求本身直接使用原接口方法就能实现那就无需更改,如果需求需要不同条件,那么自定义方法名即可,如果更为复杂的需求,直接使用自定义SQL实现。

A,接口源方法实现CURD

  1. 编写子接口继承接口JpaRepository。
    说明:JpaRepository接口中继承了来自各个父类的简单CURD方法,包括分页/排序等。这些方法可以直接引用,无需关注SQL。
    1 /**
    2  * 编写DAO接口继承JpaRepository接口
    3  * 泛型参数1:CURD实体类型
    4  * 泛型参数2:主键的类型(通常为Integer或Long)
    5  */
    6 public interface StudentDao extends JpaRepository<Student, Integer>{
    7 }
    
  2. 编写Service实现。
    (实际开发中需要抽象接口(Inteface)的不能省略,这里图方便就省略了,直接显示的是接口实现类)
    DAO对象直接自动注入即可,SpringBoot-Data-JPA自主扫描Repository及其所有子接口/子实现类组件。
    更多其他方法请自行参考附录
    1 @Service
    2 public class StudentServiceImpl implements StudentService {
    3
    4     @Autowired
    5     private StudentDao studentDao;
    6
    7     /**
    8      * 添加:调用JpaRepository的默认方法save实现保存
    9      * 返回值为添加的数据对象,同时还会将添加数据的id给返回
    10      */
    11     @Override
    12     public Student save(Student student) {
    13         return studentDao.save(student);
    14     }
    15     /**
    16      * 根据ID查询:调用JpaRepository的默认方法findById实现根据id查询
    17      * 返回结果为Optional<Student>,是JDK1.8新增的防null对象问题的一个核心类。
    18      * 你可以理解为将对象查询后,有放入到一个Optional容器中。调用方法get即可将对象取出
    19      */
    20     @Override
    21     public Student findById(Integer sid) {
    22         return studentDao.findById(sid).get();
    23     }
    24     /**
    25      * 分页查询:调用JpaRepository的默认方法findAll实现查询所有
    26      * 实际参数类型为:Pageable分页接口,PageRequest使其间接实现子类。
    27      * 参数1:当前页码(从0开始,不能为负数)
    28      * 参数2:当前页数据显示行数(从1开始,不能为负数)
    29      */
    30     @Override
    31     public Page<Student> findAll(Integer page,Integer size) {
    32         return studentDao.findAll(PageRequest.of(page,size));
    33     }
    34
    35 }
    
  3. 新增控制器,提供接口测试
    1 @RestController
    2 public class StudentController {
    3
    4     @Autowired
    5     private StudentService studentService;
    6
    7     /**
    8      * 测试接口:http://localhost:8080/saveStu
    9      * 请求方式:PUT 入参:JSON数据
    10      */
    11     @RequestMapping(value = "/saveStu",method = RequestMethod.PUT)
    12     public Student save(@RequestBody Student student) {
    13         return studentService.save(student);
    14     }
    15
    16     /**
    17      * 测试接口:http://localhost:8080/findById
    18      * 请求方式:GET 入参:占位符参数sid
    19      */
    20     @GetMapping("/findById/{id}")
    21     public Student findById(@PathVariable(name = "id") Integer sid) {
    22         return studentService.findById(sid);
    23     }
    24     /**
    25      * 测试接口:http://localhost:8080/findAll
    26      * 请求方式:POST 入参:page=?& size=?
    27      */
    28     @PostMapping("/findAll")
    29     public Page<Student> findAll(Integer page,Integer size) {
    30         return studentService.findAll(page,size);
    31     }
    32
    33 }
    
  4. 启动主程序,利用Postman工具测试

B,自定义方法名及自定义SQL实现操作

当功能需求无法通过原接口方法能实现时,就需要手动自定义方法,或者自定义SQL实现CURD。其实并不需要多复杂的部署,在源方法案例的基础上,直接在持久层接口中新增自定义方法名的方法或者新增自定义SQL的方法即可。

1 public interface StudentDao extends JpaRepository<Student, Integer>{
2     // 使用自定义命名方法名规则,进行查询服务,并添加分页功能
3     List<Student> findByNameContaining(String name,Pageable pageable);// …… where name like ‘%?%’
4
5     /**
6      * @Query进行 自定义sql编写
7      * nativeQuery=true:表示定义的SQL为标准SQL(没有这一项,SQL语句中的表名和字段名是实体类名和实体类中的字段名)
8      * 传参数使用占位符?代替,但需要注意的是这里的占位符后面需要跟数字(第几个?N 数字N从1开始)
9      */
10     @Query(value="select * from student where name = ?1",nativeQuery=true)
11     List<Student> queryByName(String name);
12 }

其他测试省略……

附录

JPA默认方法说明:查源码结构如下(内部方法好好看吧!)

1  QueryDslJpaRepository
2  ┣━ QueryDslPredicateExecutor
3  ┗━ SimpleJpaRepository
4      ┣━ JpaSpecificationExecutor
5      ┗━ JpaRepository
6          ┣━ QueryByExampleExecutor
7          ┗━ PagingAndSortingRepository
8              ┗━ CrudRepository
9                  ┗━Repository

Java mapreduce解析parquet日志

上一篇

网易严选发声退出双十一:不做复杂玩法不发战报

下一篇

你也可能喜欢

SpringBoot第四集:整合JdbcTemplate和JPA(2020最新最易懂)

长按储存图像,分享给朋友