10_连接池 & DBUtils

连接池
连接池介绍
  • 获取服务器连接和断开连接是非常消耗系统资源的,重复创建和断开连接会造成资源浪费
  • 使用数据库连接池可以解决性能问题
  • 使用连接池技术来共享Connection
  • java为数据库连接池提供了公共的接口:javax.sql.DataSource
自定义连接池
  • 数据源
    • 获取数据的资源,我们以后需要获取数据库数据,就从连接池中获取连接然后连到数据库里,称之为数据源
  • 创建连接池步骤
    1. 创建连接池实现(实现javax.sql.DataSource接口),使用getConnection()方法
    2. 提供一个集合,用于存放连接,因为移除和添加操作过多,因此选择LinkedList
      • 通过自定义的JDBCUtils获取Connection
    3. 在静态代码块中创建3个连接
    4. 程序需要连接,调用getConnection()方法,方法从LinkedList中获取连接
    5. 用户使用完连接后把连接添加回LinkedList中
public class MyDataSource implements DataSource{
    private static LinkedList pool = new LinkedList<>();
    private MyDataSource() {
        super();
    }
    static {
        Connection conn = null;
        for (int i = 0; i < 15; i++) {
            conn = JDBCUtils.getConnection();
            pool.add(conn);
        }
    }
    @Override
    public static Connection getConnection() throws SQLException {
        if (pool.size() != 0) {
            return pool.removeFirst();
        }
        Thread.sleep(100);
        return getConnection();
        
    }
    
    //回收连接
    public static releaseConnection(Connection conn) {
        if(conn != null) {
            pool.add(conn);
        }
    }
}
  • 自定义连接池需要调用连接池提供的release(connection conn)方法进行回收连接
    • 如果用户调用Connection.close()会真的关闭掉连接
  • 我们需要当用户调用Connection的close方法后,连接重新回到链接池中
    • 实现Connection.close()后连接回到连接池中
方法增强
1. 继承:子类继承父类,重写父类的方法从而使方法增强
    * 前提是必须要有父类,且存在继承关系
2. 装饰设计模式:此设计模式专门用于增强方法
    * 使用前提:必须有接口
    * 缺点:需要将接口所有方法实现
3. 动态代理:在运行时动态的创建代理类,完成增强的操作,与装饰者相似
    * 使用前提:需要有接口
    * 难点:需要有反射技术
4. 字节码增强:运行时创建目标类子类,从而进行增强
    * 常见第三方框架:cglib,javassist等
装饰设计模式
  • 专门为解决某一类问题,而编写的固定格式的代码
  • 装饰者固定结构:接口A,已知实现类C,需要装饰者创建代理类B
  1. 创建B,并实现A接口
  2. 提供B类的构造方法,参数类型为A,用于接收A接口的实现类C
  3. 给类B添加类型为A的成员变量,用于存放A接口的其他实现类
  4. 增强需要的方法
  5. 实现不需要增强的方法,方法体重调用成员变量存放的其他实现类对应的方法
  • A接口的实现类C作为参数传递,需要增强C的某个方法,创建A接口实现类B包裹C,修改该方法,然后把B替代C作为参数传递
A a = c;
B b = new B(c);
class B implement A {
    private A a;
    public B(A a)  {
        this.a = a;
    }
    //需要增强的方法
    public void close() {
        ...    
    }
    //需要增强的方法
    public void commit() {
        ...
    }
}
//1.实现同一个接口Connection
public class MyConnection implements Connection {
    //3.定义一个变量
    private Connection conn;
    private LinkedList pool;
    // 2.编写一个构造方法(参数使用了面相对象的多态特性)
    public MyConnection(Connection conn,LinkedList pool) {
        this.conn=conn;
        this.pool=pool;
    }
    //4.书写需要增强的方法
    @Override
    public void close() throws SQLException {
        pool.add(conn);
    }
    /**
     * 此方法必须覆盖!否则会出现空指针异常!!!
     */
    @Override
    public PreparedStatement prepareStatement(String sql) throws SQLException {
        return conn.prepareStatement(sql);
    }
}
C3P0连接池(使用率最高80%)
  • C3P0是开源免费的连接池,目前使用它的开源项目有:Spring,Hibernate等.

  • 使用第三方工具需要导入jar包,C3P0使用时还需要添加配置文件c3p0-config.xml

  • c3p0工具类

//创建空参的ComboPooledDataSource对象时,默认会自动读取c3p0-config.xml文件中的配置
public class C3P0Utils {
    private static ComboPooledDataSource dataSource = new ComboPooledDataSource("coinfig_name");

    public static DataSource getDataSource() {
        return dataSource;
    }

    public static Connection getConnection() {
        try {
            return dataSource.getConnection();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}
  • c3p0-config.xml


    
        com.mysql.jdbc.Driver
        jdbc:mysql:///web08
        root
        root
        5
        20
    

    
        com.mysql.jdbc.Driver
        jdbc:mysql:///web08
        root
        root
    

DBCP
  • DBCP也是开源免费的连接池,在企业开发中也比较常见
  • tomcat服务器自带DBCP连接池
  • DBCP可以自己手动设置参数,也可以通过Properties对象和BasicDataSourceFactory初始化
BasicDataSource basicDataSource = new BasicDataSource();
basicDataSource.setDriverClassName("com.mysql.Driver");
basicDataSource.setUrl("jdbc:mydql://localhost:3306/mydatabase");
basicDataSource.setUsername("root");
basicDataSource.setPassword("root");
public class DBCPUtils {
    private static DataSource dataSource;
    static{
        try {
            //1.加载找properties文件输入流
            InputStream is = DBCPUtils.class.getClassLoader().getResourceAsStream("db.properties");
            //2.加载输入流
            Properties props = new Properties();
            props.load(is);
            //3.创建数据源
            dataSource = BasicDataSourceFactory.createDataSource(props);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    public static DataSource getDataSource(){
        return dataSource;
    }
    
    public static Connection getConnection(){
        try {
            return dataSource.getConnection();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}
  • 配置文件:db.properties
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/web08?useUnicode=true&characterEncoding=utf8
username=root
password=root
initialSize=10
maxActive=50
maxIdle=5
maxWait=6000
DBUtils
  • DBUtils是java编程中操作数据库的实用工具,小巧简单
  • DBUtils封装了对JDBC操作,可以减少代码
  • DBUitls,JDBCUtils,连接池区别
    • JDBCUtils是方便获取连接
    • 数据库连接池是提高代码的性能
    • DBUtils是精简操作数据库代码量
  • DBUtils类在基础加强里面会单独讲
try {
    // 1.创建核心类QueryRunner
    QueryRunner qr = new QueryRunner(C3P0Utils.getDataSource());//参数传入连接池
    // 2.编写SQL语句
    String sql = "insert into tbl_user values(null,?,?)";
    // 3.为站位符设置值
    Object[] params = { "xx", "oo" };
    // 4.执行添加操作
    int rows = qr.update(sql, params);
    if (rows > 0) {
        System.out.println("添加成功!");
    } else {
        System.out.println("添加失败!");
    }
} catch (SQLException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

你可能感兴趣的:(10_连接池 & DBUtils)