by konley

mysql进阶第二篇,c3p0连接池、Druid连接池和Spring JDBCTemplate

一、连接池

1.1 概念

连接池就是一个容器(集合),存放数据库连接的容器

当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后,会将连接对象归还给容器

1.2 优点

  • 节约资源
  • 访问高效

1.3 实现

官方提供了一个标准接口javax.sql.DataSource

DataSource 接口提供以下方法:

  • 获取连接:Connection getConnection()
  • 归还连接:Connection.close()

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

一般不需要自己去实现,由数据库厂商实现

常用的数据库连接池技术

  • C3P0:数据库连接池技术,Hibernate默认提供
  • Druid:数据库连接池技术,由阿里巴巴提供的(更高效)

二、C3P0

2.1 使用步骤

  1. 导入Jar包(两个):c3p0-0.9.5.2.jarmchange-commons-java-0.2.12.jar

    • 数据库驱动包也需要导入
  2. 定义配置文件,xml格式或者properties格式

    • 名称:c3p0.properties 或者 c3p0-config.xml
    • 路径:将文件放在src目录下
  3. 创建数据库连接池对象:DataSource ComboPooledDataSource(filename)
  4. 获取连接:DataSource.getConnection()

2.2 代码示范

<!--
    文件名必须为c3p0-config.xml
    文件目录必须为:src下
-->
<c3p0-config>
  <!-- 使用默认的配置读取连接池对象 -->
  <default-config>
      <!--  连接参数 -->
    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbc_test</property>
    <property name="user">root</property>
    <property name="password">123456</property>
    
    <!-- 连接池参数 -->
    <!--初始化连接数-->
    <property name="initialPoolSize">5</property>
    <!--最大连接数-->
    <property name="maxPoolSize">10</property>
    <!--等待时间(超时时间)-->
    <property name="checkoutTimeout">3000</property>
  </default-config>
</c3p0-config>
/**
 * @author konley
 * @date 2020-07-07 21:36
 * c3p0简单入门
 */
public class C3P0Demo1 {
    public static void main(String[] args) throws SQLException {
        //1.创建数据库连接池对象,c3p0-config.xml或properties必须放在src目录下,自动加载
        DataSource ds = new ComboPooledDataSource();
        //2.获取连接对象
        Connection connection = ds.getConnection();
        System.out.println(connection);
    }
}

三、Druid

3.1 使用步骤

  1. 导入Jar包:druid-1.0.9.jar

    • 数据库驱动包也需要导入
  2. 定义配置文件,只能为properties格式

    • 名称:任意
    • 路径:任意
  3. 加载配置文件,需要先读取properties,用inputsteam、fileReader都可以
  4. 获取连接池对象:DataSource ds = DruidDataSourceFactory.createDataSource(properties);
  5. 获取连接:DataSource.getConnection()

3.2 代码示范

/**
 * @author konley
 * @date 2020-07-07 21:48
 * Druid简单入门
 */
public class DruidDemo1 {
    public static void main(String[] args) throws Exception {
        //加载配置文件 druid.properties位置随意
        Properties pro = new Properties();

        /*
        * 可以用inputstream、fileread和class.getClassLoader().getResourceAsStream
        * */

        //InputStream in = new FileInputStream("src/JDBCDataSource/druid.properties");
        //FileReader in = new FileReader("src/JDBCDataSource/druid.properties");
        InputStream in = DruidDemo1.class.getClassLoader().getResourceAsStream("JDBCDataSource/druid.properties");

        pro.load(in);
        //获取连接池
        DataSource ds = DruidDataSourceFactory.createDataSource(pro);
        //获取连接对象
        Connection conn = ds.getConnection();

        System.out.println(conn);
    }
}

3.3 改进JDBCUtils工具类

/**
 * @author konley
 * @date 2020-07-07 22:24
 * 使用连接池的JDBC工具类
 */
public class JDBCUtils {
    private static DataSource ds;
    //获取DataSource
    static {
        try {
            //获取properties
            Properties pro = new Properties();
            pro.load(JDBCUtils.class.getClassLoader().getResourceAsStream("JDBCDataSource/druid.properties"));
            //加载properties并创建连接池
            ds = DruidDataSourceFactory.createDataSource(pro);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //获取connection连接
    public static Connection getConnection() throws SQLException {
        return ds.getConnection();
    }

    //额外的获取连接池的方法
    public static DataSource getDataSource(){
      return ds;
    }

    //释放DQL操作的资源
    public static void close(Statement stmt, Connection con, ResultSet rs){
        try {
            if(con!=null){
                con.close();
            }
            if(stmt!=null){
                stmt.close();
            }
            if(rs!=null){
                rs.close();
            }
        }catch (SQLException e){
            System.out.println("关闭Connection失败:"+e.getMessage());
        }
    }

    //释放DML操作的资源
    public static void close(Statement stmt,Connection con){
        close(stmt,con,null);
    }
}

四、JDBCTemplate

4.1 概念

JDBCTemplate是Spring框架对JDBC的简单封装。

提供了一个JDBCTemplate对象简化JDBC的开发。

4.2 使用步骤

  1. 导入Jar包:Spirng的相关包

    • 数据库驱动包也需要导入
  2. 创建JdbcTemplate对象,依赖数据源DataSource

    • JdbcTemplate template = new JdbcTemplate(DataSource)
  3. 使用JdbcTemplate直接完成CRUD操作

4.3 DML(增删改)操作

update()方法

此方法可以执行DML语句,完成增删改操作。

代码示范

/**
 * @author konley
 * @date 2020-07-08 7:53
 * JdbcTemplate完成CUD
 */
public class SpringJDBCTemplateDML {
    //修改操作:修改dept表中的id=10的记录
    @Test
    public void update(){
        JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
        String sql = "update dept set loc=? where id=?";
        int count = template.update(sql, "天津", 10);

        System.out.println(count);
    }

    //添加操作:添加一条记录到user表
    @Test
    public void insert(){
      JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
      String sql = "insert into user value(null,?,?)";
      int count = template.update(sql, "jojo", "112233");

        System.out.println(count);
    }

    //删除操作:删除user表中id=3的记录
    @Test
    public void delete(){
        JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
        String sql = "delete from user where id=?";
        int count = template.update(sql, 3);

        System.out.println(count);
    }
}

4.4 DQL (查询)操作

1. queryFroMap(sql,[占位符?参数])方法

用途:查询结果,将结果集封装为map集合,将列名作为key,将值作为value

注意:这个方法只能查一条记录

//查询id为1,封装为map集合,查找的长度只能为1
    @Test
    public void queryForMap(){
        JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
        String sql = "select * from emp where id = ?";
        Map<String, Object> map = template.queryForMap(sql,1001);
        /*
           key=字段名,value=数据库对应的值
        */
        System.out.println(map);
    }

2. queryForList((sql,[占位符?参数])方法

用途:查询结果,将结果集封装为list集合

注意:将每一条记录封装为一个Map集合,再将Map集合装载到List集合中

 //查询所有记录,封装为list集合,里面存放map
    @Test
    public void queryFroList(){
        JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
        String sql = "select * from emp";
        List<Map<String, Object>> maps = template.queryForList(sql);
        /*
            返回map集合
         */
        for (Map<String, Object> map : maps) {
            System.out.println(map);
        }
    }

3. query(sql,RowMapper,[占位符?参数])方法

用途:查询结果,将结果封装为JavaBean对象

RowMapper参数:

  • 一般使用BeanPropertyRowMapper实现类,实现自动封装
  • 用法:new BeanPropertyRowMapper<类型>(类型.class)
  • 例子:new BeanPropertyRowMapper<emp>(emp.class)
  • 注意:使用自动封装必须满足javabean中的属性名与数据库的列名一致
//查询记录,封装为javaBean对象
    @Test
    public void qeury(){
        JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
        String sql = "select * from emp where id > ?";
        //使用BeanPropertyRowMapper<指定Bean>(指定Bean.clss) 要求Bean的字段名和数据库字段名一样
        List<Emp> list = template.query(sql, new BeanPropertyRowMapper<Emp>(Emp.class),1005);

        for (Emp emp : list) {
            System.out.println(emp);
        }
    }

4. queryForObject(sql,返回值类型.class,[占位符?参数])方法

用途:一般用于聚合函数的查询

 //查询总记录,返回值是Integer对象
    @Test
    public void queryForObject(){
        JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
        String sql = "select count(id) from emp";
        //queryForObject(sql, 接收的数据类型.class)
        Integer total = template.queryForObject(sql, Integer.class);

        System.out.println(total);
    }
文章目录