Tutorials to .com

Tutorials to .com » Jsp » Database » Dynamic use of JAVA agent database connection pool

Dynamic use of JAVA agent database connection pool

Print View , by: iSee ,Total views: 14 ,Word Count: 3225 ,Date: Sun, 19 Apr 2009 Time: 12:37 AM

database connection pool in the preparation of applications is often necessary to use the module, too frequent service to connect the database is a bottleneck in terms of performance, the use of buffer pool technology to eliminate the bottleneck. We can find a lot of the Internet on the source database connection pool, but found such a common problem: the realization of these methods of connection pooling are increased to varying degrees, and the coupling between users. Many have called the connection pool provided for the user, through its access to the database connection method, we can understand this point, after all, all the application servers the way check database connections are achieved in this way. However, another common problem is that they do not allow users at the same time explicit call Connection.close () method, and its provisions will need a way to close the connection. This approach has two shortcomings:

First: change the habits of users, an increase of the user's use of the difficulty.

First of all, we take a look at a normal operation of the database:


int executeSQL (String sql) throws SQLException
(
Connection conn = getConnection (); / / through some sort of access to the database connection
PreparedStatement ps = null;
int res = 0;
try (
ps = conn.prepareStatement (sql);
res = ps.executeUpdate ();
) finally (
try (
ps.close ();
) catch (Exception e) ()
try (
conn.close ();//
) catch (Exception e) ()
)
return res;
)




Users are usually used after the database connection is a direct call connection close to the release of database resources, if we mentioned earlier, the realization of the connection pool method statement conn.close () will be statements by certain alternative .

Second: The connection pool can not be carried out under the exclusive control of all connections. Since the connection pool does not allow users to connect directly call the close method, once the user in the use of the process used to directly as a result of the closure of a database connection, then connection pooling will not be able to maintain the normal state of all connections, consider the connection pool and application development by different staff to achieve when more prone to this problem.

Integrated the above-mentioned two issues, we discuss how to solve the problem of the two to death.

First of all, we look at first consider theusers to use the database connection pool. Users can access a specific way to connect the database and at the same time this type of connection should be standard java.sql.Connection. Users access to the database connection can be any connection to this operation, including the closure of the connection.

Through the description of users and how to take over our Connection.close method has become the subject of this article.

In order to take over the close database connection, we should have a hook-like mechanism. For example, in Windows programming Hook API we can use to achieve a takeover of the Windows API. In java will also be of such a mechanism. Proxy provides a java class and a InvocationHandler, these two categories in the java.lang.reflect package. Let's take a look at the documentation provided by the company SUN is how to describe these two categories.


public interface InvocationHandler

InvocationHandler is the interface implemented by the invocation handler of a proxy instance.

Each proxy instance has an associated invocation handler.
When a method is invoked on a proxy instance,
the method invocation is encoded and dispatched to the invoke method of its invocation handler.




SUN's API documentation on the description of Proxy many not listed here. InvocationHandler through the document on the interface description, we can see examples of when to invoke a method of Proxy will be triggered when the invoke method Invocationhanlder. Documents from JAVA, we also understand that the dynamic proxy mechanism that can only take over the interface method, and null and void on the general category, taking into account the java.sql.Connection interface itself is a result found a solution on how to take over the close approach way out.

First of all, we first define a database connection pool parameters of categories, the definition of the JDBC database driver class name, connection URL, as well as user name password, etc. Some of the information that such a connection pool for initialization of parameters, the specific definition of as follows:


public class ConnectionParam implements Serializable
(
private String driver; / / database-driven process
private String url; / / data connection URL
private String user; / / database user name
private String password; / / database password
private int minConnection = 0; / / initialize number of connections
private int maxConnection = 50; / / maximum number of connections
private long timeoutValue = 600000; / / Connect the biggest leisure time
private long waitTime = 30000; / / check connection if there is no available connection when the waiting time for the largest




Followed by the type of connection pooling factory ConnectionFactory, to the adoption of such a connection pool object with a name corresponding to the user by the name can be accessed on the specified connection pool object, the specific code as follows:


/ **
* Connection pool-type plants, such commonly used to preserve the name of a number of data sources database connection pool together the corresponding hash
* @ Author liusoft
* /
public class ConnectionFactory
(
/ / The hash table to save the data source and connection pool objects the relationship between the table
static Hashtable connectionPools = null;
static (
connectionPools = new Hashtable (2,0.75 F);
)
/ **
* From the connection pool factory to obtain the specified connection pool name of the corresponding object
* @ Param dataSource the corresponding connection pool object name
* @ Return DataSource to return the name of the corresponding connection pool object
* @ Throws NameNotFoundException can not find the specified connection pool
* /
public static DataSource lookup (String dataSource)
throws NameNotFoundException
(
Object ds = null;
ds = connectionPools.get (dataSource);
if (ds == null | |! (ds instanceof DataSource))
throw new NameNotFoundException (dataSource);
return (DataSource) ds;
)

/ **
* The specified name and the database connection configuration and bind together to initialize the database connection pool
* @ Param name the name of the corresponding connection pool
* @ Param param connection pool configuration parameters, see the specific category ConnectionParam
* @ Return DataSource return if binding is successful connection pool object
* @ Throws NameAlreadyBoundException certain the name of name has been thrown out of the binding is abnormal
* @ Throws ClassNotFoundException can not find the connection pool configuration in the driver category
* @ Throws IllegalAccessException connection pool configuration in the driver category is incorrect
* @ Throws InstantiationException driver can not be instantiated type
* @ Throws SQLException not specify the database connection
* /
public static DataSource bind (String name, ConnectionParam param)
throws NameAlreadyBoundException, ClassNotFoundException,
IllegalAccessException, InstantiationException, SQLException
(
DataSourceImpl source = null;
try (
lookup (name);
throw new NameAlreadyBoundException (name);
) catch (NameNotFoundException e) (
source = new DataSourceImpl (param);
source.initConnection ();
connectionPools.put (name, source);
)
return source;
)
/ **
* Re-bind the database connection pool
* @ Param name the name of the corresponding connection pool
* @ Param param connection pool configuration parameters, see the specific category ConnectionParam
* @ Return DataSource return if binding is successful connection pool object
* @ Throws NameAlreadyBoundException certain the name of name has been thrown out of the binding is abnormal
* @ Throws ClassNotFoundException can not find the connection pool configuration in the driver category
* @ Throws IllegalAccessException connection pool configuration in the driver category is incorrect
* @ Throws InstantiationException driver can not be instantiated type
* @ Throws SQLException not specify the database connection
* /
public static DataSource rebind (String name, ConnectionParam param)
throws NameAlreadyBoundException, ClassNotFoundException,
IllegalAccessException, InstantiationException, SQLException
(
try (
unbind (name);
) catch (Exception e) ()
return bind (name, param);
)
/ **
* Delete a database connection pool object
* @ Param name
* @ Throws NameNotFoundException
* /
public static void unbind (String name) throws NameNotFoundException
(
DataSource dataSource = lookup (name);
if (dataSource instanceof DataSourceImpl) (
DataSourceImpl dsi = (DataSourceImpl) dataSource;
try (
dsi.stop ();
dsi.close ();
) catch (Exception e) (
) finally (
dsi = null;
)
)
connectionPools.remove (name);
)

)




ConnectionFactory provides the users will be the main connection pool will be bound to a specific name and the cancellation of the binding operation. Users only need to be concerned about the use of these two types of the functions of database connection pool. Now we are given a period of how to use the connection pooling code:


String name = "pool";
String driver = "sun.jdbc.odbc.JdbcOdbcDriver";
String url = "jdbc: odbc: datasource";
ConnectionParam param = new ConnectionParam (driver, url, null, null);
param.setMinConnection (1);
param.setMaxConnection (5);
param.setTimeoutValue (20000);
ConnectionFactory.bind (name, param);
System.out.println ( "bind datasource ok.");
/ / The above code is used to register a connection pool object, the operation procedure can be initialized only once
/ / The following is the user really needs to start writing code
DataSource ds = ConnectionFactory.lookup (name);
try (
for (int i = 0; i <10; i + +) (
Connection conn = ds.getConnection ();
try (
testSQL (conn, sql);
) finally (
try (
conn.close ();
) catch (Exception e) ()
)
)
) catch (Exception e) (
e.printStackTrace ();
) finally (
ConnectionFactory.unbind (name);
System.out.println ( "unbind datasource ok.");
System.exit (0);
)




The sample code from the user can see, we have solved the conventional connection pool will cause two problems. But we most concerned about is how to resolve the approach to take over the close approach. ConnectionFactory to take over the work of the two sentences in the code:


source = new DataSourceImpl (param);
source.initConnection ();




DataSourceImpl is a realization of the javax.sql.DataSource interface class, such a connection pool to maintain the target. As a result of such is a protected category, so it exposed only to users of the methods defined in the DataSource interface methods, all the way to other users are not visible. We are concerned about the users first visit to a method getConnection


/ **
* @ See javax.sql.DataSource # getConnection (String, String)
* /
public Connection getConnection (String user, String password) throws SQLException
(
/ / First of all, free from the connection pool to find the target
Connection conn = getFreeConnection (0);
if (conn == null) (
/ / Determine whether the number of connections exceeds the maximum, if the connection exceeds the maximum number of
/ / Then wait for a certain period of time to see if there is free connection, or thrown to tell the user can be connected without
if (getConnectionCount ()> = connParam.getMaxConnection ())
conn = getFreeConnection (connParam.getWaitTime ());
else (/ / does not exceed the number of connections, re-access to a database connection
connParam.setUser (user);
connParam.setPassword (password);
Connection conn2 = DriverManager.getConnection (connParam.getUrl (),
user, password);
/ / Proxy will be returned to the connection object
_Connection _conn = New _Connection (conn2, true);
synchronized (conns) (
conns.add (_conn);
)
conn = _conn.getConnection ();
)
)
return conn;
)
/ **
* From the connection pool for a free connection
* @ Param nTimeout If the parameter value of 0 when not connected only to return a null
* Otherwise nTimeout milliseconds to wait to see if there are idle connections out if there is no abnormal
* @ Return Connection
* @ Throws SQLException
* /
protected synchronized Connection getFreeConnection (long nTimeout)
throws SQLException
(
Connection conn = null;
Iterator iter = conns.iterator ();
while (iter.hasNext ()) (
_Connection _conn = (_Connection) Iter.next ();
if (! _conn.isInUse ()) (
conn = _conn.getConnection ();
_conn.setInUse (true);
break;
)
)
if (conn == null & & nTimeout> 0) (
/ / Wait ms nTimeout to see if there is free connection
try (
Thread.sleep (nTimeout);
) catch (Exception e) ()
conn = getFreeConnection (0);
if (conn == null)
throw new SQLException ( "No database connection");
)
return conn;
)




DataSourceImpl class getConnection method to achieve with a normal database connection pool is the same logic, first of all determine whether there is any idle connection, if not determine whether the number of connections exceeds the maximum number of connections has some logic and so on. But there is one point difference is obtained through the DriverManager is not timely return the database connection, but through an intermediary called _Connection class and then call back to the _Connection.getConnection. If we do not through an intermediary that is JAVA to take over the Proxy to return to the interface object, then there is no way we stopped Connection.close method.

Finally to the core, we first take a look at is how to achieve the _Connection, and then introduce the client to call methods Connection.close What follows is a process, why has not really shut down the connection.


/ **
* Since the data connection package and method of shielding a close
* @ Author Liudong
* /
class _Connection implements InvocationHandler
(
private final static String CLOSE_METHOD_NAME = "close";
private Connection conn = null;
/ / Busy status of the database
private boolean inUse = false;
/ / Users to visit the last time connection method
private long lastAccessTime = System.currentTimeMillis ();

_Connection (Connection conn, boolean inUse) (
this.conn = conn;
this.inUse = inUse;
)
/ **
* Returns the conn.
* @ Return Connection
* /
public Connection getConnection () (
/ / Return the database connection conn-type receiver in order to stop close method
Connection conn2 = (Connection) Proxy.newProxyInstance (
conn.getClass (). getClassLoader (),
conn.getClass (). getInterfaces (), this);
return conn2;
)
/ **
* This method is a real closure of a database connection
* @ Throws SQLException
* /
void close () throws SQLException (
/ / Conn is due to type of property has not been taken over the connection, so call the close method as soon after the closure of the direct connection
conn.close ();
)
/ **
* Returns the inUse.
* @ Return boolean
* /
public boolean isInUse () (
return inUse;
)

/ **
* @ See java.lang.reflect.InvocationHandler # invoke (java.lang.Object, java.lang.reflect.Method, java.lang.Object)
* /
public Object invoke (Object proxy, Method m, Object [] args)
throws Throwable
(
Object obj = null;
/ / Determine whether to call the close method, if the method call while connected home close to useless state
if (CLOSE_METHOD_NAME.equals (m.getName ()))
setInUse (false);
else
obj = m.invoke (conn, args);
/ / Set the last access time in order to timely clear connection timeout
lastAccessTime = System.currentTimeMillis ();
return obj;
)

/ **
* Returns the lastAccessTime.
* @ Return long
* /
public long getLastAccessTime () (
return lastAccessTime;
)

/ **
* Sets the inUse.
* @ Param inUse The inUse to set
* /
public void setInUse (boolean inUse) (
this.inUse = inUse;
)
)




Once users get connected to call the close method, as a result of the user's connection object is the object after the takeover, so the opportunity to JAVA virtual _Connection.invoke first method call in the method to determine whether to close the first method, if not will be code has not been transferred to the real object to take over the connection conn. Otherwise, simply state that the connection is set to available. This you may understand the whole process of taking over, but at the same time there is a doubt: this is the case is not such a connection has been established yet no solution has been a real turn off? The answer is yes. We take a look at ConnectionFactory.unbind method to find the name of the corresponding first connection pool object, and then close the connection pool and all connections removed connection pool. DataSourceImpl the definition of class in a close method to close all the connection code details are as follows:


/ **
* Close the connection all the database connection pool
Return * @ return int the number of connections have been closed
* @ Throws SQLException
* /
public int close () throws SQLException
(
int C++ = 0;
SQLException excp = null;
Iterator iter = conns.iterator ();
while (iter.hasNext ()) (
try (
((_Connection) Iter.next ()). Close ();
cc + +;
) catch (Exception e) (
if (e instanceof SQLException)
excp = (SQLException) e;
)
)
if (excp! = null)
throw excp;
return cc;
)




This method is called one by one for each connection pool object close approach, the close method is _Connection corresponding to the realization of the close, in the definition of _Connection time to close the database connection is not directly call for closure of the object of takeover approach , so the way to really close the database resources released.

Text only description of the above methods of the interface to take over the specific connection pool of a practical module also need to connect to the free and timely release of the monitor connected to a detailed code please refer to the annex.

References:

http://java.sun.com
The official website of JAVA



Moderators Comments:
Did not look that complicated, it should be pretty good, but it only needs a simple agent model can be achieved. At the same time, we recommend the use of the app server to provide the connection pool. These connection pool connections are to be packaged. con.close () method is actually a return to the connection pool.


Jsp And Database Articles


Can't Find What You're Looking For?


Rating: Not yet rated

Comments

No comments posted.