数据库连接池中的connection在八小时内没有被用到,则会自动断开连接,那么怎么处理数据库连接超时的问题?

         我在自己写mybatis框架的时候,这样处理的:首先确保连接池中有指定数量的链接:将connection和创建时间System.currentTimeMillis()以键值对的形式存放在map集合中,用一个定时器,每隔1小时检查一下连接数目,数目大于指定个数,则从map中移除,小于指定个数,则加入新的链接。其次:检查连接在7个小时内是否被用,如果没有被用,则执行一个sql语句:String sql = "drop table if exists tables";将connection对象重新加入到map集合中。

我的代码:

public class ConnectionFacory{
         private static ConnectionFacory instance;
         private static DBConn dbConn = new DBConn();//获取链接的类
         private static String fileName = null;//数据库的文件名,先为null,初始化对象后改为传入的值
         
         /**
          * 需要知道连接池中的连接是否被使用。
          * 如果用Map<Connection,time>的数据类型去保存
          * time为初始化连接的毫秒值,没有使用过的话设置为0.
          * 从数据库获取时,设置获取当前的时间毫秒值。
          * 并把这个连接加入到另一个连接池中
          * 
          */
         private static Map<Connection,Long> connectionPool =new HashMap<Connection,Long>();
         
         /**
          * 设置最大时间为一个常量
          */
          public static finallong MAX_UNUSED_TIME = 7 * 60 *60 * 1000; 
         
         /**
          * 使用的连接都加入到这个连接池中
          */
         private static Map<Connection,Long> connectionUsePool= new HashMap<Connection,Long>();
         
         private ConnectionFacory(){
         }
         
         public static synchronized ConnectionFacorygetInstance(String fileName){
                   if(instance == null){
                            instance = new ConnectionFacory();
                            
                            ConnectionFacory.fileName = fileName;//属于共享数据
                            initPool(20);
                            timer();
                   }
                   
                   return instance;
         }
 
         public static void initPool(int connectionCount) {
                   //得到connectionCount个连接,并把连接加入到连接池中
                   for (int i = 0; i < connectionCount; i++) {
                            connectionPool.put(dbConn.getConnection(fileName),System.currentTimeMillis());//添加进来的连接都没有使用过。
                   }
         }
         
         public Connection getConnection(){
                   Connection conn = null;
                   
                   //如果connectionPool为空,说明连接池中没有连接,要向连接池中添加一个连接
                   if(connectionPool.isEmpty()){
                            connectionPool.put(dbConn.getConnection(fileName),System.currentTimeMillis());
                   }
                   
                   //从连接池中获取一个连接,获取的时候,也获取时间,保存到另一个连接池中
                   Entry<Connection, Long> en =connectionPool.entrySet().iterator().next();
                   conn = en.getKey();//获取一个connection对象。
                   connectionPool.remove(conn);//移除con对象
                   
                   return conn;
         }
         
         /*
          * 设置一个定时器
          *   每隔一个小时监测一下connectionpool连接池中的连接个数
          *   如果个数过少,创建新连接,如果个数过多,则移除连接.
          *   还要保证连接是持续的,保证每8小时执行一次sql语句
          */
         public static void timer(){
                   Timer timer = new Timer();
                   
                   timer.scheduleAtFixedRate(new TimerTask() {
                            //指定时间要执行的代码
                            @Override
                            public void run() {
                                     int size =connectionPool.size();
                                     /**
                                      * 对连接池的连接进行检验,小于20个,则说明连接池的数量过少,需要向里面添加新连接至20个。
                                      * 但是正在使用的连接可能还会归还,所以以后还可能多出来连接。所以还要检验连接数量是否多余20个。
                                      */
                                     if(size < 20){
                                               for (; size < 21;size++) {
                                                        connectionPool.put(dbConn.getConnection(fileName),System.currentTimeMillis());
                                               }
                                     }
                                     
                                     /**
                                      * 因为检测到连接小于20个时,可能有些连接正在使用,会添加连接至20个。
                                      * 当正在使用的连接已经使用完了,会归还给连接池,这是连接池的数量会多于20个,所以要删除多余的连接,这样保证连接的数量动态平衡。
                                      * 移除时尽量移除长时间不使用的连接
                                      *
                                      */
                                     if(size > 20){
                                               for (; size < 21;size--) {
//                                                     Entry<Connection,Long> en = connectionPool.entrySet().iterator().next();
                                                        connectionPool.remove(0);//移除con对象
                                               }
                                     }
                                     
                                     //链接8小时后就会关,所以八小时内就要使用一次,而且再次执行会判断用不用!
                                     /*
                                      * 判断前连接是否八小时内被执行过,
                                      * 如果执行过,那么不用管,
                                      * 如果没有被执行过,那么执行一天sql语句,确保连接不会关闭。
                                      * 一个大的连接池,用来保存总的连接数。
                                      * 将使用的连接使用时,保存到另一个连接中
                                      * 但是怎么确保连接的时间呢?
                                      */
                                     //遍历这连接池中所有的连接,查看每个连接用的时间,如果时间7个小时没有用了,那么使用一次
                                     /**
                                      * 每次得到当前时间,计算出时间差,超过7小时没有使用,就使用一次。
                                      */
                                     
                                     /*
                                      * 定义一个Map集合,用于存放con和是否被修改的变量
                                      * 为什么要不直接把这个connection重新加入到map中,而要重新定义这个变量?
                                      * 因为map集合在遍历的时候不能修改集合,否则会出现异常。
                                      */
                                     Map<Boolean,Connection>conMap = new HashMap<Boolean,Connection>();
 
                                     /*
                                      * for循环遍历的时候不能修改集合元素的内容。
                                      */
                                     for (Entry<Connection,Long> en : connectionPool.entrySet()) {
                                               long time =System.currentTimeMillis() - en.getValue();
                                               
                                               Connection con =en.getKey();
                                               if(time >MAX_UNUSED_TIME){
                                                        /**
                                                         * 执行一个sql语句
                                                         */
                                                        
                                                        String sql ="drop table if exists tables";
                                                        
                                                        try {
                                                                 con.prepareStatement(sql).execute();
                                                                 
                                                                 conMap.put(true,con);
                                                                 
                                                        } catch(SQLException e) {
                                                                 thrownew RuntimeException("run sql fail!");
                                                        }
                                               }
                                               
                                               conMap.put(false,con);
                                     }
                                     
                                     /*
                                      * 遍历conMap,如果是false那么取得con,再次存入ConnectionPool中
                                      */
                                     for (Entry<Boolean, Connection>en : conMap.entrySet()) {
                                               if(en.getKey()){
                                                        connectionPool.put(en.getValue(),System.currentTimeMillis());
                                               }
                                     }
                            }
                   }, 0, 60 * 1000);
         }
}