数据库连接池和Spring JDBC

数据库连接池

  • 概念:本质上是一个容器,存放数据库连接的容器

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

  • 数据库厂商实现

    cp30:数据库连接池技术

    Druid:数据库连接池实现技术(阿里巴巴)

C3P0

  • 下载c3p0压缩包:https://sourceforge.net/projects/c3p0/files/latest/download?source=files

  • 导入jar包:c3p0-0.9.5.5.jar和mchange-commons-java-0.2.19.jar

  • 定义配置文件:

    • 名称:c3p0.propertiesorc3p0-config.xml
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    <c3p0-config>
    <!--使用默认的配置读取连接池对象 -->
    <default-config>
    <property name="driverClass">com.mysql.cj.jdbc.Driver</property>
    <!--jdbc:mysql://localhost:3306/test?&useSSL=false&serverTimezone=GMT%2B8-->
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/test?&amp;useSSL=false&amp;serverTimezone=GMT%2B8</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>

    <name-config name="otherc3p0">
    <property name="driverClass">com.mysql.cj.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/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>
    </name-config>>
    </c3p0-config>
    • 路径:直接将文件放在src目录下即可
  • 创建数据库连接对象 ComboPooledDataSource

  • 获取连接:getConnection

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public class c3p0demo2 {
    public static void main(String[] args) throws SQLException {
    DataSource ds = new ComboPooledDataSource();
    //DataSource ds = new ComboPooledDataSource("otherc3p0");
    //验证最大连接数量参数
    for (int i = 0; i < 10; i++) {
    ds.getConnection();
    System.out.println(i+":"+ds);
    }
    }
    }

Druid

  • 导入jar包,下载地址:https://repo1.maven.org/maven2/com/alibaba/druid/

  • 定义配置文件properties

    1
    2
    3
    4
    5
    6
    7
    driverClassname=com.mysql.cj.jdbc.Driver
    url=jdbc:mysql://localhost:3306/test?&useSSL=false&serverTimezone=GMT%2B8
    username=root
    password=123456
    initialSize=5
    maxActive=10
    maxWait=3000
  • 获取数据库连接池对象:通过工厂类来获取 DruidDataSourceFactory

  • 获取数据库连接

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public class druiddemo {
    public static void main(String[] args) throws Exception {
    Properties pro = new Properties();
    //加载配置文件
    InputStream is = druiddemo.class.getClassLoader().getResourceAsStream("druid.properties");
    pro.load(is);
    //参数是配置文件Properties对象
    DataSource ds = DruidDataSourceFactory.createDataSource(pro);
    Connection conn = ds.getConnection();
    System.out.println(conn);
    }
    }

Druid工具类实现

  • 定义一个工具类JDBCutils

    提供静态代码块加载配置文件,初始化连接池对象

    提供方法

    • 获取数据库连接方法:通过数据库连接池对象获取连接
    • 释放资源
    • 获取连接池的方法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    public class JDBCutils {
    //定义数据库连接池对象
    private static DataSource ds;

    //静态代码块
    static{
    try {
    //加载配置文件
    Properties pro = new Properties();
    pro.load(JDBCutils.class.getClassLoader().getResourceAsStream("druid.properties"));
    //获取DataSource
    ds = DruidDataSourceFactory.createDataSource(pro);
    } catch (IOException e) {
    e.printStackTrace();
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    //获取数据库连接方法
    public static Connection getConnection() throws SQLException {
    return ds.getConnection();
    }
    //释放连接
    public static void close(ResultSet rs,Statement stmt, Connection conn){
    if(rs != null){
    try {
    rs.close();
    } catch (SQLException throwables) {
    throwables.printStackTrace();
    }
    }
    if(stmt != null){
    try {
    stmt.close();
    } catch (SQLException throwables) {
    throwables.printStackTrace();
    }
    }
    if(conn != null){
    try {
    conn.close(); //归还连接
    } catch (SQLException throwables) {
    throwables.printStackTrace();
    }
    }
    }
    public static void close(Statement stmt, Connection conn){
    close(null,stmt,conn);
    }
    //返回数据库连接池
    public static DataSource getDataSource(){
    return ds;
    }
    }
  • 工具类测试

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    public class druiddemo2 {
    public static void main(String[] args) {
    Connection connection = null;
    PreparedStatement pstmt = null;
    //获取数据库连接
    try {
    connection = JDBCutils.getConnection();
    String sql = "insert into user values(?,?)";
    pstmt = connection.prepareStatement(sql);
    //给问号赋值
    pstmt.setString(1,"hxxx");
    pstmt.setString(2,"123");
    //执行sql
    int count = pstmt.executeUpdate();
    System.out.println(count);

    } catch (SQLException throwables) {
    throwables.printStackTrace();
    }finally {
    //释放连接
    JDBCutils.close(pstmt,connection);
    }
    }
    }

Spring JDBC

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

  • 步骤

    1. 导入jar包:下载链接: https://jar-download.com/artifacts/org.springframework/spring-jdbc
    2. 创建JDBCTemplate对象。依赖于数据源DataSource
    3. 调用JdbcTemplate的方法来完成CRUD的操作
      • update():执行DML语句。增删改
      • queryForMap():将查询结果集封装为Map集合,将列名作为key,将值作为value,将这条记录封装为一个Map集合。这个方法查询结果集长度只能是1.
      • queryForList():将查询结果集封装为Lisit集合,每一条记录封装为一个Map集合,再对Map集合装载到List集合中
      • query():查询结果,将结果封装为JavaBean对象
      • queryForObject():将结果封装为对象
  • 案例

    • 需求(表emp,字段id,name,age,dep_id)

      1. 添加一条记录

      2. 删除一条记录

      3. 查询id为1的记录,将其封装为Map集合

      4. 查询所有记录,将其封装为List集合

      5. 查询所有记录,将其封装为user对象的List集合

      6. 查询总记录数

    • 封装user类

      1
      2
      3
      4
      5
      6
      7
      public class user {
      private String name;
      private Integer id;
      private Integer age;
      private Integer dep_id;
      //省略get,set,toString
      }
    • 使用Junit进行测试

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      public class JdbcTemplateTest {
      private JdbcTemplate template = new JdbcTemplate(JDBCutils.getDataSource());
      // 添加一条记录
      @Test
      public void test1(){
      String sql = "insert into emp values(?,?,?,?)";
      int count = template.update(sql, 6, "老王", 21, null);
      System.out.println(count);
      }

      //删除一条记录
      @Test
      public void test2(){
      String sql = "delete from emp where id = ?";
      int count = template.update(sql, 6);
      System.out.println(count);
      }
      //查询id为1的记录,将其封装为Map集合
      @Test
      public void test3(){
      String sql = "select *from emp where id = ?";
      Map<String, Object> stringObjectMap = template.queryForMap(sql, 1);
      System.out.println(stringObjectMap);
      }
      //查询所有记录,将其封装为List集合
      @Test
      public void test4(){
      String sql = "select *from emp";
      List<Map<String, Object>> mapList = template.queryForList(sql);
      for (Map<String, Object> stringObjectMap : mapList) {
      System.out.println(stringObjectMap);
      }
      }
      //查询所有记录,将其封装为user对象的List集合
      @Test
      public void test5(){
      String sql = "select *from emp";
      List<user> list = template.query(sql, new BeanPropertyRowMapper<user>(user.class));
      for (user user : list) {
      System.out.println(user);
      }
      }
      //查询所有记录,将其封装为user对象的List集合
      @Test
      public void test6(){
      String sql = "select *from emp";
      List<user> list = template.query(sql, new RowMapper<user>() {
      @Override
      public user mapRow(ResultSet resultSet, int i) throws SQLException {
      user use = new user();
      String name = resultSet.getString("name");
      Integer id = resultSet.getInt("id");
      Integer age = resultSet.getInt("age");
      Integer dep_id = resultSet.getInt("dep_id");
      use.setAge(age);
      use.setDep_id(dep_id);
      use.setId(id);
      use.setName(name);
      return use;
      }
      });
      for (user user : list) {
      System.out.println(user);
      }
      }
      //查询记录总数
      @Test
      public void test7(){
      String sql = "select count(id) from emp";
      Long aLong = template.queryForObject(sql, Long.class);
      System.out.println(aLong);
      }
      }