JDBC学习笔记(18):通过代理模式来保持用户关闭连接的习惯

在前面的JdbcUtils包中,在关闭连接的时候使用了conn.close()方法,如果关闭了连接,那么放回连接池中的连接就成为无效的连接,为了规范用户关闭连接的习惯,使用代理模式来将连接放回连接池而又不改变用户的程序:

将JdbcUtils工具包改变回原来的情形:

 1 package com.xxyh.jdbc;
 2 import java.sql.Connection;
 3 import java.sql.ResultSet;
 4 import java.sql.SQLException;
 5 import java.sql.Statement;
 6 import com.xxyh.jdbc.datasource.MyDataSource2;
 7 public class JdbcUtils {
 8     private static MyDataSource2 myDataSource = null;
 9
10     private JdbcUtils() {
11     }
12
13     static {
14         try {
15             // 将注册驱动放在静态代码块中只需执行一次
16             Class.forName("com.mysql.jdbc.Driver");
17             myDataSource = new MyDataSource2();
18         } catch(ClassNotFoundException e) {
19             throw new ExceptionInInitializerError(e);
20         }
21     }
22
23     public static Connection getConnection() throws SQLException {
24 //        return DriverManager.getConnection(url, user, password);
25         // 当需要连接的时候,不再创建,而是从连接池中获取
26         return myDataSource.getConnection();
27     }
28
29     public static void close(ResultSet rs, Statement stmt, Connection conn) {
30         try {
31             if (rs != null) {
32                 rs.close();
33             }
34         } catch (SQLException e) {
35             e.printStackTrace();
36         } finally {
37             try {
38                 if (stmt != null) {
39                     stmt.close();
40                 }
41             } catch (SQLException e) {
42                 e.printStackTrace();
43             } finally {
44                 if (conn != null) {
45                     try {
46                         conn.close();    ///////按照常用情形关闭连接
47                         // 将连接放回连接池,而不是关闭连接
48 //                        myDataSource.free(conn);
49                     } catch (Exception e) {
50                         e.printStackTrace();
51                     }
52                 }
53             }
54         }
55     }
56 }

创建自己的连接方式,实现java.sql.Connection接口,截取部分代码:

 1 package com.xxyh.jdbc.datasource;
 2 import java.sql.Array;
 3 import java.sql.Blob;
 4 import java.sql.CallableStatement;
 5 import java.sql.Clob;
 6 import java.sql.Connection;
 7 import java.sql.DatabaseMetaData;
 8 import java.sql.NClob;
 9 import java.sql.PreparedStatement;
10 import java.sql.SQLClientInfoException;
11 import java.sql.SQLException;
12 import java.sql.SQLWarning;
13 import java.sql.SQLXML;
14 import java.sql.Savepoint;
15 import java.sql.Statement;
16 import java.sql.Struct;
17 import java.util.Map;
18 import java.util.Properties;
19 import java.util.concurrent.Executor;
20 public class MyConnection implements Connection{
21
22     private Connection realConnetion; // 真正的数据库连接,可能来源于MySQL、Oracle、DB2……
23     private MyDataSource2 dataSource;
24
25     MyConnection(Connection connection, MyDataSource2 dataSource) {
26         this.realConnetion = connection;
27         this.dataSource = dataSource;
28     }
29
30     @Override
31     public void close() throws SQLException {
32         this.dataSource.connectionsPool.addLast(this);
33     }
34
35     @Override
36     public void commit() throws SQLException {
37         // TODO Auto-generated method stub
38         this.realConnetion.commit();
39     }

以上只是部分代码,值得注意的是close方法,并不是将连接关闭,而是让它放回连接池。

连接池:

 1 package com.xxyh.jdbc.datasource;
 2 import java.sql.Connection;
 3 import java.sql.DriverManager;
 4 import java.sql.SQLException;
 5 import java.util.LinkedList;
 6 public class MyDataSource2 {
 7     private static String url = "jdbc:mysql://localhost:3306/jdbc?generateSimpleParameterMetadata=true";
 8     private static String user = "root";
 9     private static String password = "1234";
10
11     private static int initCount = 5;    // 初始连接数
12     private static int maxCount = 10;    // 最大连接数
13     private int currentCount = 0;        // 当前连接数
14
15     ////////包内可见
16     LinkedList<Connection> connectionsPool = new LinkedList<>();
17
18     public MyDataSource2() {
19         try {
20             // 创建 5 个连接
21             for (int i = 0; i < initCount; i++) {
22                 this.connectionsPool.addLast(this.createConnection());
23                 this.currentCount++;
24             }
25         } catch (SQLException e) {
26             throw new ExceptionInInitializerError(e);
27         }
28     }
29
30     private Connection createConnection() throws SQLException {
31         Connection realConn = DriverManager.getConnection(url, user, password);
32         MyConnection myConnection = new MyConnection(realConn, this);
33         return myConnection;
34     }
35
36     public void free(Connection conn) {
37         // 释放一个连接,将它放回连接池
38         this.connectionsPool.addLast(conn);
39     }
40
41     public Connection getConnection() throws SQLException {
42         // 从连接池中获取一个连接
43         synchronized(connectionsPool) {
44             if (this.connectionsPool.size() > 0)
45                 return this.connectionsPool.removeFirst();
46
47             // 如果连接池中没有连接且当前连接小于最大连接,则创建一个连接
48             if (this.currentCount < maxCount) {
49                 this.currentCount++;
50                 return this.createConnection();
51             }
52
53             throw new SQLException("已没有连接");
54         }
55     }
56 }

测试创建的连接:

 1 package com.xxyh.jdbc;
 2 import java.sql.Connection;
 3 import java.sql.DriverManager;
 4 import java.sql.ResultSet;
 5 import java.sql.SQLException;
 6 import java.sql.Statement;
 7 public class Base {
 8     public static void main(String[] args) throws ClassNotFoundException, SQLException {
 9
10         for (int i = 0; i < 5; i++) {
11             Connection conn = JdbcUtils.getConnection();
12             System.out.println(conn);
13             JdbcUtils.close(null, null, conn);
14         }
15     }
16 }

【运行结果】:

com.xxyh.jdbc.datasource.MyConnection@59ea632e

com.xxyh.jdbc.datasource.MyConnection@2b158f20

com.xxyh.jdbc.datasource.MyConnection@146793f9

com.xxyh.jdbc.datasource.MyConnection@1c23cae6

com.xxyh.jdbc.datasource.MyConnection@71ddd078

时间: 2024-08-29 07:04:02

JDBC学习笔记(18):通过代理模式来保持用户关闭连接的习惯的相关文章

Java学习笔记——设计模式之四.代理模式

To be, or not to be: that is the question. --<哈姆雷特> 代理模式(Proxy),为其他对象提供一种代理以控制对这个对象的访问. 上代码: 1 package cn.no4.proxy; 2 3 public interface IMakeMoney { 4 5 void makeMoney(); 6 } 1 package cn.no4.proxy; 2 3 public class Proxy implements IMakeMoney { 4

java学习笔记-设计模式9(代理模式)

意图 为其他对象提供一种代理以控制对这个对象的访问. public interface Sourceable { public void method(); } public class Source implements Sourceable{ @Override public void method() { System.out.println("this is original method!"); } } public class Proxy implements Source

《大话设计模式》学习笔记18:桥接模式

手机品牌及手机软件示例: 1.Implementor: public abstract class HandsetSoft { public abstract void Run(); } 2.ConcreteImplementor(以游戏类为例): public class HandsetGame:HandsetSoft { public override void Run() { Console.WriteLine("运行手机游戏"); } } 3.Abstraction: publ

Ext.Net学习笔记18:Ext.Net 可编辑的GridPanel

Ext.Net学习笔记18:Ext.Net 可编辑的GridPanel Ext.Net GridPanel 有两种编辑模式:编辑单元格和编辑行. 单元格编辑: 行编辑: 可以看出,单元格编辑的时候,只有单元格会进入编辑模式,而行编辑模式中则对编辑行的所有可编辑字段统一进行编辑,通过Update进行更新,Cancel进行取消编辑. 要对Ext.Net GridPanel进行编辑,需要进行两步配置: 配置列的编辑控件(TextField.NumberField.DateField等) 配置编辑插件(

Android学习笔记18:自定义Seekbar拖动条式样

Android学习笔记18:自定义Seekbar拖动条式样

java学习笔记14--动态代理

java学习笔记14--动态代理 InvocationHandler接口 [java] view plaincopy public interface InvocationHandler{ public Object invoke(Object proxy,Method method,Object[] args)throws Throwable } 参数说明: Object  proxy:被代理的对象 Method  method:要调用的方法 Object   args[]:方法调用时所需要的

Oracle 学习笔记 18 -- 存储函数和存储过程(PL/SQL子程序)

PL/SQL子程序 包括函数和过程.这里的函数指的是用户自己定义的函数,和系统函数是不同的.子程序一般是完成特定功能的PL/SQL程序块,并且具有一定的通用性,可以被不同的应用程序多次调用.Oracle提供可以把PL/SQL程序存储在数据库中,并可以再任何地方来运行它.这样就叫做存储过程或者是函数.过程和函数的唯一区别就是函数总是向调用者返回数据,而过程则不返回数据. 函数 如果用户要经常执行某些操作,并且需要返回特定的数据,那么就可以将这些操作构造成一个函数. 可以使用SQL语句定义函数. 基

概率图模型(PGM)学习笔记(三)模式推断与概率图流

我们依然使用"学生网络"作为例子,如图1. 图1 首先给出因果推断(Causal Reasoning)的直觉解释. 可以算出来 即学生获得好的推荐信的概率大约是0.5. 但如果我们知道了学生的智商比较低,那么拿到好推荐信的概率就下降了: 进一步,如果又同时知道了考试的难度很低,那么他拿到好的推荐信得概率又上升了,甚至还能超过最初的概率: 上述这个过程就是因果推断,你看它是顺着箭头的方向进行推断. 其次给出信度推断(Evidential Reasoning)的直觉解释.如图2. 图2 本

springmvc学习笔记(18)-json数据交互

springmvc学习笔记(18)-json数据交互 springmvc学习笔记18-json数据交互 springmvc进行json交互 环境准备 添加json转换的依赖 配置json转换器 json交互测试 输入json串输出是json串 输入keyvalue输出是json串 本文主要介绍如何在springmvc中进行json数据的交互,先是环境准备和配置,然后分别展示了"输入json串,输出是json串"和"输入key/value,输出是json串"两种情况下