Spring Boot (三): ORM 框架 JPA 与连接池 Hikari

摘要:
当谈到使用ORM框架时,我们必须讨论连接池。市场上有许多成熟的数据库连接池,如C3P0、Tomcat连接池、BoneCP和许多其他产品。但我们为什么要介绍Hikari?HikariCP的口号是快速、简单和可靠。SpringBootJPA是Spring基于ORM框架和JPA规范封装的JPA应用程序框架,它使开发人员能够以最少的代码访问和操作数据。学习和使用SpringDataJPA可以大大提高开发效率!SpringBootJPA将我们从DAO层的操作中解放出来。基本上,所有CRUD都可以依赖它来实现。

Spring Boot (三): ORM 框架 JPA 与连接池 Hikari第1张

前面两篇文章我们介绍了如何快速创建一个 Spring Boot 工程《Spring Boot(一):快速开始》和在 Spring Boot 中如何使用模版引擎 Thymeleaf 渲染一个Web页面《Spring Boot (二):模版引擎 Thymeleaf 渲染 Web 页面》,本篇文章我们继续介绍在 Spring Boot 中如何使用数据库。

1. 概述

数据库方面我们选用 Mysql , Spring Boot 提供了直接使用 JDBC 的方式连接数据库,毕竟使用 JDBC 并不是很方便,需要我们自己写更多的代码才能使用,一般而言在 Spring Boot 中我们常用的 ORM 框架有 JPA 和 Mybaties ,本篇文章我们要介绍的就是 JPA 的使用姿势。

说道使用 ORM 框架,就不得不顺便聊一下连接池,市面上很多成熟的数据库连接池,如 C3P0 、 Tomcat 连接池、 BoneCP 等等很多产品,但是我们为什么要介绍 Hikari ?这个要从 BoneCP 说起。

因为,传说中 BoneCP 在快速这个特点上做到了极致,官方数据是C3P0等的25倍左右。不相信?其实我也不怎么信。可是,有图有真相啊,传说图片来源于官网,然而笔者在官网并没有找到,大家看一下:

Spring Boot (三): ORM 框架 JPA 与连接池 Hikari第2张

看起来是不是完全吊打,但是当 HikariCP 横空出世以后,这个局面就被完全改写了, BoneCP 被 HikariCP 完全吊打,看了一下 BoneCP Github 上面的版本更新,发现在2013年10月23日以后就再也没有更新过了,包括在仓库介绍上面都写着建议大家使用 HikariCP ,看来作者已经完全心灰意冷了。

Spring Boot (三): ORM 框架 JPA 与连接池 Hikari第3张

Hikari 这个词来源于日文,是“光”的意思,估计作者的意思是这个连接池将会和光一样快,不知道作者是不是日本人。

HikariCP 的口号是快速,简单,可靠。不知道是否真的如它自己宣传的一样,官方又提供了一张图,大家感受一下,这张图来源于:https://github.com/brettwooldridge/HikariCP 。

Spring Boot (三): ORM 框架 JPA 与连接池 Hikari第4张

更多有关 HikariCP 的信息,大家可以访问官方的 Github 仓库了解:https://github.com/brettwooldridge/HikariCP ,笔者这里不多做介绍,毕竟我们更关注的如何使用。

2. JPA 介绍

JPA (Java Persistence API) 是 Sun 官方提出的 Java 持久化规范。它为 Java 开发人员提供了一种对象/关联映射工具来管理 Java 应用中的关系数据。它的出现主要是为了简化现有的持久化开发工作和整合 ORM 技术,结束现在 Hibernate,TopLink,JDO 等 ORM 框架各自为营的局面。

值得注意的是,JPA 是在充分吸收了现有 Hibernate,TopLink,JDO 等 ORM 框架的基础上发展而来的,具有易于使用,伸缩性强等优点。从目前的开发社区的反应上看, JPA 受到了极大的支持和赞扬,其中就包括了 Spring 与 EJB3. 0的开发团队。

注意: JPA 是一套规范,不是一套产品,那么像 Hibernate,TopLink,JDO 他们是一套产品,如果说这些产品实现了这个 JPA 规范,那么我们就可以叫他们为 JPA 的实现产品。

Spring Boot JPA 是 Spring 基于 ORM 框架、 JPA 规范的基础上封装的一套 JPA 应用框架,可使开发者用极简的代码即可实现对数据的访问和操作。它提供了包括增删改查等在内的常用功能,且易于扩展!学习并使用 Spring Data JPA 可以极大提高开发效率!

Spring Boot JPA 让我们解脱了 DAO 层的操作,基本上所有 CRUD 都可以依赖于它来实现。

Spring Boot JPA 帮我们定义了很多自定义的简单查询,并且可以根据方法名来自动生成 SQL ,主要的语法是 findXXBy , readAXXBy , queryXXBy , countXXBy , getXXBy 后面跟属性名称:

public interface UserRepository extends JpaRepository<UserModel, Long> {
    UserModel getByIdIs(Long id);

    UserModel findByNickName(String nickName);

    int countByAge(int age);

    List<UserModel> findByNickNameLike(String nickName);
}

具体的关键字,使用方法和生产成SQL如下表所示:

KeywordSampleJPQL snippet
AndfindByLastnameAndFirstname… where x.lastname = ?1 and x.firstname = ?2
OrfindByLastnameOrFirstname… where x.lastname = ?1 or x.firstname = ?2
Is,EqualsfindByFirstname,findByFirstnameIs,findByFirstnameEquals… where x.firstname = 1?
BetweenfindByStartDateBetween… where x.startDate between 1? and ?2
LessThanfindByAgeLessThan… where x.age < ?1
LessThanEqualfindByAgeLessThanEqual… where x.age <= ?1
GreaterThanfindByAgeGreaterThan… where x.age > ?1
GreaterThanEqualfindByAgeGreaterThanEqual… where x.age >= ?1
AfterfindByStartDateAfter… where x.startDate > ?1
BeforefindByStartDateBefore… where x.startDate < ?1
IsNullfindByAgeIsNull… where x.age is null
IsNotNull,NotNullfindByAge(Is)NotNull… where x.age not null
LikefindByFirstnameLike… where x.firstname like ?1
NotLikefindByFirstnameNotLike… where x.firstname not like ?1
StartingWithfindByFirstnameStartingWith… where x.firstname like ?1 (parameter bound with appended %)
EndingWithfindByFirstnameEndingWith… where x.firstname like ?1 (parameter bound with prepended %)
ContainingfindByFirstnameContaining… where x.firstname like ?1 (parameter bound wrapped in %)
OrderByfindByAgeOrderByLastnameDesc… where x.age = ?1 order by x.lastname desc
NotfindByLastnameNot… where x.lastname <> ?1
InfindByAgeIn(Collection ages)… where x.age in ?1
NotInfindByAgeNotIn(Collection age)… where x.age not in ?1
TruefindByActiveTrue()… where x.active = true
FalsefindByActiveFalse()… where x.active = false
IgnoreCasefindByFirstnameIgnoreCase… where UPPER(x.firstame) = UPPER(?1)

3. 工程实战

这里我们创建工程 spring-boot-jpa-hikari 。

3.1 工程依赖 pom.xml

代码清单:spring-boot-jpa-hikari/pom.xml
***

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.8.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.springboot</groupId>
    <artifactId>spring-boot-jpa-hikari</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-boot-jpa-hikari</name>
    <description>spring-boot-jpa-hikari</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

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

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
  • mysql-connector-java:mysql连接驱动
  • spring-boot-starter-data-jpa:jpa相关的依赖包,这个包里包含了很多内容,包括我们使用的连接池 HikariCP ,从 Spring Boot 2.x 开始, Spring Boot 默认的连接池更换成为 HikariCP ,在当前的 Spring Boot 2.1.8 RELEASE 版本中,所使用的 HikariCP 版本为 3.2.0 ,如图:

Spring Boot (三): ORM 框架 JPA 与连接池 Hikari第5张

3.2 配置文件 application.yml

代码清单:spring-boot-jpa-hikari/src/main/resources/application.yml
***

server:
  port: 8080
spring:
  application:
    name: spring-boot-jpa-hikari
  jpa:
    database: mysql
    show-sql: true
    generate-ddl: true
    database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
    hibernate:
      ddl-auto: update
  datasource:
    url: jdbc:mysql://192.168.0.128:3306/test?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.zaxxer.hikari.HikariDataSource
    hikari:
      auto-commit: true
      minimum-idle: 2
      idle-timeout: 60000
      connection-timeout: 30000
      max-lifetime: 1800000
      pool-name: DatebookHikariCP
      maximum-pool-size: 5

注意:

  1. 有关 JPA 的配置有一点需要的, spring.jpa.hibernate.ddl-auto ,这个属性需谨慎配置,它的几个值的含义对数据库来讲都是高危操作,笔者这里方便起见配置了 update ,各位读者请根据具体使用场景配置。

    • create :每次加载hibernate时都会删除上一次的生成的表,然后根据你的model类再重新来生成新表,哪怕两次没有任何改变也要这样执行,这就是导致数据库表数据丢失的一个重要原因。
    • create-drop :每次加载hibernate时根据model类生成表,但是sessionFactory一关闭,表就自动删除。
    • update :最常用的属性,第一次加载hibernate时根据model类会自动建立起表的结构(前提是先建立好数据库),以后加载hibernate时根据 model类自动更新表结构,即使表结构改变了但表中的行仍然存在不会删除以前的行。要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等 应用第一次运行起来后才会。
    • validate :每次加载hibernate时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。
    • none :不做任何操作
  2. 有关 HikariCP 更多的配置可以参考源码类 com.zaxxer.hikari.HikariConfig ,笔者这里仅简单配置了自动提交、超时时间、最大最小连接数等配置。

3.3 映射实体类 UserModel.java

代码清单:spring-boot-jpa-hikari/src/main/java/com/springboot/springbootjpahikari/model/UserModel.java
***

@Entity
@Data
@Table(name = "user")
public class UserModel {
    @Id
    @GeneratedValue(generator = "paymentableGenerator")
    @GenericGenerator(name = "paymentableGenerator", strategy = "uuid")
    @Column(name ="ID",nullable=false,length=36)
    private String id;
    @Column(nullable = true, unique = true)
    private String nickName;
    @Column(nullable = false)
    private int age;
}
  • unique : 唯一约束

  • 主键生成策略为uuid

3.4 资源类 UserRepository.java

代码清单:spring-boot-jpa-hikari/src/main/java/com/springboot/springbootjpahikari/repository/UserRepository.java
***

public interface UserRepository extends JpaRepository<UserModel, Long> {
    UserModel getByIdIs(Long id);

    UserModel findByNickName(String nickName);

    int countByAge(int age);

    List<UserModel> findByNickNameLike(String nickName);
}

3.5 接口测试类 UserController.java

代码清单:spring-boot-jpa-hikari/src/main/java/com/springboot/springbootjpahikari/controller/UserController.java
***

@RestController
public class UserController {

    @Autowired
    UserRepository userRepository;

    /**
     * 查询用户列表
     * @return
     */
    @GetMapping("/user")
    public List<UserModel> user() {
        return userRepository.findAll(Sort.by("id").descending());
    }

    /**
     * 新增或更新用户信息
     * @param user
     * @return
     */
    @PostMapping("/user")
    public UserModel user(UserModel user) {
        return userRepository.save(user);
    }

    /**
     * 根据id删除用户
     * @param id
     * @return
     */
    @DeleteMapping("/user")
    public String deleteUserById(Long id) {
        userRepository.deleteById(id);
        return "success";
    }
}

4. 测试

测试我们借助工具 PostMan ,启动工程,首先我们新增一个用户信息,如图:

Spring Boot (三): ORM 框架 JPA 与连接池 Hikari第6张

如果我们参数中加入 id ,并且 id 的值和数据库中的 id 维持一致,这是会更新当前 id 的数据,如图:

Spring Boot (三): ORM 框架 JPA 与连接池 Hikari第7张

我们执行查询操作,如图:

Spring Boot (三): ORM 框架 JPA 与连接池 Hikari第8张

执行删除操作,如图:

Spring Boot (三): ORM 框架 JPA 与连接池 Hikari第9张

至此,测试完成。

5. 示例代码

示例代码-Github

示例代码-Gitee

6. 参考

https://github.com/brettwooldridge/HikariCP

https://docs.spring.io/spring-data/jpa/docs/current/reference/html/

http://www.ityouknow.com/springboot/2016/08/20/spring-boot-jpa.html

扫描二维码关注「极客挖掘机」公众号!
作者:极客挖掘机
定期发表作者的思考:技术、产品、运营、自我提升等。

本文版权归作者极客挖掘机和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
如果您觉得作者的文章对您有帮助,就来作者个人小站逛逛吧:极客挖掘机

免责声明:文章转载自《Spring Boot (三): ORM 框架 JPA 与连接池 Hikari》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇channels使用【Swift】UILabel的简单操作方法下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Hibernate

Hibernate环境搭建 Hibernate的API Hibernate的CRUD EE三层结构: web层       业务逻辑层    持久层         jdbc,DBUTils,Hibernate    Hibernate简介: 一个开源的对象关系映射框架,对JDBC进行了轻量级封装,将pojo与数据库表建立映射关系,是一个全自动的O...

数据连接池DruId的使用

1,下载druID.jar包 2,配置文件druid.properties配置相关信息 driverClassName : org.gjt.mm.mysql.Driverurl : jdbc:mysql://127.0.0.1:3306/e_testusername : rootpassword : admin#初始化物理连接数目#initialSize...

python并发编程:阻塞IO

阻塞IO(blocking  IO) 在Linux中,默认情况下所有的socket都是blocking,一个典型的读操作流程大概是这样:   当用户进程调用了recvfrom这个系统调用,kernel就开始了IO的第一个阶段:准备数据。对于network io来说,很多时候数据在一开始还没有到达(比如,还没有收到一个完整的udp包),这个时候kernel...

Spring源码系列1

一、搭建源码环境 从Spring官网下载源码,我下载的是spring 4.3.26。 spring源码下载地址:https://github.com/spring-projects/spring-framework/releases spring发布包下载地址:https://repo.spring.io/release/org/springframewo...

mybatis的知识点总结

1.接口绑定:两种方法,基于注解或者基于xml文档mapper,但要注意mapper的namespace要与接口路径完全一致。 2.orm格式转换:通过设置resultMap和ResultType,将数据库中的记录转换为代码的bean对象。得到list或者对象。 3.通过parameterType接收参数,进行动态sql生成。运用ognl表达式 4.走缓存...

JDBC: C3P0连接池

C3P0连接池      C3P0是一个开源的JDBC连接池,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate、 Spring等。    导入jar包及配置文件     1) 将jar包 复制到myJar文件夹即可,IDEA会自动导入        2) 导入配置文件 c3p0-config.xml      c3p0-co...