對於數據庫連接池的一些思考和MyBatis的集成與使用


  Java應用要連接數據庫需要先通過jdbc與數據庫之間產生connection,然后通過sql語句產生statment,再執行這個statment查詢的到ResultSet返回給應用,應用解析ResultSet獲得Java支持類型的結果。

這里存在以下幾個問題:

  1. 產生連接本身需要,而且這個延時比起常規的查詢操作來說是較高的,對於有響應時限的操作來說這是一個致命問題。
  2. 建立連接需要消耗數據庫資源,數據庫本身開放的連接數量是有限的,即使不斷的建立與關閉連接保證總數的穩定,也會極大消耗數據庫資源影響性能。而數據庫資源比起應用服務器來說又是非常寶貴的,數據庫的分流比應用要困難很多。

  所以要避免這種情況就有了連接池。連接池有幾個基本屬性:初始連接數、最大連接數、最小空閑數、最大空閑數、最大等待毫秒數,分別假設為5 10 1 5 60。連接池可以想象為一個池子,先建立5個連接放入池子中。應用的一個線程需要與數據庫交互時,向連接池要一個連接,然后去執行,執行完后會將連接還給連接池。當並發量很高時,連接池內的連接會被取完,此時又有線程要連接,就會檢查是否達到了最大連接數,如果沒達到就會繼續新建連接,將連接交給線程。如果達到上限,則讓線程進行等待,知道有線程把連接還回來。

  當連接池內的連接數超過了最大空閑數時,當這個連接被歸還連接池,它就會被強制關閉。而當連接池內的連接數小於最小空閑數時,連接池會自動去新建連接來補充到這個數量。為什么連接數量自己會變化呢?因為數據庫存在一個連接的等待時間,超過這個時間始終沒有活動的話,連接會被數據庫關閉,連接池會周期性的去探知所有連接是否存活,以管理連接的數量。

  所謂持久層,是指將數據長期存儲到硬盤當中。因為在webapp開發中數據通過數據庫存儲到硬盤中,所以持久層可以簡單的認為就是負責對數據庫的增刪改查。用過Java原始jdbc的查詢的話都知道ResultSet要轉換成Java Bean中間的重復操作還是挺多的;要把一個List<T>轉換成SQL語句也挺麻煩的,持久層框架的好處之一就是省略掉這中間的重復操作,根據寫好的映射關系,直接完成數據庫與Java代碼之間交互。

  常用的持久層框架有兩個:MyBatis和Hibernate。MyBatis最大的特點是SQL語句基本就是沒有任何封裝的原生SQL。缺點當然是開發起來工作量較大,同時不同數據庫之間的遷移性收到影響。優點是學習簡單,SQL自由性大,也就有更大的優化空間。畢竟正常情況下你能夠控制的東西越多,開發就會越復雜,但是性能極限會更高,當然這里的前提是開發者足夠資深,畢竟一般人寫的代碼不如編譯器優化出來的。

  下面開始SSM框架下的這個M的搭建。首先,pom.xml里面引入相關的依賴,包括mybatis本身、Spring的支持插件、mysql驅動,以及連接池創建工具這里采用dbcp

        <!--mysql數據庫驅動 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.38</version>
        </dependency>

        <!-- mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.1</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>
        <!-- 連接池創建 -->
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.4</version>
        </dependency>

然后配置數據源的話有兩種方式,一種是直接配置數據源,還有一種是基於容器的數據源比如tomcat下的jndi連接。

直接配置的話,在applicationContext.xml,即通過ContextLoaderListener監聽的配置文件里面添加如下:

<!-- 配置jdbc文件 -->
    <bean id="propertyConfigurer"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations" value="classpath:jdbc.properties" />
    </bean>
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName" value="${driver}" />
        <property name="url" value="${url}" />
        <property name="username" value="${username}" />
        <property name="password" value="${password}" />
        <!-- 初始化連接大小 -->
        <property name="initialSize" value="${initialSize}" />
        <!-- 連接池最大數量 -->
        <property name="maxActive" value="${maxActive}" />
        <!-- 連接池最大空閑 -->
        <property name="maxIdle" value="${maxIdle}" />
        <!-- 連接池最小空閑 -->
        <property name="minIdle" value="${minIdle}" />
        <!-- 獲取連接最大等待時間 -->
        <property name="maxWait" value="${maxWait}" />
    </bean>

    <!-- spring和MyBatis完美整合,不需要mybatis的配置映射文件 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <!-- 自動掃描mapping.xml文件,**表示迭代查找 -->
        <property name="mapperLocations" value="classpath:com/web/**/*.xml" />
    </bean>

    <!-- DAO接口所在包名,Spring會自動查找其下的類 ,包下的類需要使用@MapperScan注解,否則容器注入會失敗 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.web" />
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
    </bean>

    <!-- (事務管理)transaction manager, use JtaTransactionManager for global tx -->
    <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

這里采用外部讀入參數的方式加載用戶名信息,便於統一管理。resources目錄下添加jdbc.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf8
username=root
password=123456
initialSize=5
maxActive=10
maxIdle=5
minIdle=1
maxWait=60

然后添加dao層Bean層與對應的xml映射文件

<?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.web.dao.TestMapper">
    <select id="getTest" resultType="com.web.bean.HelloBean">
        select id,txt from test
    </select>
</mapper>
package com.web.dao;

import java.util.List;

import org.mybatis.spring.annotation.MapperScan;

import com.web.bean.HelloBean;

@MapperScan
public interface TestMapper {
    public List<HelloBean> getTest();
}
package com.web.bean;

public class HelloBean {
    private String id;
    private String txt;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getTxt() {
        return txt;
    }

    public void setTxt(String txt) {
        this.txt = txt;
    }

}

全部添加完后,項目的路徑如下:

 

然后通過注入dao層類之后執行testMapper.getTest(),表與插入的測試數據可以參見我上一篇文章。結果下:

 

說明數據已經直接映射到了結果的bean上面。

  第二種方法,就是利用tomcat來創建連接池,然后mybatis直接只用tomcat的數據源。先配置context.xml

<Resource name="jdbc/mybatis-jndi" auth="Container" type="javax.sql.DataSource"
        maxActive="100" maxIdle="30" maxWait="10000" username="root" password="123456"
        driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/demo" />

然后在applicationContext.xml文件上添加jndi數據源,並修改mybatis使用的數據源java:comp/env/這里是固定字段,后面的jdbc/mybatis-jndi對應context里面配置的name屬性

    <bean id="jndiDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName">
            <value>java:comp/env/jdbc/mybatis-jndi</value>
        </property>
    </bean>

    <!-- spring和MyBatis完美整合,不需要mybatis的配置映射文件 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- ref是使用的數據源 -->
        <property name="dataSource" ref="jndiDataSource" />
        <!-- 自動掃描mapping.xml文件,**表示迭代查找 -->
        <property name="mapperLocations" value="classpath:com/web/**/*.xml" />
    </bean>

  MyBatis的集成至此完成。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM