1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > java jdbc init_Java 的JDBC 数据库连接池实现方法

java jdbc init_Java 的JDBC 数据库连接池实现方法

时间:2023-11-15 11:08:27

相关推荐

java jdbc init_Java 的JDBC 数据库连接池实现方法

虽然 J2EE 程序员一般都有现成的应用服务器所带的JDBC 数据库连接池,不过对于开发一般的 Java Application 、 Applet 或者 JSP、velocity 时,我们可用的JDBC 数据库连接池并不多,并且一般性能都不好。 Java 程序员都很羡慕 Windows ADO ,只需要 new Connection 就可以直接从数据库连接池中返回 Connection。并且 ADO Connection 是线程安全的,多个线程可以共用一个 Connection, 所以 ASP 程序一般都把 getConnection 放在 Global.asa 文件中,在 IIS 启动时建立数据库连接。ADO 的 Connection 和 Result 都有很好的缓冲,并且很容易使用。

其实我们可以自己写一个JDBC 数据库连接池。写 JDBC connection pool 的注意事项有:

1. 有一个简单的函数从连接池中得到一个 Connection。

2. close 函数必须将 connection 放回 数据库连接池。

3. 当数据库连接池中没有空闲的 connection,数据库连接池必须能够自动增加 connection 个数。

4. 当数据库连接池中的 connection 个数在某一个特别的时间变得很大,但是以后很长时间只用其中一小部分,应该可以自动将多余的 connection 关闭掉。

5. 如果可能,应该提供debug 信息报告没有关闭的 new Connection 。

如果要 new Connection 就可以直接从数据库连接池中返回 Connection, 可以这样写( Mediator pattern ) (以下代码中使用了中文全角空格):

public class EasyConnection implements java.sql.Connection{

private Connection m_delegate = null;

public EasyConnection(){

m_delegate = getConnectionFromPool();

}

public void close(){

putConnectionBackToPool(m_delegate);

}

public PreparedStatement prepareStatement(String sql) throws SQLException{

m_delegate.prepareStatement(sql);

}

//...... other method

}

看来并不难。不过不建议这种写法,因为应该尽量避免使用 Java Interface, 关于 Java Interface 的缺点我另外再写文章讨论。大家关注的是 Connection Pool 的实现方法。下面给出一种实现方法。

import java.sql.*;

import java.lang.reflect.*;

import java.util.*;

import java.io.*;

public class SimpleConnetionPool {

private static LinkedList m_notUsedConnection = new LinkedList();

private static HashSet m_usedUsedConnection = new HashSet();

private static String m_url = "";

private static String m_user = "";

private static String m_password = "";

static final boolean DEBUG = true;

static private long m_lastClearClosedConnection = System.currentTimeMillis();

public static long CHECK_CLOSED_CONNECTION_TIME = 4 * 60 * 60 * 1000; //4 hours

static {

initDriver();

}

private SimpleConnetionPool() {

}

private static void initDriver() {

Driver driver = null;

//load mysql driver

try {

driver = (Driver) Class.forName("com.mysql.jdbc.Driver").newInstance();

installDriver(driver);

} catch (Exception e) {

}

//load postgresql driver

try {

driver = (Driver) Class.forName("org.postgresql.Driver").newInstance();

installDriver(driver);

} catch (Exception e) {

}

}

public static void installDriver(Driver driver) {

try {

DriverManager.registerDriver(driver);

} catch (Exception e) {

e.printStackTrace();

}

}

public static synchronized Connection getConnection() {

clearClosedConnection();

while (m_notUsedConnection.size() > 0) {

try {

ConnectionWrapper wrapper = (ConnectionWrapper) m_notUsedConnection.removeFirst();

if (wrapper.connection.isClosed()) {

continue;

}

m_usedUsedConnection.add(wrapper);

if (DEBUG) {

wrapper.debugInfo = new Throwable("Connection initial statement");

}

return wrapper.connection;

} catch (Exception e) {

}

}

int newCount = getIncreasingConnectionCount();

LinkedList list = new LinkedList();

ConnectionWrapper wrapper = null;

for (int i = 0; i < newCount; i++) {

wrapper = getNewConnection();

if (wrapper != null) {

list.add(wrapper);

}

}

if (list.size() == 0) {

return null;

}

wrapper = (ConnectionWrapper) list.removeFirst();

m_usedUsedConnection.add(wrapper);

m_notUsedConnection.addAll(list);

list.clear();

return wrapper.connection;

}

private static ConnectionWrapper getNewConnection() {

try {

Connection con = DriverManager.getConnection(m_url, m_user, m_password);

ConnectionWrapper wrapper = new ConnectionWrapper(con);

return wrapper;

} catch (Exception e) {

e.printStackTrace();

}

return null;

}

static synchronized void pushConnectionBackToPool(ConnectionWrapper con) {

boolean exist = m_usedUsedConnection.remove(con);

if (exist) {

m_notUsedConnection.addLast(con);

}

}

public static int close() {

int count = 0;

Iterator iterator = m_notUsedConnection.iterator();

while (iterator.hasNext()) {

try {

( (ConnectionWrapper) iterator.next()).close();

count++;

} catch (Exception e) {

}

}

m_notUsedConnection.clear();

iterator = m_usedUsedConnection.iterator();

while (iterator.hasNext()) {

try {

ConnectionWrapper wrapper = (ConnectionWrapper) iterator.next();

wrapper.close();

if (DEBUG) {

wrapper.debugInfo.printStackTrace();

}

count++;

} catch (Exception e) {

}

}

m_usedUsedConnection.clear();

return count;

}

private static void clearClosedConnection() {

long time = System.currentTimeMillis();

//sometimes user change system time,just return

if (time < m_lastClearClosedConnection) {

time = m_lastClearClosedConnection;

return;

}

//no need check very often

if (time - m_lastClearClosedConnection < CHECK_CLOSED_CONNECTION_TIME) {

return;

}

m_lastClearClosedConnection = time;

//begin check

Iterator iterator = m_notUsedConnection.iterator();

while (iterator.hasNext()) {

ConnectionWrapper wrapper = (ConnectionWrapper) iterator.next();

try {

if (wrapper.connection.isClosed()) {

iterator.remove();

}

} catch (Exception e) {

iterator.remove();

if (DEBUG) {

System.out.println("connection is closed, this connection initial StackTrace");

wrapper.debugInfo.printStackTrace();

}

}

}

//make connection pool size smaller if too big

int decrease = getDecreasingConnectionCount();

if (m_notUsedConnection.size() < decrease) {

return;

}

while (decrease-- > 0) {

ConnectionWrapper wrapper = (ConnectionWrapper) m_notUsedConnection.removeFirst();

try {

wrapper.connection.close();

} catch (Exception e) {

}

}

}

/**

* get increasing connection count, not just add 1 connection

* @return count

*/

public static int getIncreasingConnectionCount() {

int count = 1;

int current = getConnectionCount();

count = current / 4;

if (count < 1) {

count = 1;

}

return count;

}

/**

* get decreasing connection count, not just remove 1 connection

* @return count

*/

public static int getDecreasingConnectionCount() {

int count = 0;

int current = getConnectionCount();

if (current < 10) {

return 0;

}

return current / 3;

}

public synchronized static void printDebugMsg() {

printDebugMsg(System.out);

}

public synchronized static void printDebugMsg(PrintStream out) {

if (DEBUG == false) {

return;

}

StringBuffer msg = new StringBuffer();

msg.append("debug message in " + SimpleConnetionPool.class.getName());

msg.append("\r\n");

msg.append("total count is connection pool: " + getConnectionCount());

msg.append("\r\n");

msg.append("not used connection count: " + getNotUsedConnectionCount());

msg.append("\r\n");

msg.append("used connection, count: " + getUsedConnectionCount());

out.println(msg);

Iterator iterator = m_usedUsedConnection.iterator();

while (iterator.hasNext()) {

ConnectionWrapper wrapper = (ConnectionWrapper) iterator.next();

wrapper.debugInfo.printStackTrace(out);

}

out.println();

}

public static synchronized int getNotUsedConnectionCount() {

return m_notUsedConnection.size();

}

public static synchronized int getUsedConnectionCount() {

return m_usedUsedConnection.size();

}

public static synchronized int getConnectionCount() {

return m_notUsedConnection.size() + m_usedUsedConnection.size();

}

public static String getUrl() {

return m_url;

}

public static void setUrl(String url) {

if (url == null) {

return;

}

m_url = url.trim();

}

public static String getUser() {

return m_user;

}

public static void setUser(String user) {

if (user == null) {

return;

}

m_user = user.trim();

}

public static String getPassword() {

return m_password;

}

public static void setPassword(String password) {

if (password == null) {

return;

}

m_password = password.trim();

}

}

class ConnectionWrapper implements InvocationHandler {

private final static String CLOSE_METHOD_NAME = "close";

public Connection connection = null;

private Connection m_originConnection = null;

public long lastAccessTime = System.currentTimeMillis();

Throwable debugInfo = new Throwable("Connection initial statement");

ConnectionWrapper(Connection con) {

this.connection = (Connection) Proxy.newProxyInstance(

con.getClass().getClassLoader(),

con.getClass().getInterfaces(), this);

m_originConnection = con;

}

void close() throws SQLException {

m_originConnection.close();

}

public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {

Object obj = null;

if (CLOSE_METHOD_NAME.equals(m.getName())) {

SimpleConnetionPool.pushConnectionBackToPool(this);

}

else {

obj = m.invoke(m_originConnection, args);

}

lastAccessTime = System.currentTimeMillis();

return obj;

}

}

使用方法

public class TestConnectionPool{

public static void main(String[] args) {

SimpleConnetionPool.setUrl(DBTools.getDatabaseUrl());

SimpleConnetionPool.setUser(DBTools.getDatabaseUserName());

SimpleConnetionPool.setPassword(DBTools.getDatabasePassword());

Connection con = SimpleConnetionPool.getConnection();

Connection con1 = SimpleConnetionPool.getConnection();

Connection con2 = SimpleConnetionPool.getConnection();

//do something with con ...

try {

con.close();

} catch (Exception e) {}

try {

con1.close();

} catch (Exception e) {}

try {

con2.close();

} catch (Exception e) {}

con = SimpleConnetionPool.getConnection();

con1 = SimpleConnetionPool.getConnection();

try {

con1.close();

} catch (Exception e) {}

con2 = SimpleConnetionPool.getConnection();

SimpleConnetionPool.printDebugMsg();

}

}

运行测试程序后打印连接池中 Connection 状态,以及正在使用的没有关闭 Connection 信息。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。