Jython和独立数据库连接池:如何确认池是Singleton

时间:2014-11-07 01:49:41

标签: java tomcat database-connection jython connection-pooling

问题:您是否可以在应用服务器容器外使用zxJDBC.connectx方法?

我在Jython中有自己的服务器应用程序,我正在寻求升级到使用数据库连接池(因为我现在手动构建和销毁单个连接)。我已经找到了一些示例代码并且已经使用它(使用Tomcat的连接池),但是它的工作方式让我感到烦恼。对我而言,看起来游泳池一次又一次地被创造出来。这是我的工作示例:

from __future__ import with_statement
from com.ziclix.python.sql import zxJDBC

params = { }
params['url'] = 'jdbc:mysql://localhost:3306/my_database'
params['driverClassName'] = 'com.mysql.jdbc.Driver'
params['username'] = 'mario'
params['password'] = 'myP@ssw0rd'
params['validationQuery'] = 'SELECT 1'
params['jdbcInterceptors'] = \
    'org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;' + \
    'org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer'

# This is the line that worries me!
conn = zxJDBC.connectx('org.apache.tomcat.jdbc.pool.DataSource', **params)

with conn.cursor() as cursor:
    cursor.execute('SELECT * FROM MyTable')
    data = cursor.fetchall()
    print data

conn.close()

看看“令我担忧的那条线”。我想使用zxJDBC连接对象,但是如果每次我获得它,我必须提供DataSource类名和设置参数,那么我认为首先要重新创建连接池每一次。那显然 不是我想要的。

有没有人确切知道发生了什么,或者我怎么可能会通过一些实验来确认发生了什么?如果我想在我的服务器中使用它,我应该复制servlet容器的JNDI基础结构吗?我无法理解DataSource到底是什么以及它是如何工作的?我不知道如何深究它。谢谢!


编辑:Jython源代码

我看了一下Jython源代码。 connectx类支持com.ziclix.python.sql.connect.Connectx方法。相关代码段如下所示:

/**
 * Construct a javax.sql.DataSource or javax.sql.ConnectionPooledDataSource
 */
@Override
public PyObject __call__(PyObject[] args, String[] keywords) {
    Connection c = null;
    PyConnection pc = null;
    Object datasource = null;
    PyArgParser parser = new PyArgParser(args, keywords);

    try {
        String klass = (String) parser.arg(0).__tojava__(String.class);
        datasource = Class.forName(klass).newInstance();
    } catch (Exception e) {
        throw zxJDBC.makeException(zxJDBC.DatabaseError, "unable to instantiate datasource");
    }

    /* 
     * The code continues on, setting up the connection pool's parameters, 
     * handling errors, etc., and obtaining a connection (variable: c). 
     */

    try {
        if (c == null || c.isClosed()) {
            throw zxJDBC.makeException(zxJDBC.DatabaseError, "unable to establish connection");
        }

        pc = new PyConnection(c);
    } catch (SQLException e) {
        throw zxJDBC.makeException(zxJDBC.DatabaseError, e);
    }

    return pc;
}

从源代码构建Jython并不是那么容易(似乎没有记录良好的依赖项),或者我会放入一些调试语句来比较datasource对象。但是当我尝试自己复制创作部分时......

datasource = Class.forName(klass).newInstance();

...在我看来,每次调用都会创建唯一的DataSource实例(因此,可能是唯一的池实例)。

有没有人对Jython有任何经验并且肯定知道?感谢。

1 个答案:

答案 0 :(得分:0)

根据我的研究,我提出了以下解决方案。

我没有使用大多数Jython示例代码中显示的更直接的方法,而是使用Java方法实例化DataSource。 (我从Apache Tomcat站点上的示例代码中获取此信息。)然后,我不使用zxJDBC方法来获取连接对象,而是使用该方法所依赖的内容:即com.ziclix.python.sql.PyConnection类。

结果是从池中抽取的传统Java连接对象,然后将其包装在PyConnection对象中,以便于Jython连接及其游标对象。

from __future__ import with_statement

from com.ziclix.python.sql import PyConnection
import org.apache.tomcat.jdbc.pool as pool

# https://people.apache.org/~fhanik/jdbc-pool/jdbc-pool.html
p = pool.PoolProperties()
p.setUrl('jdbc:mysql://localhost:3306/my_database')
p.setDriverClassName('com.mysql.jdbc.Driver')
p.setUsername('mario')
p.setPassword('myP@ssw0rd')
p.setValidationQuery("SELECT 1")
p.setJdbcInterceptors('org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;' + 
                      'org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer')

datasource = pool.DataSource()
datasource.setPoolProperties(p)

# http://www.jython.org/javadoc/com/ziclix/python/sql/PyConnection.html
conn = PyConnection(datasource.getConnection())

with conn.cursor() as cursor:
    cursor.execute('SELECT * FROM MyTable')
    data = cursor.fetchall()
    print data

conn.close()

我对这种方法更有信心。我有什么理由不这样做吗?