MySql & JDBC & 连接池 & 总结

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySql & JDBC & 连接池 & 总结相关的知识,希望对你有一定的参考价值。

连接池:解决资源浪费,提高代码性能。
本小节目标:
使用DBCP,C3P0连接池完成基本数据库的操作。
使用DBUtils完成CRUD的操作。
 
数据库连接池的解决方案是:
当应用程序启动时,系统主动建立足够的数据库连接,并将这些连接组成一个连接池。每次应用程序请求数据库连接时,无须重新打开连接,而是从连接池中取出已有的连接使用,使用完后不再关闭数据库连接,而是直接将连接归还给连接池。通过使用连接池,将大大提高程序的运行效率。
 
数据库连接池是Connection 对象的工程。数据库连接池的常用参数如下。
a、数据库的初始连接数
b、连接池的最大连接数
c、连接池的最小连接数
d、连接池每次增加的容量
 
公共接口:javax.sql.DataSource。
常见的连接池:DBCP 、 C3P0 (主要)
 
自定义连接池代码实现改进(增强close方法):
    自定义连接池中存在的严重问题,用户调用getConnection()获得连接后,必须使用release()方法进行连接的归还,如果用户调用conn.close()将连接真正的释放,连接池中将出现无连接可以。
 
方法增强的办法:
a、继承,子类继承父类,将父类的方法进行复写,从而进行增强。
    使用前提:必须有父类,且存在继承关系。
b、装饰者设计模式,此设计模式专门用于增强方法。
    使用前提:必须有接口
    缺点:需要将接口的所有方法都实现
c、动态代理:在运行时动态的创建代理类,完成增强操作。与装饰者相似
    使用前提:必须有接口
    难点:需要反射技术
d、字节码增强,运行时创建目标类子类,从而进行增强
    常见第三方框架:cglib 、javassist等。
 
连接池释放资源问题(WEB_10视频05自定义连接池代码实现改进(增强close方法)):
使用 c3p0 的话,也是 java.sql.Connection,只要是 JDBC 都是这个接口的对象!
 
使用完后必须 con.close() 掉,使用连接池的话,执行 con.close 并不会关闭与数据库的 TCP 连接,而是将连接还回到池中去,如果不 close 掉的话,这个连接将会一直被占用,直接连接池中的连接耗尽为止。
 
至于是如何做到 con.close 并不是真正意义上的关闭连接?而是直接将连接还回到池中去?
 
一般有两种方式:
 
一:使用装饰器模式,在装饰器构造中传入一个真正的 Connection,这个装饰器实现 Connection,使用构造 传入 Connection 委托重写所有方法,并改写 close 方法:
 
Java code
 
?
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
public class ConnectionDecorator implements Connection {
 
    private Connection con = null;
     
    public ConnectionDecorator(Connection con) {
        this.con = con;
    }
     
    public void close() throws SQLException {
        // 重写!
    }
 
    public void commit() throws SQLException {
        this.con.commit();
    }
 
    public Statement createStatement() throws SQLException {        
        return this.con.createStatement();
    }
 
    public Statement createStatement(int resultSetType, int resultSetConcurrency)
            throws SQLException {
        return this.con.createStatement(resultSetType, resultSetConcurrency);
    }
 
    ......
}
 
 
 
然后经过连接池控制的 Connection 对象都使用该装饰器进行包装
 
二:动态代理:
 
使用动态代理重新实现 close 方法,每个获得 Connection 是一个代理后的对象。
 
 
一个完善的连接池,其架构设计非常复杂,Connection#close 问题就是连接池诸多设计难点当中的一个。
 
 
总结:
关于学习mysql 以及JDBC方面的总结!
一、MySql  
MySQL基本命令
SQL(全称)语句基础:DML 、 DDL 、 DCL 、 DQL
数据库约束
查询(单表、多表   左右连接等)
truncate  和  delete比较?
等等等
 
二、JDBC编程步骤
1、加载驱动     
c3p0-config.xml
db.properties     
2、获取连接    
连接池概念
步骤   J3P0(XML)
3、DBUtils   完成CRUD (增删改查)
封装JDBC操作,简化JDBC操作
JavaBean组件(封装数据)   包:com.scalpet.domain
4、使用完连接池后:释放资源
得出结论,DBUtils在创建QueryRunner时传入dataSource对象每次在执行完之后都会自动关闭Connection连接对象~所以再也不用担心没有关闭对象而导致的问题了~如果没有传入dataSource的话 ·····需要手动关闭
 
三、练习
a、建立工程---java project
b、导入JDBC连接的jar包---jar包都添加在新文件夹lib下面
c、导入c3p0jar包
d、编写c3p0-config.xml文件
e、编写C3P0工具类---其核心工具类ComboPooledDataSource(命名配置、默认配置)---工具类都放在新建包com.scalpel.utils包下
f、编写JavaBean组件User----组件在新建包com.scalpel.domain包下
g、导入DBUtils的jar包
h、编写DBUtils的测试java类
 
代码实现:
c3p0-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
 
  <default-config>
    <property name="driverClass">com.mysql.jdbc.Driver</property>
       <property name="jdbcUrl">jdbc:mysql:///web</property>
       <property name="user">root</property>
       <property name="password">12345678</property>
       <property name="initialPoolSize">5</property>
       <property name="maxPoolSize">20</property>
  </default-config>
 
  <named-config name="scalpel">
    <property name="driverClass">com.mysql.jdbc.Driver</property>
       <property name="jdbcUrl">jdbc:mysql:///web</property>
       <property name="user">root</property>
       <property name="password">12345678</property>
  </named-config>
 
 
</c3p0-config>
 
C3P0Utils工具类:
package com.scalpel.jdbc.utils;
 
import java.sql.Connection;
import java.sql.SQLException;
 
import javax.sql.DataSource;
 
import com.mchange.v2.c3p0.ComboPooledDataSource;
 
public class C3P0Utils {
       
       //使用命名配置
       private static ComboPooledDataSource dataSource = new ComboPooledDataSource("scalpel");
       
       /*
        * 获得数据源(连接池)
        */
       public static DataSource getDataSource()
       {
             return dataSource;
       }
       
       /*
        * 获得连接
        */
       public static Connection getConnection()
       {
             try {
                    return dataSource.getConnection();
             } catch (SQLException e) {
                    throw new RuntimeException();
             }
       }
}
 
userbean组件类:
package com.scalpel.domain;
 
public class User {
       
       private  int id;
       private  String name;
       private  String password;
       public int getId() {
             return id;
       }
       public void setId(int id) {
             this.id = id;
       }
       public String getName() {
             return name;
       }
       public void setName(String name) {
             this.name = name;
       }
       public String getPassword() {
             return password;
       }
       public void setPassword(String password) {
             this.password = password;
       }
       
       
}
 
连接测试类:
package com.scalpel.jdbc.link;
 
import java.sql.SQLException;
import java.util.List;
 
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.junit.Test;
 
import com.scalpel.domain.User;
import com.scalpel.jdbc.utils.C3P0Utils;
 
public class LinkJDBC {
 
       /*
        * 添加用户
        */
       @Test
       public void AddUser() {
             try {
                    // 1.连接数据源连接池
                    QueryRunner qr = new QueryRunner(C3P0Utils.getDataSource());
                    // 2.编写sql语句
                    String sql = "insert into user values( ?, ?, null )";
                    // 3.添加params参数
                    Object[] params = { "ctxixi", "123" };
                    // 4.执行sql语句
                    int rows = qr.update(sql, params);
                    // 5.判断是否执行成功
                    if (rows > 0) {
                           System.out.println("添加成功");
                    } else {
                           System.out.println("添加失败");
                    }
             } catch (SQLException e) {
                    e.printStackTrace();
             }
       }
 
       /*
        * 查询用户,使用BeanListHandler
        */
       @Test
       public void QueryAllUserInf()
       {
             try {
                    QueryRunner qr = new QueryRunner(C3P0Utils.getDataSource());
                    String sql = "select * from user";
                    List<User> queryUser = qr.query(sql, new BeanListHandler<User>(User.class));
                    for (User user : queryUser)
                    {
                           System.out.println(user.getId() +"、" + user.getName() + " : " + user.getPassword());                      
                    }                   
             } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
             }
       }
 
}
 
 

以上是关于MySql & JDBC & 连接池 & 总结的主要内容,如果未能解决你的问题,请参考以下文章

JDBC连接MySQL

JDBC连接MySQL

独立出properties的mybatis连接池

mysql8以上的连接配置

使用JDBC连接mysql遇到的若干问题及解决办法

jdbc连接数据库