持续学习&持续更新中…

守破离



【Java从零到架构师第③季】【05】MyBatis集成数据库连接池

  • 为什么要集成数据库连接池
  • 回顾之前如何使用数据库连接池
  • MyBatis集成数据库连接池
  • DruidDataSourceFactory的实现方式
  • 在mybatis-config起别名
  • druid的properties设置
  • 方法一
  • 方法二
  • 方法三
  • 方法四
  • 参考


为什么要集成数据库连接池

数据库连接池可以提高访问数据库的性能,负责创建、分配、管理和释放数据库连接。

  • 实际开发时,并不会直接使用MyBatis内置的连接池
  • MyBatis内置连接池是没有那些专门做连接池的连接池好用的(比如druid、C3P0连接池)
  • MyBatis内置连接池也没有那些连接池专业

回顾之前如何使用数据库连接池

  • 首先在maven项目的resource目录下新建druid.properties文件
  • 然后在该文件中写入:
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/lp_resume
username=root
password=root
initialSize=5
maxActive=10
maxWait=5000
  • Java②课程中使用SpringJDBC+Druid
static {
        try (InputStream is = WebsiteDaoImpl.class.getClassLoader().getResourceAsStream("druid.properties")) {
            Properties properties = new Properties();
            properties.load(is);
            JDBCTEMPLATE = new JdbcTemplate(DruidDataSourceFactory.createDataSource(properties));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
  • 可以看到使用如下语句来创建dataSource对象:
DruidDataSourceFactory.createDataSource(properties)
  • 如果不使用SpringJDBC,直接使用Druid的dataSource是这样使用的:
PreparedStatement preparedStatement = dataSource.getConnection().prepareStatement(sql)
  • 获取到preparedStatement 就可以去执行数据库操作了
  • 注意:不要自己去关闭获取到的Connection对象dataSource.getConnection(),现在你已经使用Druid数据库连接池了,人家Druid连接池会自动管理的。
  1. 该对象不是自己创建的,不需要自己负责任
  2. 不要随意更改别人的代码,因为有可能出问题做好自己的本职工作即可
  • 至此,回顾已经完毕。

MyBatis集成数据库连接池

以Druid数据库连接池为例,其他数据库连接池集成的操作方法类似。

mybatis连接池配置 mysql数据库 mybatis的数据库连接池_数据库

mybatis连接池配置 mysql数据库 mybatis的数据库连接池_mysql_02

  • pom.xml:
<dependency>
	    <groupId>com.alibaba</groupId>
	    <artifactId>druid</artifactId>
	    <version>1.1.22</version>
	</dependency>
  • 新建一个DruidDataSourceFactory.java(类名可以随意,但最好这样,比较规范)
public class DruidDataSourceFactory extends UnpooledDataSourceFactory {

    public DruidDataSourceFactory() {
        this.dataSource = new DruidDataSource();
    }

}
  • mybatis-config.xml中
<environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="programmer.lp.DruidDataSourceFactory">
                <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/test_mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
                <!-- 以下为可选项 -->
                <property name="initialSize" value="5"/>
                <property name="maxActive" value="10"/>
                <property name="maxWait" value="5000"/>
            </dataSource>
        </environment>

DruidDataSourceFactory的实现方式

  • DruidDataSourceFactory其实有两种实现方法,分别是:
  1. 继承PooledDataSourceFactory
  2. 继承UnpooledDataSourceFactory(推荐)

mybatis连接池配置 mysql数据库 mybatis的数据库连接池_Source_03

mybatis连接池配置 mysql数据库 mybatis的数据库连接池_数据库_04

那么为什么推荐使用继承UnpooledDataSourceFactory这种方法呢?因为这样做可以少调用一次父类的构造方法,更会少一步创建PooledDataSource对象

  • 观察PooledDataSourceFactory,发现它是继承自UnpooledDataSourceFactory的,只是将dataSource的实现重写为PooledDataSource了
  • 也就是说PooledDataSourceFactory和UnpooledDataSourceFactory其他的实现都是一样的,只是dataSource数据源不同

mybatis连接池配置 mysql数据库 mybatis的数据库连接池_bc_05

mybatis连接池配置 mysql数据库 mybatis的数据库连接池_java_06

  • 既然我们此时已经将dataSource重新设置为了DruidDataSource:
this.dataSource = new DruidDataSource();
  • 因此就没有必要继承PooledDataSourceFactory了,直接继承UnpooledDataSourceFactory即可
  • 如果自己实现的DruidDataSourceFactory是继承自PooledDataSourceFactory的话,肯定会多一层父类方法的调用,肯定会先经过PooledDataSourceFactory的构造方法,然后再调用UnpooledDataSourceFactory的构造方法,然后会创建UnpooledDataSource对象和PooledDataSource对象
  • 如果直接继承自UnpooledDataSourceFactory的话,就只会调用UnpooledDataSourceFactory的构造方法,只会多余创建一个对象:UnpooledDataSource对象
  • 注意:虽然我们现在继承的是UnpooledDataSourceFactory,但是不要被类名所迷惑,认为我们没有使用数据库连接池技术
  • 我们刚才已经分析了:PooledDataSourceFactory和UnpooledDataSourceFactory的区别就是dataSource不同,一个是PooledDataSource,一个是UnpooledDataSource。其他的实现都是一样的
  • 那么可以得到一个结论:UpPooledDataSource之所以没有可以不使用数据库连接池技术是因为它的数据源是UnpooledDataSource;PooledDataSourceFactory之所以使用数据库连接池技术是因为它的数据源是PooledDataSource
  • 但是我们现在已经将dataSource重新设置为了DruidDataSource,使用的数据源是DruidDataSource,那么,使用的数据库连接池技术就是Druid,因此虽然我们继承的是UnpooledDataSourceFactory,但还是使用了连接池技术的。

在mybatis-config起别名

  • mybatis-config.xml中,之前使用MyBatis的默认连接池技术时,dataSource的type为POOLED,如果不使用数据库连接池技术则dataSource的type为UNPOOLED
  • POOLED和UNPOOLED其实就分别对应的是org.apache.ibatis.datasource.pooled.PooledDataSourceFactoryorg.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory
  • 不难看出,MyBatis内部预先已经定义好了这两个类型的别名
  • 因此,dataSource的type也可以写为:pooled或者unpooled
  • 同样的,transactionManager的type之前一直都是JDBC
  • JDBC同样也是别名,因此也可以写为jdbc
  • 因为别名一旦被定义,是不区分大小写的
  • 同样的,我们也可以给自己实现的DruidDataSourceFactory定义别名:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- ... -->
    <typeAliases>
 	    <!-- ... -->
        <typeAlias type="programmer.lp.DruidDataSourceFactory" alias="druid"/>
    </typeAliases>
    <environments default="development">
    <!-- ... -->
        <environment id="development">
            <transactionManager type="JDBC"/>
            <!-- <dataSource type="druid"> -->
            <dataSource type="DRUID">
                <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/test_mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    <!-- ... -->
    </environments>
    <!-- ... -->
</configuration>

druid的properties设置

MyBatis会自动将property设置到dataSource上去

方法一
<configuration>
    <!-- ... -->
    <typeAliases>
        <!-- ... -->
        <typeAlias type="programmer.lp.DruidDataSourceFactory" alias="druid"/>
    </typeAliases>
    <environments default="development">
    	<!-- ... -->
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="DRUID">
                <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/test_mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
        <!-- ... -->
    </environments>
    <!-- ... -->
</configuration>
方法二
<configuration>
    <properties>
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/test_mybatis"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </properties>
    <!-- ... -->
    <typeAliases>
        <!-- ... -->
        <typeAlias type="programmer.lp.DruidDataSourceFactory" alias="druid"/>
    </typeAliases>
    <environments default="development">
    	<!-- ... -->
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="druid">
                <property name="driverClassName" value="${driverClassName}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
        <!-- ... -->
    </environments>
    <!-- ... -->
</configuration>
方法三

druid.properties:

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test_mybatis
username=root
password=root

mybatis-config.xml:

<configuration>
    <properties resource="druid.properties" />
    <!-- ... -->
    <typeAliases>
        <!-- ... -->
        <typeAlias type="programmer.lp.DruidDataSourceFactory" alias="druid"/>
    </typeAliases>
    <environments default="development">
    	<!-- ... -->
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="druid">
                <property name="driverClassName" value="${driverClassName}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
        <!-- ... -->
    </environments>
    <!-- ... -->
</configuration>
方法四

druid的容错率很高,使用driverClass代替driverClassName也可以

druid.properties:

dev.driverClass=com.mysql.jdbc.Driver
dev.url=jdbc:mysql://localhost:3306/test_mybatis
dev.username=root
dev.password=root
dev.initialSize=5
dev.maxActive=10
dev.maxWait=5000
pdr.driverClass=com.mysql.jdbc.Driver
pdr.url=jdbc:mysql://localhost:3306/lp_resume
pdr.username=root
pdr.password=root
pdr.initialSize=5
pdr.maxActive=10
pdr.maxWait=5000

mybatis-config.xml:

<configuration>
    <properties resource="druid.properties" />
    <!-- ... -->
    <typeAliases>
        <!-- ... -->
        <typeAlias type="programmer.lp.DruidDataSourceFactory" alias="druid"/>
    </typeAliases>
    <environments default="development">
    	<!-- ... -->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="DRUID">
                <property name="driverClass" value="${dev.driverClass}"/>
                <property name="url" value="${dev.url}"/>
                <property name="username" value="${dev.username}"/>
                <property name="password" value="${dev.password}"/>
                <property name="initialSize" value="${dev.initialSize}"/>
                <property name="maxActive" value="${dev.maxActive}"/>
                <property name="maxWait" value="${dev.maxWait}"/>
            </dataSource>
        </environment>
        <environment id="production">
            <transactionManager type="JDBC"/>
            <dataSource type="DRUID">
                <property name="driverClass" value="${pdr.driverClass}"/>
                <property name="url" value="${pdr.url}"/>
                <property name="username" value="${pdr.username}"/>
                <property name="password" value="${pdr.password}"/>
                <property name="initialSize" value="${pdr.initialSize}"/>
                <property name="maxActive" value="${pdr.maxActive}"/>
                <property name="maxWait" value="${pdr.maxWait}"/>
            </dataSource>
        </environment>
        <!-- ... -->
    </environments>
    <!-- ... -->
</configuration>

参考

小码哥-李明杰:


本文完,感谢您的关注支持!