JDBC之c3p0连接池及其代码优化
一、JDBCUtils工具类的创建,通过属性文件来改变数据库用户登录以及要连接的数据库
package com.my.work; import java.io.IOException; import java.io.InputStream; import java.sql.*; import java.util.Properties; public class JDBCUtils { public static final String driverClass; public static final String url; public static final String username; public static final String password; static { //加载属性文件jdbc.properties并解析 Properties prop=new Properties(); //如何获得属性文件的输入流? //通常情况下使用类的加载器的方式进行获取 InputStream is=JDBCUtils.class.getClassLoader().getResourceAsStream("jdbc.properties"); try { prop.load(is); } catch (IOException e) { e.printStackTrace(); } driverClass=prop.getProperty("driverClass"); url=prop.getProperty("url"); username=prop.getProperty("username"); password=prop.getProperty("password"); } //注册驱动方法 public static void loadDriver() throws ClassNotFoundException { Class.forName(driverClass); } //获得连接方法 public static Connection getConnection() throws ClassNotFoundException, SQLException { loadDriver(); Connection conn=DriverManager.getConnection(url,username,password); return conn; } //资源释放(增删改) public static void release(Statement sta,Connection conn){ if (sta!=null){ try { sta.close(); }catch (SQLException e){ e.printStackTrace(); } sta=null; } if (conn!=null){ try { conn.close(); }catch (SQLException e){ e.printStackTrace(); } conn=null; } } //资源释放(查) public static void release(ResultSet res,Statement sta, Connection conn){ if (res!=null){ try { res.close(); }catch (SQLException e){ e.printStackTrace(); } res=null; } if (sta!=null){ try { sta.close(); }catch (SQLException e){ e.printStackTrace(); } sta=null; } if (conn!=null){ try { conn.close(); }catch (SQLException e){ e.printStackTrace(); } conn=null; } } }
配置属性文件jdbc.properties
driverClass=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/enter?characterEncoding=utf8&useSSL=false username=root password=mysql
利用创建的JDBCUtils工具类来做一个用户登陆注册修改查询删除的测试
package com.my.work; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; public class UserEnter{ //用户登录 public static void userenter(String username,String password){ Connection conn=null; PreparedStatement pre=null; ResultSet rs=null; try { //通过工具类获取连接 conn=JDBCUtils.getConnection(); //先写SQL语句 String sql="select * from enter where username= ? and password= ?"; //执行SQL语句 pre=conn.prepareStatement(sql); //对查询信息进行赋值 pre.setString(1,username); pre.setString(2,password); //显示结果 rs=pre.executeQuery(); if (rs.next()){ System.out.println("登陆成功"); }else{ System.out.println("登陆失败"); } }catch (Exception e){ e.printStackTrace(); }finally { //释放资源 JDBCUtils.release(rs,pre,conn); } } //注册新用户 public static void userenrol(int sno,String username,String password){ Connection conn=null; PreparedStatement pre=null; try { conn=JDBCUtils.getConnection(); String sql="insert into enter value(?,?,?)"; pre=conn.prepareStatement(sql); pre.setString(1, String.valueOf(sno)); pre.setString(2,username); pre.setString(3,password); int num=pre.executeUpdate(); if (num>0){ System.out.println("注册成功"); }else{ System.out.println("注册失败"); } }catch (Exception e){ e.printStackTrace(); }finally { JDBCUtils.release(pre,conn); } } //用户信息修改 public static void useralter(int sno,String username,String password){ Connection conn=null; PreparedStatement pre=null; try { conn=JDBCUtils.getConnection(); String sql="update enter set username=?,password=? where sno=?"; pre=conn.prepareStatement(sql); pre.setString(1,username); pre.setString(2,password); pre.setString(3, String.valueOf(sno)); int num=pre.executeUpdate(); if (num>0){ System.out.println("修改成功"); }else{ System.out.println("修改失败"); } }catch (Exception e){ e.printStackTrace(); }finally { JDBCUtils.release(pre,conn); } } //删除用户 public static void userdrop(int sno){ Connection conn=null; PreparedStatement pre=null; try { conn=JDBCUtils.getConnection(); String sql="delete from enter where sno=?"; pre=conn.prepareStatement(sql); pre.setString(1, String.valueOf(sno)); int num=pre.executeUpdate(); if (num>0){ System.out.println("删除成功"); }else{ System.out.println("删除失败"); } }catch (Exception e){ e.printStackTrace(); }finally { JDBCUtils.release(pre,conn); } } //查询所有用户信息 public static void userallshow(){ Connection conn=null; PreparedStatement pre=null; ResultSet rs=null; try { conn=JDBCUtils.getConnection(); }catch (Exception e){ e.printStackTrace(); }finally { JDBCUtils.release(rs,pre,conn); } } //查询指定用户信息 public static void usershow(String username){ Connection conn=null; PreparedStatement pre=null; ResultSet rs=null; try { conn=JDBCUtils.getConnection(); String sql="select * from enter where username=?"; pre=conn.prepareStatement(sql); pre.setString(1,username); rs=pre.executeQuery(); while (rs.next()){ System.out.println(rs.getString("sno")+" "+rs.getString("username")+" "+rs.getString("password")); } }catch (Exception e){ e.printStackTrace(); }finally { JDBCUtils.release(rs,pre,conn); } } }
二、c3p0连接池的创建
首先要准备以下jar包,都添加到lib文件夹中
c3p0jar包下载地址为:
https://sourceforge.net/projects/c3p0/files/latest/download?source=files
mchange-commmon-java jar包的下载地址为:
http://commons.apache.org/proper/commons-dbutils/download_dbutils.cgi
创建常量池的实例
package com.my.work; import com.mchange.v2.c3p0.ComboPooledDataSource; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; public class ConnectionPool { public void connectionPool(){ Connection conn=null; PreparedStatement pre=null; ResultSet rs=null; try { //创建常量池对象 ComboPooledDataSource combopool=new ComboPooledDataSource("mysql");//这里的名字要与c3p0-config.xml里面<named-config name="mysql">的名字一样,且不能为空 //配置常量池信息 combopool.setDriverClass("com.mysql.jdbc.driver"); combopool.setJdbcUrl("jdbc:mysql://localhost:3306/enter?characterEncoding=utf8&useSSL=false"); combopool.setUser("root"); combopool.setPassword("mysql"); combopool.setMaxPoolSize(20); combopool.setInitialPoolSize(3); //获得连接 conn=combopool.getConnection(); //书写SQL语句 String sql="select * from enter"; //执行SQL语句 pre=conn.prepareStatement(sql); //输出查询结果 rs=pre.executeQuery(); while (rs.next()){ System.out.println(rs.getString("sno")+" "+rs.getString("username")+" "+rs.getString("password")); } }catch (Exception e){ e.printStackTrace(); }finally { //释放资源 JDBCUtils.release(rs,pre,conn); } } }
通过在src目录下添加 c3p0-config.xml 文件来优化代码,
<?xml version="1.0" encoding="UTF-8"?> <c3p0-config> <!-- This is default config! --> <default-config> <property name="initialPoolSize">10</property> <property name="maxIdleTime">30</property> <property name="maxPoolSize">100</property> <property name="minPoolSize">10</property> <property name="maxStatements">200</property> </default-config> <!-- This is my config for mysql--> <named-config name="mysql"> //自己定义名字 <property name="driverClass">com.mysql.jdbc.Driver</property> //获取驱动 <property name="jdbcUrl">jdbc:mysql://localhost:3306/enter?characterEncoding=utf8&useSSL=false</property> //获取URL <!--MySQL账户密码--> <property name="root">root</property> //获取账户 <property name="password">mysql</property> //获取密码 <!-- 初始化连接池中的连接数,取值应在minPoolSize与maxPoolSize之间,默认为3--> <property name="initialPoolSize">10</property> <!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。默认值: 0 --> <property name="maxIdleTime">30</property> <!--连接池中保留的最大连接数。默认值: 15 --> <property name="maxPoolSize">100</property> <!-- 连接池中保留的最小连接数,默认为:3--> <property name="minPoolSize">10</property> <!--c3p0全局的PreparedStatements缓存的大小。如果maxStatements与maxStatementsPerConnection均为0,则缓存不生效,只要有一个不为0,则语句的缓存就能生效。如果默认值: 0--> <property name="maxStatements">200</property> <!-- 当连接池连接耗尽时,客户端调用getConnection()后等待获取新连接的时间,超时后将抛出SQLException,如设为0则无限期等待。单位毫秒。默认: 0 --> <!--这种写法也可以 <property name="checkoutTimeout" value="3000"/> --> <property name="checkoutTimeout">3000</property> <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。默认值: 3 --> <!-- <property name="acquireIncrement" value="2"/> --> <property name="acquireIncrement">2</property> <!--定义在从数据库获取新连接失败后重复尝试的次数。默认值: 30 ;小于等于0表示无限次--> <!-- <property name="acquireRetryAttempts" value="0"/> --> <property name="acquireRetryAttempts">0</property> <!--重新尝试的时间间隔,默认为:1000毫秒--> <!-- <property name="acquireRetryDelay" value="1000" /> --> <property name="acquireRetryDelay">1000</property> <!--关闭连接时,是否提交未提交的事务,默认为false,即关闭连接,回滚未提交的事务 --> <property name="autoCommitOnClose">false</property> <!--c3p0将建一张名为Test的空表,并使用其自带的查询语句进行测试。如果定义了这个参数那么属性preferredTestQuery将被忽略。你不能在这张Test表上进行任何操作,它将只供c3p0测试使用。默认值: null --> <property name="automaticTestTable">Test</property> <!--如果为false,则获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常,但是数据源仍有效保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试获取连接失败后该数据源将申明已断开并永久关闭。默认: false--> <property name="breakAfterAcquireFailure">false</property> <!--每60秒检查所有连接池中的空闲连接。默认值: 0,不检查 --> <property name="idleConnectionTestPeriod">60</property> <!--maxStatementsPerConnection定义了连接池内单个连接所拥有的最大缓存statements数。默认值: 0 --> <property name="maxStatementsPerConnection">200</property> </named-config> <named-config name="mysql"> //自己设置名字 <property name="driverClass">com.mysql.jdbc.Driver</property> //获取驱动 <property name="jdbcUrl">jdbc:mysql://localhost:3306/enter?characterEncoding=utf8&useSSL=false</property> //获取URL <property name="user">root</property> //获取用户 <property name="password">mysql</property> //获取密码 <property name="initialPoolSize">10</property> <property name="maxIdleTime">30</property> <property name="maxPoolSize">100</property> <property name="minPoolSize">10</property> <property name="maxStatements">200</property> </named-config> </c3p0-config>
添加c3p0-config.xml 文档后对JDBCUtils工具类进行优化
package com.my.work; import com.mchange.v2.c3p0.ComboPooledDataSource; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class JDBCUtils2 { public static final ComboPooledDataSource dataSource=new ComboPooledDataSource("mysql");//这里的名字要与c3p0-config.xml里面<named-config name="mysql">的名字一样,且不能为空
//不再需要注册驱动和获取连接池对象和配置连接池,直接从池子里面拿来用就行
//获得连接方法
public static Connection getConnection() throws Exception{ Connection conn=dataSource.getConnection(); return conn; }
//资源释放(增删改) public static void release(Statement sta,Connection conn){ if (sta!=null){ try { sta.close(); }catch (SQLException e){ e.printStackTrace(); } sta=null; } if (conn!=null){ try { conn.close(); }catch (SQLException e){ e.printStackTrace(); } conn=null; } }
//资源释放(查) public static void release(ResultSet res,Statement sta, Connection conn){ if (res!=null){ try { res.close(); }catch (SQLException e){ e.printStackTrace(); } res=null; } if (sta!=null){ try { sta.close(); }catch (SQLException e){ e.printStackTrace(); } sta=null; } if (conn!=null){ try { conn.close(); }catch (SQLException e){ e.printStackTrace(); } conn=null; } } }
添加c3p0-config.xml 文档后对创建常量池的实例优化
package com.my.work; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; public class ConnectionPool { public void connectionPool(){ Connection conn=null; PreparedStatement pre=null; ResultSet rs=null; try { conn=JDBCUtils.getConnection();//优化之后直接从池子里面获取连接即可 //书写SQL语句 String sql="select * from enter"; //执行SQL语句 pre=conn.prepareStatement(sql); //输出查询结果 rs=pre.executeQuery(); while (rs.next()){ System.out.println(rs.getString("sno")+" "+rs.getString("username")+" "+rs.getString("password")); } }catch (Exception e){ e.printStackTrace(); }finally { //释放资源 JDBCUtils未优化.release(rs,pre,conn); } } }