Spring Boot 默认数据源 HikariDataSource 与 JdbcTemplate

本文导读

  • Spring Boot 数据库访问 简介》中已经介绍,Spring Boot 可以通过多种方式访问各种数据库,本文将介绍 Spring Boot 内部集成的 JDBC 类访问 Mysql 数据库
  • 为了更加清晰明了,本文将新建项目进行说明。

环境准备

新建项目

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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>www.wmx.com.horse</groupId>
    <artifactId>horse</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>horse</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.4.RELEASE</version>
        <relativePath/>
        <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <!-- 引入Spring封装的jdbc-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <!-- 引入html模板引擎Thymeleaf-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <!-- 因为web项目启动模块-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- 引入mysql数据库连接驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

        <!-- 引入Spring Boot 测试模块-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!-- Spring Boot 打包插件-->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

mysql 数据库

  • 此 Mysql 数据是 CentOS 7.2 中的 Docker 容器中,所以用了 CentOS 的 3307 端口映射了 Docker 容器的 3306 端口,CentOS 主机 ip 为 192.168.58.129
  • 账号 root、密码 root

数据库 CRUD

全局配置文件

spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://192.168.58.129:3307/horse?characterEncoding=UTF-8
    driver-class-name: com.mysql.jdbc.Driver
  • 配置的内容以及意义就如同以前在 Sping 核心配置文件 beans.xml 中配置时是一样的
  • 到这里就已经可以操作数据库了,因为 Spring Boot 都已经自动配置好了,如 Spring Boot 默认已经提供了数据源
  • 关于上面的数据源配置内容,都可以从 Spring Boot 官方文档 查看
# DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
spring.datasource.continue-on-error=false # Whether to stop if an error occurs while initializing the database.
spring.datasource.data= # Data (DML) script resource references.
spring.datasource.data-username= # Username of the database to execute DML scripts (if different).
spring.datasource.data-password= # Password of the database to execute DML scripts (if different).
spring.datasource.dbcp2.*= # Commons DBCP2 specific settings
spring.datasource.driver-class-name= # Fully qualified name of the JDBC driver. Auto-detected based on the URL by default.
spring.datasource.generate-unique-name=false # Whether to generate a random datasource name.
spring.datasource.hikari.*= # Hikari specific settings
spring.datasource.initialization-mode=embedded # Initialize the datasource with available DDL and DML scripts.
spring.datasource.jmx-enabled=false # Whether to enable JMX support (if provided by the underlying pool).
spring.datasource.jndi-name= # JNDI location of the datasource. Class, url, username & password are ignored when set.
spring.datasource.name= # Name of the datasource. Default to "testdb" when using an embedded database.
spring.datasource.password= # Login password of the database.
spring.datasource.platform=all # Platform to use in the DDL or DML scripts (such as schema-${platform}.sql or data-${platform}.sql).
spring.datasource.schema= # Schema (DDL) script resource references.
spring.datasource.schema-username= # Username of the database to execute DDL scripts (if different).
spring.datasource.schema-password= # Password of the database to execute DDL scripts (if different).
spring.datasource.separator=; # Statement separator in SQL initialization scripts.
spring.datasource.sql-script-encoding= # SQL scripts encoding.
spring.datasource.tomcat.*= # Tomcat datasource specific settings
spring.datasource.type= # Fully qualified name of the connection pool implementation to use. By default, it is auto-detected from the classpath.
spring.datasource.url= # JDBC URL of the database.
spring.datasource.username= # Login username of the database.
spring.datasource.xa.data-source-class-name= # XA datasource fully qualified name.
spring.datasource.xa.properties= # Properties to pass to the XA data source.
  • 也可以从 org.springframework.boot.autoconfigure.jdbc.DataSourceProperties 数据源配置文件类中进行查看

默认数据源

package com.lct.www;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

@RunWith(SpringRunner.class)
@SpringBootTest
public class HorseApplicationTests {

    /**
     * Spring Boot 默认已经配置好了数据源,程序员可以直接 DI 注入然后使用即可
     */
    @Resource
    DataSource dataSource;

    @Test
    public void contextLoads() throws SQLException {

        System.out.println("数据源>>>>>>" + dataSource.getClass());
        Connection connection = dataSource.getConnection();

        System.out.println("连接>>>>>>>>>" + connection);
        System.out.println("连接地址>>>>>" + connection.getMetaData().getURL());
        connection.close();

    }
}
  • 运行之后控制台核心输出如下:

数据源>>>>>>class com.zaxxer.hikari.HikariDataSource
2018-08-19 09:31:31.689  INFO 8948 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2018-08-19 09:31:31.986  INFO 8948 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
连接>>>>>>>>>HikariProxyConnection@280862192 wrapping com.mysql.jdbc.JDBC4Connection@3ae0b770
连接地址>>>>>jdbc:mysql://192.168.58.129:3307/horse
2018-08-19 09:31:31.996  INFO 8948 --- [       Thread-2] o.s.w.c.s.GenericWebApplicationContext   : Closing org.springframework.web.context.support.GenericWebApplicationContext@dc7df28: startup date [Sun Aug 19 09:31:29 CST 2018]; root of context hierarchy
2018-08-19 09:31:31.998  INFO 8948 --- [       Thread-2] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2018-08-19 09:31:32.001  INFO 8948 --- [       Thread-2] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.

Process finished with exit code 0

  • 可以看出 Spring Boot 2.0.4 默认使用 com.zaxxer.hikari.HikariDataSource 数据源
  • 而以前版本,如 Spring Boot 1.5 默认使用 org.apache.tomcat.jdbc.pool.DataSource 作为数据源;
  • HikariDataSource 号称 Java WEB 当前速度最快的数据源,相比于传统的 C3P0 、DBCP、Tomcat jdbc 等连接池更加优秀
  • HikariDataSource 的内容本文暂时不做延伸
  • 有了数据库连接,显然就可以 CRUD 操作数据库了

CRUD 数据库

  • 有了数据源(com.zaxxer.hikari.HikariDataSource),然后拿到l了数据库连接(java.sql.Connection),自然就可以使用连接和原生的 JDCB 语句来操作数据库
  • 即使不使用第三方第数据库操作框架,如 MyBatis、Hibernate 、JDBC Utils 等,Spring 本身也对 原生的 JDBC 做了轻量级的封装,即 org.springframework.jdbc.core.JdbcTemplate。这原本是 Spring 的知识点!
  • 数据库操作的所有 CRUD 方法都在 JdbcTemplate 中,有了 JdbcTemplate 就能更加轻松的操作数据库。
  • Spring Boot 不仅提供了默认的数据源,同时默认已经配置好了 JdbcTemplate 放在了容器中,程序员只需自己注入即可使用
  • JdbcTemplate  的自动配置原理是依赖 org.springframework.boot.autoconfigure.jdbc 包下的 org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration 类

PhoneController

  • 为了尽可能符合实际开发,新建一个控制层,通过浏览器访问来进行 CRUD,但是不再进行细致的分层,如 dao、service、domain 等都省略

package com.lct.www.controller;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

/**
 * Created by Administrator on 2018/8/19 0019.
 */
@Controller
public class PhoneController {

    /**
     * JdbcTemplate 是 core 包的核心类,用于简化 JDBC 操作,还能避免一些常见的错误,如忘记关闭数据库连接
     * Spring Boot 默认提供了数据源,默认提供了 org.springframework.jdbc.core.JdbcTemplate
     * JdbcTemplate 中会自己注入数据源,使用起来也不用再自己来关闭数据库连接
     */
    @Resource
    JdbcTemplate jdbcTemplate;

    /**
     * 查询 phone 表所有数据
     *
     * @return
     */
    @ResponseBody
    @GetMapping("phoneList")
    public List<Map<String, Object>> userList() {
        /**
         * 查询 phone 表所有数据
         * List 中的1个 Map 对应数据库的 1行数据
         * Map 中的 key 对应数据库的字段名,value 对应数据库的字段值
         */
        List<Map<String, Object>> mapList = jdbcTemplate.queryForList("SELECT * FROM phone");
        return mapList;
    }

    /**
     * 新增 phone 数据
     *
     * @return
     */
    @GetMapping("savePhone")
    public String savePhone() {
        String sql = "INSERT INTO phone(number,region) VALUES (?,?)";
        Object[] objects = new Object[2];
        objects[0] = "18673886425";
        objects[1] = "湖南";

        jdbcTemplate.update(sql, objects);
        return "forward:/phoneList";
    }

    /**
     * 修改 phone 数据
     *
     * @return
     */
    @GetMapping("updatePhone")
    public String updatePhone() {
        String sql = "UPDATE phone SET number=? WHERE pid=?";
        Object[] objects = new Object[2];
        objects[0] = "18666668888";
        objects[1] = "1";

        jdbcTemplate.update(sql, objects);
        return "forward:/phoneList";
    }

    /**
     * 删除 phone 数据
     * update 方法可以做查询以外的 增加、修改、删除操作
     *
     * @return
     */
    @GetMapping("deletePhone")
    public String deletePhone() {
        String sql = "DELETE FROM phone WHERE number=?";
        Object[] objects = new Object[1];
        objects[0] = "18673886425";

        jdbcTemplate.update(sql, objects);
        return "forward:/phoneList";
    }
}

测试结果

  • 查询:http://localhost:8080/phoneList
  • 添加:http://localhost:8080/savePhone
  • 修改:http://localhost:8080/updatePhone
  • 删除:http://localhost:8080/deletePhone
  • 启动应用成功

some templates or check your Thymeleaf configuration)
2018-08-19 12:15:23.522  INFO 14052 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2018-08-19 12:15:23.525  INFO 14052 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Bean with name 'dataSource' has been autodetected for JMX exposure
2018-08-19 12:15:23.532  INFO 14052 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Located MBean 'dataSource': registering with JMX server as MBean [com.zaxxer.hikari:name=dataSource,type=HikariDataSource]
2018-08-19 12:15:23.573  INFO 14052 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2018-08-19 12:15:23.577  INFO 14052 --- [           main] com.lct.www.HorseApplication             : Started HorseApplication in 3.863 seconds (JVM running for 4.455)

自动配置原理

  • 自动配置都在 org.springframework.boot.autoconfigure.jdbc 包下可以找到

DataSourceConfiguration

  • org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration 数据源配置类作用是根据逻辑判断之后,添加数据源
  • SpringBoot 默认支持如下数据源;

com.zaxxer.hikari.HikariDataSource (Spring Boot 2.0 以上,默认使用此数据源)

org.apache.tomcat.jdbc.pool.DataSource

org.apache.commons.dbcp2.BasicDataSource

  • 可以使用 spring.datasource.type 指定自定义的数据源类型,值为 要使用的连接池实现的完全限定名。默认情况下,它是从类路径自动检测的。
    @ConditionalOnMissingBean({DataSource.class})
    @ConditionalOnProperty(
        name = {"spring.datasource.type"}
    )
    static class Generic {
        Generic() {
        }

        @Bean
        public DataSource dataSource(DataSourceProperties properties) {
            return properties.initializeDataSourceBuilder().build();
        }
    }

猜你喜欢

转载自blog.csdn.net/wangmx1993328/article/details/81834974
今日推荐