第一步: 首先创建一个数据库连接池的接口:
数据库连接池接口有两个主要的方法,其中一个getConnection(); 通过数据库连接池返回给用户封装的数据库连接对象
createConnections(int count);是当数据库连接池中的连接不够用的时候用来创建数据库连接个数;
参数解释: 首先,vector是我们所用的数据库连接池,其中用来存储我们所需要的数据库连接的个数,就相当于一个池子,当人们需要数据库连接时候只需要去vector中去拿就可以了,首先,因为有池子,池子中就一定要有初始化的数据库连接, 所以用一个init()函数,将池子中进行初始化,
初始化字段:
public static String jdbcDriver="";
public static String dbUserName="";
public static String dbPassword="";
public static String dbUrl="";
public static int initConCount;
public static int maxConnects;
public static int inCrementalcount;
这些字段的定义是从对应的properties文件中读取数据, 分别是数据库驱动,账号,密码,数据库地址,初始化的连接数目,连接池中的最大连接数,当达到了最大个数,增加连接池中的个数。这些数据都是从properties文件中读取的。
package jdbcpool; import com.mysql.jdbc.Connection; public interface IPool { PooledConnection getConnection(); void createConnections(int count); }
第二步:JdbcPool
其中JdbcPool实现了 上面的数据库连接池的接口;需要重写上面的两个方法,
package jdbcpool; import java.io.IOException; import java.io.InputStream; import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Properties; import java.util.Vector; import sun.reflect.generics.tree.Tree; import com.sun.corba.se.spi.orbutil.fsm.InputImpl; public class JdbcPool implements IPool{ public static String jdbcDriver=""; public static String dbUserName=""; public static String dbPassword=""; public static String dbUrl=""; public static int initConCount; public static int maxConnects; public static int inCrementalcount; private static Vector<PooledConnection> vector=new Vector<PooledConnection>();//vector当成一个池子,需要就去里面拿,pooledConnction,用来分装一个JDBCconection public void init(){ System.out.println("1"); InputStream in= JdbcPool.class.getClassLoader().getResourceAsStream("jdbcpool/jdbc.properties"); Properties pt= new Properties(); try { pt.load(in); } catch (IOException e) { e.printStackTrace(); } jdbcDriver=pt.getProperty("jdbcDriver"); dbUserName=pt.getProperty("dbUserName"); dbPassword=pt.getProperty("dbPassword"); dbUrl=pt.getProperty("dbUrl"); initConCount=Integer.valueOf(pt.getProperty("initConCount")) ; maxConnects=Integer.valueOf(pt.getProperty("maxConnects")) ; inCrementalcount=Integer.valueOf(pt.getProperty("inCrementalcount")) ; try { Driver driver=(Driver)(Class.forName(jdbcDriver).newInstance()); DriverManager.registerDriver(driver);//载入JDBC驱动,连接的时候以后不用再加载驱动了 createConnections(initConCount);//初始化连接池中数据 } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } } public synchronized PooledConnection getConnection() { if(vector.size()<=0){//拿连接的时候,首先应该判定池子中有没有数据,没有错误就应该抛出对应的一个错误信息 System.out.println("连接池中还没有连接"); throw new RuntimeException("连接池中还没有连接"); } PooledConnection conn = getActionConnection();//得到数据库连接 if(conn==null){//连接池中的连接全部为忙碌状态, 这个时候要扩容//的到连接后首先应该判定连接有没有拿到,没到那就为null,拿到了就直接返回 //这个时候需要对连接池进行增长 createConnections(inCrementalcount);//没有了就根据对应的步长去拿 conn=getActionConnection();//有没有再次为Null 多个线程拿连接,Vector 为单例,内存中只有一份,一直拿不到,所以为Null while(conn==null){//如果没有拿到,就无线循环 try { Thread.sleep(300);//每次循环休息300 } catch (InterruptedException e) { e.printStackTrace(); } conn=getActionConnection();//继续拿,迟早会拿到 } } return conn; } private PooledConnection getActionConnection(){ for (PooledConnection conn : vector) {//遍历池子中封装的jdbcPool if(!conn.isBusy()){//这个数据不忙碌 Connection trueconn=conn.getConn();//拿到这个连接 try { if(!trueconn.isValid(0)){//拿到连接后要判定有没有超时 Connection newconn=DriverManager.getConnection(dbUrl, dbUserName, dbPassword); conn.setConn(newconn); } } catch (SQLException e) { e.printStackTrace(); } conn.setBusy(true);//拿到后就必须设置为忙碌 return conn; } } return null; } /** * 创建连接,首先应该判定 在创建 */ public void createConnections(int count) { if(maxConnects>0&&vector.size()>=maxConnects){ System.out.println("连接大于最大的值"); throw new RuntimeException("连接池中的连接已经大于最大值"); } for (int i = 0; i < count; i++) { //创建连接时候 我们要判定是否小于最大值 try { Connection conn=DriverManager.getConnection(dbUrl,//创建数据库的连接 dbUserName, dbPassword); vector.add(new PooledConnection(conn,false));//封装成自己的连接; } catch (SQLException e) { e.printStackTrace(); } } } }
第三步:新建一个PooledConnection ,用来人工封装我们的数据库连接池中的单位, this.conn=conn; this.isBusy=isBusy;isBusy为true的时候,代表该连接不可用
package jdbcpool; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class PooledConnection { private Connection conn=null; private boolean isBusy=false; public PooledConnection(Connection conn,boolean isBusy){ this.conn=conn; this.isBusy=isBusy; } public ResultSet queryBySql(String sql){ Statement sm=null; ResultSet rs=null; try { sm=conn.createStatement(); rs=sm.executeQuery(sql); } catch (SQLException e) { e.printStackTrace(); } return rs; } public int updateBysql(String sql){ Statement sm=null; int count=-1; try{ sm=conn.createStatement(); count=sm.executeUpdate(sql); } catch (SQLException e){ e.printStackTrace(); } return count; } public Connection getConn() { return conn; } public void setConn(Connection conn) { this.conn = conn; } public boolean isBusy() { return isBusy; } public void setBusy(boolean isBusy) { this.isBusy = isBusy; } public void close(){ isBusy=false; } }
jdbc.properties 文件中配置参数,以后只用改这里就可以了
jdbcDriver=com.mysql.jdbc.Driver dbUrl=jdbc:mysql://localhost:3306/query dbUserName=root dbPassword=123456 initConCount=10 maxConnects=100 inCrementalcount=2
第五步:测试JdbcPoolTest
测试用的junit ,需要导入对应的架包,
package jdbcpool; import java.sql.ResultSet; import org.junit.Before; import org.junit.Test; public class JdbcPoolTest { JdbcPool pool=DbManager.getInstance(); @Before public void before(){ pool.init(); } @Test public void select()throws Exception{ PooledConnection conn=pool.getConnection(); ResultSet rs=conn.queryBySql("select * from account "); System.out.println("线程名称:"+Thread.currentThread().getName()); while(rs.next()){ System.out.print(rs.getString("id")+" "); System.out.print(rs.getString("account_name")+" "); System.out.print(rs.getString("account_pwd")+" "); } rs.close(); conn.close(); } @Test public void threadTest() { for (int i = 0; i < 100; i++) { new Thread(new Runnable() { public void run() { try { select(); } catch (Exception e) { e.printStackTrace(); } } }).start(); } } }