springboot整合mybatis 使用HikariCP連接池

前言

Springboot讓Java開發更加美好,本節主要講的是使用Hikari數據庫連接池,如果需要使用druid連接池的請看我另外一篇博客,springboot Mybatis 整合(這篇文章有詳細搭建springboot項目的過程,對於剛接觸springboot的新手有幫助)。

爲什麼使用HikariCP

在Springboot2.X版本,數據庫的連接池官方推薦使用HikariCP,官方的原話:

Production database connections can also be auto-configured by using a poolingDataSource. Spring Boot uses the following algorithm for choosing a specific implementation:

  1. We preferHikariCPfor its performance and concurrency. If HikariCP is available, we always choose it.

  2. Otherwise, if the Tomcat poolingDataSourceis available, we use it.

  3. If neither HikariCP nor the Tomcat pooling datasource are available and ifCommons DBCP2is available, we use it.

意思是說:

  1. 我們更喜歡HikariCP的性能和併發性。如果有HikariCP,我們總是選擇它

  2. 否則,如果Tomcat池數據源可用,我們將使用它。

  3. 如果HikariCP和Tomcat池數據源都不可用,如果Commons DBCP2可用,我們將使用它。

那麼如何使用HikariCP呢?

如果你的springboot版本是2.X,當你使用spring-boot-starter-jdbc或者spring-boot-starter-data-jpa依賴,springboot就會自動引入HikariCP的依賴了。

使用指定的數據庫連接池

如果你需要使用指定的數據庫連接池,那麼你需要在application.properties中配置:spring.datasource.type

環境

  • JDK: 1.8

  • Maven: 3.3.9

  • SpringBoot: 2.0.3.RELEASE

  • 開發工具:Intellij IDEA 2017.1.3

開始使用

本次的配置中我們持久層使用mybatis,使用HikariCP作爲數據庫連接池。

引入依賴

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <!--排除默認的tomcat-jdbc-->
                <exclusion>
                    <groupId>org.apache.tomcat</groupId>
                    <artifactId>tomcat-jdbc</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.46</version>
        </dependency>
        <!-- mybatis一定要使用starter,不然無法自動配置和注入 -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

以上的依賴就足夠了,前面介紹過,只需要導入spring-boot-starter-jdbc依賴springboot就默認使用Hikari作爲數據庫連接池了。

創建數據表

CREATE DATABASE mytest;

CREATE TABLE t_user(
  userId INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
  userName VARCHAR(255) NOT NULL ,
  password VARCHAR(255) NOT NULL ,
  phone VARCHAR(255) NOT NULL
) ENGINE=INNODB AUTO_INCREMENT=1000 DEFAULT CHARSET=utf8;

創建實體類

package com.winterchen.model;

/**
 * Created by Donghua.Chen on 2018/7/25.
 */
public class UserDomain {

    private Integer userId;

    private String userName;

    private String password;

    private String phone;

    // @TODO 省略get/set
}

創建Dao以及mapper映射

創建Dao類

創建一個dao的包,並且在這個包下創建一個UserDao

package com.winterchen.dao;

import com.winterchen.model.UserDomain;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.util.List;

/**
 * Created by Donghua.Chen on 2018/7/25.
 */
@Mapper
public interface UserDao {

    int insert(UserDomain record);

    void deleteUserById(@Param("userId") Integer userId);

    void updateUser(UserDomain userDomain);

    List<UserDomain> selectUsers();

}

注意:一定不要忘了使用@Mapper註解,如果沒有這個註解,spring就無法掃描到這個類,導致項目啓動報錯。

創建Mapper映射

上一步我們創建dao數據庫持久層類,由於本文使用的是xml映射的方式,所以我們需要創建一個xml映射文件。

resources文件夾下新建一個文件夾mapper

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.winterchen.dao.UserDao" >
    <sql id="BASE_TABLE">
        t_user
    </sql>

    <sql id="BASE_COLUMN">
        userId,userName,password,phone
    </sql>

    <insert id="insert" parameterType="com.winterchen.model.UserDomain">
        INSERT INTO
        <include refid="BASE_TABLE"/>
        <trim prefix="(" suffix=")" suffixOverrides=",">
            userName,password,
            <if test="phone != null">
                phone,
            </if>
        </trim>
        <trim prefix="VALUES(" suffix=")" suffixOverrides=",">
            #{userName, jdbcType=VARCHAR},#{password, jdbcType=VARCHAR},
            <if test="phone != null">
                #{phone, jdbcType=VARCHAR},
            </if>
        </trim>
    </insert>

    <delete id="deleteUserById">
      DELETE FROM
      <include refid="BASE_TABLE"/>
      WHERE
      userId = #{userId, jdbcType=INTEGER}
    </delete>
    <!-- 更新用戶信息,爲空的字段不進行置空 -->
    <update id="updateUser" parameterType="com.winterchen.model.UserDomain">
        UPDATE
        <include refid="BASE_TABLE"/>
        <set>
          <if test="userName != null">
              userName = #{userName, jdbcType=VARCHAR},
          </if>
          <if test="password != null">
              password = #{password, jdbcType=VARCHAR},
          </if>
          <if test="phone != null">
              phone = #{phone, jdbcType=VARCHAR},
          </if>
        </set>
        <where>
            userId = #{userId, jdbcType=INTEGER}
        </where>
    </update>

    <select id="selectUsers" resultType="com.winterchen.model.UserDomain">
        SELECT
        <include refid="BASE_COLUMN"/>
        FROM
        <include refid="BASE_TABLE"/>
    </select>
</mapper>

注意點: 請將namespace="com.winterchen.dao.UserDao"改爲你自己項目Dao的路徑,以及下面方法的一些路徑都要改爲你自己項目的相關路徑。

配置

server.port=8080

#### 數據庫連接池屬性
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/mytest?useSSL=false&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
spring.datasource.username=root
spring.datasource.password=root
#自動提交
spring.datasource.default-auto-commit=true
#指定updates是否自動提交
spring.datasource.auto-commit=true
spring.datasource.maximum-pool-size=100
spring.datasource.max-idle=10
spring.datasource.max-wait=10000
spring.datasource.min-idle=5
spring.datasource.initial-size=5
spring.datasource.validation-query=SELECT 1
spring.datasource.test-on-borrow=false
spring.datasource.test-while-idle=true
# 配置間隔多久才進行一次檢測,檢測需要關閉的空閒連接,單位是毫秒
spring.datasource.time-between-eviction-runs-millis=18800
# 配置一個連接在池中最小生存的時間,單位是毫秒
spring.datasource.minEvictableIdleTimeMillis=300000

# mybatis對應的映射文件路徑
mybatis.mapper-locations=classpath:mapper/*.xml
# mybatis對應的實體類
mybatis.type-aliases-package=com.winterchen.model

Service層

package com.winterchen.service;

import com.winterchen.model.UserDomain;

import java.util.List;

/**
 * Created by Donghua.Chen on 2018/7/25.
 */
public interface UserService {

    int insert(UserDomain record);

    void deleteUserById(Integer userId);

    void updateUser(UserDomain userDomain);

    List<UserDomain> selectUsers();

}

Service 實現層

package com.winterchen.service.impl;

import com.winterchen.dao.UserDao;
import com.winterchen.model.UserDomain;
import com.winterchen.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * Created by Donghua.Chen on 2018/7/25.
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;//這裏會爆紅,請忽略

    @Override
    public int insert(UserDomain record) {
        return userDao.insert(record);
    }

    @Override
    public void deleteUserById(Integer userId) {
        userDao.deleteUserById(userId);
    }

    @Override
    public void updateUser(UserDomain userDomain) {
        userDao.updateUser(userDomain);
    }

    @Override
    public List<UserDomain> selectUsers() {
        return userDao.selectUsers();
    }
}

Controller層

package com.winterchen.controller;

import com.winterchen.model.UserDomain;
import com.winterchen.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

/**
 * Created by Donghua.Chen on 2018/7/25.
 */
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @PostMapping("")
    public ResponseEntity addUser(
            @RequestParam(value = "userName", required = true)
            String userName,
            @RequestParam(value = "password", required = true)
            String password,
            @RequestParam(value = "phone", required = false)
            String phone
    ){
        UserDomain userDomain = new UserDomain();
        userDomain.setUserName(userName);
        userDomain.setPassword(password);
        userDomain.setPhone(phone);
        userService.insert(userDomain);
        return ResponseEntity.ok("添加成功");
    }

    @DeleteMapping("")
    public ResponseEntity deleteUser(@RequestParam(value = "userId", required = true) Integer userId){

        userService.deleteUserById(userId);
        return ResponseEntity.ok("刪除成功");
    }

    @PutMapping("")
    public ResponseEntity updateUser(
            @RequestParam(value = "userId", required = true)
                    Integer userId,
            @RequestParam(value = "userName", required = false)
                    String userName,
            @RequestParam(value = "password", required = false)
                    String password,
            @RequestParam(value = "phone", required = false)
                    String phone
    ){
        UserDomain userDomain = new UserDomain();
        userDomain.setUserId(userId);
        userDomain.setUserName(userName);
        userDomain.setPassword(password);
        userDomain.setPhone(phone);
        userService.updateUser(userDomain);
        return ResponseEntity.ok("更新成功");
    }

    @GetMapping("")
    public ResponseEntity getUsers(){
        return ResponseEntity.ok(userService.selectUsers());
    }
}

強行科普一下:

  • @RequestParam 用於將請求參數區數據映射到功能處理方法的參數上,value:參數名字,即入參的請求參數名字,如userName表示請求的參數區中的名字爲userName的參數的值將傳入,required:是否必須,默認是true,表示請求中一定要有相應的參數,否則將報404錯誤碼;

  • @Controller和@RestController的區別?

啓動類

package com.winterchen;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringBootMybatisHikaricpApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootMybatisHikaricpApplication.class, args);
    }
}

最終項目結構

這裏寫圖片描述

啓動

啓動項目啓動類

2018-07-25 15:25:42.970  INFO 22602 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-07-25 15:25:43.380  INFO 22602 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2018-07-25 15:25:43.382  INFO 22602 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Bean with name 'dataSource' has been autodetected for JMX exposure
2018-07-25 15:25:43.389  INFO 22602 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Located MBean 'dataSource': registering with JMX server as MBean [com.zaxxer.hikari:name=dataSource,type=HikariDataSource]
2018-07-25 15:25:43.450  INFO 22602 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2018-07-25 15:25:43.456  INFO 22602 --- [           main] c.w.SpringBootMybatisHikaricpApplication : Started SpringBootMybatisHikaricpApplication in 6.267 seconds (JVM running for 7.784)

這樣的輸出表示項目啓動成功了!!如果遇到報錯啓動不了,請回頭看看是不是有些地方沒有注意到。

測試

項目成功啓動了,那麼可以開始測試了

推薦使用一個強大的http請求工具:Postman

添加

這裏寫圖片描述

刪除

這裏寫圖片描述

更新

這裏寫圖片描述

查找

這裏寫圖片描述

最後

在編程的路上肯定會遇到很多的bug,程序員就是要不斷的和bug作鬥爭,加油,願你成爲真正的大牛。有機會講講Hikari如何使用多數據源。

源碼地址:戳這裏

springboot技術交流羣:681513531

個人博客:https://winterchen.com

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章