浅析Java数据库连接:从Jdbc到Datasource

浅析Java数据库连接:从JdbcDatasource


  在Java项目中,基本都会和数据库打交道,那一个需要访问数据库的web项目,我们一般是怎么搭建的呢?在应用运行过程中,我们的Java应用是如何和数据库通讯的呢?
  那我们带着这些一点问题,来从搭建一个数据库的web项目开始,来看一看Java和数据库交互的主要流程吧。
  本文语雀链接:https://www.yuque.com/theskyzero/qdl2y7/qbqai8

基于springboot搭建访问数据库的web项目

  项目仓库访问地址:https://gitee.com/theskyone/new-bird.git ,分支feature/jdbc

  首先,介绍下这个demo背景,我们准备用springboot快速搭建一个web项目,在这个web项目中将用到数据库。

  那么我们Java程序要访问一个数据库,需要准备哪些东西呢?

  1. 数据库选型:oraclemysql等等…
  2. 数据库连接驱动
  3. 数据库连接池:druidhikaritomcat等等…
  4. 数据映射/ormspring-jdbcmybatisjpa等。

  我们这里为示例的需要,选型为:

  1. 数据库:h2数据库,支持内存、文件数据库类型,支持SQL语言。
  2. 数据库连接驱动:h2的数据库驱动
  3. 数据库连接池:druid连接池。springboot2默认使用性能更好的hikari,我们使用久经考验的druid
  4. orm:使用spring-jdbc。这里我们主要探讨Java和数据库的交互过程,不拘泥于如mybatis在数据映射上的抽象封装。

使用springboot搭建一个web项目

  示例开发环境:IDEA+Maven+Git。示例程序:feature/jdbc

  使用springboot搭建一个web项目超级简单,我们只要做两件事情:

  1. 依赖spring-boot-starter-web
  2. 编写注解@SpringBootApplication的启动类

  这里我们创建的是多module项目,一些关键的配置如下:

<!-- 父pom.xml, 继承spring-boot-starter-parent-->

<?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">

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.4</version>
    </parent>

    <packaging>pom</packaging>

    <groupId>com.gitee.theskyone</groupId>
    <artifactId>new-bird</artifactId>
    <version>1.0-SNAPSHOT</version>

    <modules>
        <module>bird-web</module>
    </modules>
</project>
<!-- web子模块pom.xml 使用依赖 spring-boot-starter-web-->

<?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">
    <parent>
        <artifactId>new-bird</artifactId>
        <groupId>com.gitee.theskyone</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>bird-web</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
</project>
// SpringBoot启动类

package com.gitee.theskyone.bird;

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

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

  至此,我们可以直接运行WebApplication.main方法,启动一个web项目。

集成数据库相关依赖

   以上我们选型为h2+druid+spring-jdbc,那我们先添加相关的依赖。
  h2相关的依赖定义默认spring-boot-dependencies已经提供,我们这里使用druid-spring-boot-starter来提供druidspringboot的整合。

添加druid依赖管理

我们在parentpom.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">

    <parent>
        <artifactId>spring-boot-starter-parent</artifactId>
        <groupId>org.springframework.boot</groupId>
        <version>2.6.4</version>
    </parent>

    <modules>
        <module>bird-web</module>
    </modules>

    <properties>
        <!-- 依赖版本定义-->
        <druid-boot.version>1.2.8</druid-boot.version>
    </properties>

    <!-- 依赖管理定义 -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid-spring-boot-starter</artifactId>
                <version>${druid-boot.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

添加相关依赖

web项目中添加数据库、数据库驱动、数据库连接池、spring-jdbc依赖。

<?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">
    <parent>
        <artifactId>new-bird</artifactId>
        <groupId>com.gitee.theskyone</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>bird-web</artifactId>

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

        <!-- 1. 数据库 & 数据库驱动 -> h2-->
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
        </dependency>

        <!-- 2. 数据源 druid-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
        </dependency>

        <!-- 3. orm:spring-jdbc -->
        <dependency>
            <!-- 默认 HikariCP 数据源-->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
    </dependencies>
</project>

  在spring-boot-starter-jdbc中,spring默认为我们提供了HikariCP数据源。之后,我们会手动注入一个DruidDataSourceSpring容器内。

编码实现数据库访问功能

数据库初始化

  我们借助SqlInitializationAutoConfiguration来完成数据库初始化工作。并仍使用DataSourceProperties来提供数据源的配置。

  application.yml核心配置信息如下:

# h2 内存数据源配置
spring:
  datasource:
    # 内存数据库
    url: jdbc:h2:mem:test
    username: test
    password: test
    type: com.alibaba.druid.pool.DruidDataSource
  sql:
    init:
      schema-locations: classpath*:/sql/ddl.sql
# /sql/ddl.sql
create table simple
(
    id          bigint(20) auto_increment primary key comment '主键',
    name        varchar(30) not null comment '名称',
    description varchar(255) comment '描述',
    create_time timestamp default current_timestamp() comment '创建时间',
    update_time timestamp default current_timestamp() on update current_timestamp() comment '更新时间'
);

注入自定义druid数据源

  这里我们手动注入DataSource,会替换DruidDataSourceAutoConfigure默认注入的DruidDataSource

package com.gitee.theskyone.bird.jdbc.h2.ds;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.util.JdbcConstants;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Profile;

import javax.sql.DataSource;

/**
 * @see org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
 * @see com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
 */
@Configuration
@Profile("mem")
public class DruidDatasourceConfiguration {

    /**
     * 数据源:1. 管理数据库连接;  2. 连接数、保活...
     * 数据库连接:url + username + password + driver
     *
     * @return
     */
    @Bean
    @Primary
    DataSource druidDataSource(DataSourceProperties dataSourceProperties) {
        DruidDataSource druidDataSource = new DruidDataSource();
        // 数据库连接必须参数
        druidDataSource.setUrl(dataSourceProperties.determineUrl());
        druidDataSource.setUsername(dataSourceProperties.determineUsername());
        druidDataSource.setPassword(dataSourceProperties.determinePassword());
        druidDataSource.setDriverClassName(JdbcConstants.H2_DRIVER);    // 可选,druid可以通过url解析猜测

        // 数据源管理参数
        druidDataSource.setMinIdle(0);
        druidDataSource.setMaxActive(8);
        druidDataSource.setName("ds01");
        return druidDataSource;
    }
}

  这里要注意的一点是,仓库上的代码这里使用@Profile("mem"),仅当激活application-mem.yml时配置类生效。当前默认激活使用的是application-druid.yml,使用的是druid-spring-boot-starter的自动配置。

编码持久层对象及数据访问层

// SimplePO.java -> 持久层对象

package com.gitee.theskyone.bird.jdbc.h2.po;

import lombok.Data;
import java.time.Instant;

@Data
public class SimplePO {
    Long id;
    String name;
    String description;
    Instant createTime;
    Instant updateTime;
}
// SimpleJdbcTemplateDao.java -> 使用JdbcTemplate实现的数据访问层

package com.gitee.theskyone.bird.jdbc.h2.dao;

import com.gitee.theskyone.bird.jdbc.h2.po.SimplePO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import java.util.List;

@Repository
public class SimpleJdbcTemplateDao {

    @Autowired
    JdbcTemplate jdbcTemplate;

    public void insert(SimplePO po) {
        String insertSql = "insert into simple(name,description) values(?,?)";
        jdbcTemplate.update(insertSql, po.getName(), po.getDescription());
    }

    public List<SimplePO> selectAll() {
        String selectAll = "select * from simple";
        return jdbcTemplate.query(selectAll, new BeanPropertyRowMapper(SimplePO.class));
    }
}

  JdbcTemplate还是比较原生的用法,直接通过DataSource获取数据库连接,并执行SQL语句。点开JdbcTemplate的实现,我们可以看到熟悉ConnectionPreparedStatementResultSet等等。

  那么到这里,一般我们Java应用和数据库如何通过Jdbc通讯的过程就出来了,总结一下:

  1. 通过DataSource获取和数据库的连接Connection
  2. 通过Connection向数据库请求执行Statement,返回响应。

  当然,这里的Connection是如何建立的呢?以上我们并未提及到,大家也可以跟踪下DataSource.getConnection()的实现,其实最终都是通过连接驱动Driver.connect()建立产生。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

theskyzero

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值