JAVA【20】连接池Template

今日内容

  • 数据库连接池
  • Spring JDBC : JDBC Template

一、数据库连接池

1. 概念

其实就是一个容器(集合),存放数据库连接的容器。
当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后,会将连接对象归还给容器。


在这里插入图片描述


2. 好处

  • 节约资源
  • 用户访问高效

3. 实现:两种方式

(1)标准接口:DataSource javax.sql包下的

获取连接:getConnection()
归还连接:Connection.close()。如果连接对象Connection是从连接池中获取的,那么调用Connection.close()方法,则不会再关闭连接了。而是归还连接到池中。

(2) 一般我们不去实现它,有数据库厂商来实现

C3P0:数据库连接池技术
Druid:数据库连接池实现技术,由阿里巴巴提供

4. C3P0:数据库连接池技术

(1)步骤

① 导入jar包 (两个) c3p0-0.9.5.2.jar mchange-commons-java-0.2.12.jar
-------不要忘记导入数据库驱动jar包
② 定义配置文件:
-------名称: c3p0.properties 或者 c3p0-config.xml
-------路径:直接将文件放在src目录下即可。

③ 创建核心对象 数据库连接池对象 ComboPooledDataSource
④ 获取连接: getConnection

(2)入门代码

导入依赖pom.xml

 <dependencies>
     <dependency>
         <groupId>c3p0</groupId>
         <artifactId>c3p0</artifactId>
         <version>0.9.1.2</version>
     </dependency>
     <dependency>
         <groupId>mysql</groupId>
         <artifactId>mysql-connector-java</artifactId>
         <version>8.0.17</version>
     </dependency>
 </dependencies>

配置文件c3p0-config.xml

<c3p0-config>
  <!-- 使用默认的配置读取连接池对象 -->
  <default-config>

    <!--  连接参数 -->
    <property name="driverClass">com.mysql.cj.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/db2?characterEncoding=utf8&amp;useSSL=false&amp;serverTimezone=UTC</property>
    <property name="user">root</property>
    <property name="password">password</property>
    
    <!-- 连接池参数 -->
    <!--初始化申请的连接数量-->
    <property name="initialPoolSize">5</property>
    <!--最大的连接数量-->
    <property name="maxPoolSize">10</property>
    <!--超时时间-->
    <property name="checkoutTimeout">3000</property>
  </default-config>
  
</c3p0-config>

测试文件java

public static void main(String[] args) throws SQLException {
    //1.创建数据库连接池对象
    DataSource ds = new ComboPooledDataSource();
    //2.获取连接对象
    Connection  conn= ds.getConnection();

    System.out.println(conn);
}
(3)常用参数验证

导入依赖pom.xml
配置文件c3p0-config.xml

<c3p0-config>
  <!-- 使用默认的配置读取连接池对象 -->
  <default-config>
    <!--  连接参数 -->
    <property name="driverClass">com.mysql.cj.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/db2?characterEncoding=utf8&amp;useSSL=false&amp;serverTimezone=UTC</property>
    <property name="user">root</property>
    <property name="password">password</property>
    
    <!-- 连接池参数 -->
    <!--初始化申请的连接数量-->
    <property name="initialPoolSize">5</property>
    <!--最大的连接数量-->
    <property name="maxPoolSize">10</property>
    <!--超时时间-->
    <property name="checkoutTimeout">3000</property>
  </default-config>

  <named-config name="otherc3p0"> 
    <!--  连接参数 -->
    <property name="driverClass">com.mysql.cj.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/db2?characterEncoding=utf8&amp;useSSL=false&amp;serverTimezone=UTC</property>
    <property name="user">root</property>
    <property name="password">password</property>
    
    <!-- 连接池参数 -->
    <property name="initialPoolSize">5</property>
    <property name="maxPoolSize">8</property>
    <property name="checkoutTimeout">1000</property>
  </named-config>

</c3p0-config>

测试代码Demotest

public class C3P0Demo02 {

    /**
        设置最大的连接数量
        <property name="maxPoolSize">10</property>
     */

    @Test//正常获取10个连接
    public void test1() throws SQLException {
        //1.创建数据库连接池对象
        DataSource ds = new ComboPooledDataSource();
        //2.获取连接
        for (int i = 0; i <10 ; i++) {
            Connection  conn= ds.getConnection();
            System.out.println(i+""+conn);
        }
    }

    @Test//获取连接数 > 池中连接数
    public void test2() throws SQLException {
        //1.创建数据库连接池对象
        DataSource ds = new ComboPooledDataSource();
        //2.获取连接
        for (int i = 0; i <11 ; i++) {
            Connection  conn= ds.getConnection();
            System.out.println(i+""+conn);
        }
        //第十个输出正常,等待三秒,出异常,第11为获取失败
    }

    @Test
    public void test3() throws SQLException {
        //1.创建数据库连接池对象
        DataSource ds = new ComboPooledDataSource();
        //2.获取连接
        for (int i = 0; i <11 ; i++) {
            Connection  conn= ds.getConnection();
            System.out.println(i+""+conn);
            if (i==5){//第6个归还,第11个正常显示
                conn.close();
            }
        }
    }

     
    /*
      《《《使用非默认配置》》》

        <!-- 使用默认的配置读取连接池对象 -->
          <default-config>默认使用</default-config>
          //非默认配置
          <named-config name="otherc3p0">
              <!--  连接参数 -->
              <property name="driverClass">   <property name="jdbcUrl">
              <property name="user">  <property name="password">

              <!-- 连接池参数 -->
              <property name="maxPoolSize">8</property>
          </named-config>
     */
    @Test
    public void test4() throws SQLException {
        //1.创建数据库连接池对象
        //DataSource ds = new ComboPooledDataSource();
        //1.1获取DataSource,使用指定名称配置
        DataSource ds = new ComboPooledDataSource("otherc3p0");
        //2.获取连接
        for (int i = 0; i <10 ; i++) {
            Connection  conn= ds.getConnection();
            System.out.println(i+""+conn);
        }
        //指定配置最大连接数为8,第九个出错 TimeoutException
    }
}

5. Druid

数据库连接池实现技术,由阿里巴巴提供的

(1) 步骤

1.导入jar包 druid-1.0.9.jar
2. 定义配置文件:
--------是properties形式的
--------可以叫任意名称,可以放在任意目录下
3. 加载配置文件。Properties(c3p0会自动加载,它不会)
4. 获取数据库连接池对象:通过工厂来来获取 DruidDataSourceFactory
5. 获取连接:getConnection

代码:

a. 导入依赖pom.xml

<dependencies>
   <dependency>
       <groupId>mysql</groupId>
       <artifactId>mysql-connector-java</artifactId>
       <version>8.0.17</version>
   </dependency>
   
   <dependency>
       <groupId>com.alibaba</groupId>
       <artifactId>druid</artifactId>
       <version>1.0.9</version>
   </dependency>
</dependencies>

b. 定义配置文件druid.properties

driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/db2?useSSL=false&serverTimezone=UTC
username=root
password=password

# 初始化连接数量
initialSize=5
# 最大连接数
maxActive=10
# 最大等待时间
maxWait=3000

c. 编写代码

@Test
public void test1() throws Exception {
    //1.导入jar包druid-1.0.9
    //2.定义配置文件druid.properties

    //3.加载配置文件
    Properties pro = new Properties();
    pro.load(DruidDemo01.class.getClassLoader().getResourceAsStream("druid.properties"));

    //4.获取连接池对象
    DataSource ds = DruidDataSourceFactory.createDataSource(pro);

    //5.获取连接
    Connection conn = ds.getConnection();
    System.out.println(conn);
}
(2)定义工具类
  1. 定义一个类 JDBCUtils
  2. 提供静态代码块加载配置文件,初始化连接池对象
  3. 提供方法
    * 获取连接方法:通过数据库连接池获取连接
    * 释放资源
    * 获取连接池的方法

注意: 实用工具类需要导读依赖,编写配置文件

工具类代码:

public class DruidUtils {

    //1.定义成员变量 DataSource
    private static DataSource ds;
    
    static {
        try {
            //1.加载配置文件
            Properties pro = new Properties();
            pro.load(DruidUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
            //2.获取DataSource
            ds = DruidDataSourceFactory.createDataSource(pro);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 获取连接的方法
     * @return
     * @throws SQLException
     */
    public static Connection getConnection() throws SQLException {
        return ds.getConnection();
    }

    /**
     * 释放归还资源
     * @param rs
     * @param stmt
     * @param conn
     */
    public static void close(ResultSet rs,Statement stmt, Connection conn){

        if (rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (stmt!=null){
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (conn!=null){
            try {
                conn.close();//归还连接
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

    }
    
    public static void close(Statement stmt,Connection conn){
    /*
        if (stmt!=null){
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (conn!=null){
            try {
                conn.close();//归还连接
            } catch (SQLException e) {
                e.printStackTrace();
            }
     }*/
        close(null,stmt,conn);
    }

    /**
     * 获取连接池对象DataSource
     * @return
     */
    public static DataSource getDataSource(){
        return ds;
    }
}
(3)测试类
@Test//添加一条记录到account表中
public void testInsert(){

    Connection conn = null;
    PreparedStatement ps = null;
    //1.加载驱动
        //连接池帮助我们完成

    try {
        //2.获取数据库连接对象
        conn = DruidUtils.getConnection();

        //3.定义sql语句
        String sql = "insert into account value(null,?,?)";

        //4.获取执行SQL语句的 prepareStatement对象
        ps = conn.prepareStatement(sql);
        ps.setString(1,"huawei");
        ps.setInt(2,888);

        //5.执行SQL语句
        int count = ps.executeUpdate();

        //6.处理结果集
        if (count>0){
            System.out.println("执行成功");}
        else{
            System.out.println("执行失败");
        }


    } catch (SQLException e) {
        e.printStackTrace();
    }finally {
        //7.释放归还资源
        DruidUtils.close(ps,conn);
    }

}

二、Spring JDBC

Spring框架对JDBC的简单封装。提供了一个JDBCTemplate对象简化JDBC的开发

1、使用步骤

(1)导入jar包

在这里插入图片描述

(2)创建JdbcTemplate对象。依赖于数据源DataSource

JdbcTemplate template = new JdbcTemplate(ds);

(3)调用JdbcTemplate的方法来完成CRUD的操作
 1、update():执行DML语句。增、删、改语句

 2、queryForMap():查询结果将结果集封装为map集合,
 	将列名作为key,将值作为value 将这条记录封装为一个map集合 		
 	注意:这个方法查询的结果集长度只能是1

 3、queryForList():查询结果将结果集封装为list集合 		
 	注意:将每一条记录封装为一个Map集合,再将Map集合装载到List集合中

 4、query():查询结果,将结果封装为JavaBean对象 		
 	query的参数:RowMapper 			
		一般我们使用BeanPropertyRowMapper实现类。可以完成数据到JavaBean的自动封装 			
 		new BeanPropertyRowMapper<类型>(类型.class)

 5、queryForObject:查询结果,将结果封装为对象 		
	 注意:一般用于聚合函数的查询
(4)入门程序
@Test//1.更新操作
public void test1(){
    //1.导入jar
    //2.创建JDBCTemplate对象
    JdbcTemplate template = new JdbcTemplate(DruidUtils.getDataSource());
    //3.调用方法
    String sql = "update account set balance = ? where id = 2";
    int count = template.update(sql, 300);
    System.out.println(count);
}
(5)练习
  1. 修改1号数据的 balance 为 10000
  2. 添加一条记录
  3. 删除刚才添加的记录
  4. 查询id为1的记录,将其封装为Map集合
  5. 查询所有记录,将其封装为List
  6. 查询所有记录,将其封装为Account对象的List集合
  7. 查询总记录数

2、代码

import cn.itcast.domain.Emp;
import cn.itcast.utils.JDBCUtils;
import org.junit.Test;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;

import java.sql.Date;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

public class JdbcTemplateDemo2 {

   
    @Test//1.修改1号数据的 balance 为 10000
    public void test1(){
        //1.获取JDBCTemplate对象
        JdbcTemplate template = new JdbcTemplate(DruidUtils.getDataSource());
        String sql = "update account set balance = ? where id = ?";
        template.update(sql,10000,1);
    }

    @Test//2.添加一条记录
    public void test2(){
        //1.获取JDBCTemplate对象
        JdbcTemplate template = new JdbcTemplate(DruidUtils.getDataSource());
        String sql = "insert into account value(null,?,?)";
        int insert = template.update(sql, "seleina", 47800);
        System.out.println(insert);

    }

    @Test//3.删除刚才添加的记录
    public void test3(){
        //1.获取JDBCTemplate对象
        JdbcTemplate template = new JdbcTemplate(DruidUtils.getDataSource());
        String sql = "delete from account where name=?";
        int delete = template.update(sql, "seleina");
        System.out.println(delete);
    }
    
    /**
     * 4.查询id为1的记录,将其封装为Map集合
     * 		注意:这个方法查询的结果集长度只能是1
     */
    public void test4(){
        //1.获取JDBCTemplate对象
        JdbcTemplate template = new JdbcTemplate(DruidUtils.getDataSource());
        String sql = "select * from account where id = ?";
        //只能返回一条记录:key为数据库字段名,value为值
        Map<String, Object> map = template.queryForMap(sql,1);

        Set<String> sets = map.keySet();
        for (String set : sets) {
            System.out.println(set+":"+map.get(set));
        }
        /*
            id:1
            NAME:zhangsan
            balance:10000.0
         */
    }

	/**
		5.查询所有记录,将其封装为List
	*/
    @Test
    public void test5(){
        //1.获取JDBCTemplate对象
        JdbcTemplate template = new JdbcTemplate(DruidUtils.getDataSource());
        String sql  = "select * from account";
        //返回多条记录:list集合元素中为map,key为字段名,value为值
        List<Map<String, Object>> lists = template.queryForList(sql);

        for(Map<String, Object> map : lists) {
            Set<String> sets = map.keySet();
            for (String set : sets) {
                System.out.print(set+":"+map.get(set)+"\t");
            }
            System.out.println();
        }

        /*
            id:1	NAME:zhangsan	balance:10000.0
            id:2	NAME:lisi	balance:300.0
         */
    }

    /**
     * 6.1. 查询所有记录,将其封装为Account对象的List集合
     */

    @Test
    public void test66(){
        //1.获取JDBCTemplate对象
        JdbcTemplate template = new JdbcTemplate(DruidUtils.getDataSource());
        String sql = "select * from account";
        //2.返回值是list<Account>
        List<Account> list = template.query(sql, new RowMapper<Account>() {
            @Override
            public Account mapRow(ResultSet rs, int rowNum) throws SQLException {
                Account account = new Account();
                account.setId(rs.getInt(1));
                account.setName(rs.getString(2));
                account.setBalance(rs.getDouble(3));
                return account;
            }
        });

        for (Account account : list) {
            System.out.println(account);
        }
    }

    /**
     * 6.2. 查询所有记录,将其封装为Account对象的List集合
     */

    @Test
    public void test6(){
        //1.获取JDBCTemplate对象
        JdbcTemplate template = new JdbcTemplate(DruidUtils.getDataSource());
        String sql = "select * from account";
        //2.返回值是list<Account>
        List<Account> list = template.query(sql, new BeanPropertyRowMapper<Account>(Account.class));

        for (Account account : list) {
            System.out.println(account);
        }
    }

    /**
     * 7. 查询总记录数
     */

   @Test
    public void test7(){
        //1.获取JDBCTemplate对象
        JdbcTemplate template = new JdbcTemplate(DruidUtils.getDataSource());
        String sql = "select count(*) from account";
        //2.查询结果,将结果封装为对象,一般用于聚合函数,第二个参数为返回值类型.class
        Integer count = template.queryForObject(sql, Integer.class);
        System.out.println(count);
    }

}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值