zoukankan      html  css  js  c++  java
  • 数据库连接池原理 与实现(动脑学院Jack老师课后自己的练习有感)

    第一步: 首先创建一个数据库连接池的接口:

        数据库连接池接口有两个主要的方法,其中一个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();
            }
        }
        
        
    }
  • 相关阅读:
    java ppt4
    课后作业 2
    课后作业2
    java ppt题目
    CommandParameter设计
    《大道至简》第二章读后感
    8.多态
    7.接口与继承
    6.数组
    字符串
  • 原文地址:https://www.cnblogs.com/softwarewebdesign/p/5902662.html
Copyright © 2011-2022 走看看