从Python连接和测试JDBC驱动程序

从Python连接和测试JDBC驱动程序,python,jdbc,py4j,jpype,Python,Jdbc,Py4j,Jpype,我正在尝试使用Python对JDBC驱动程序进行一些测试 最初我弄明白了JPype,最终我连接了驱动程序并执行了select查询,如下所示(复制了一个通用的代码片段): 然而,我无法批量插入,这正是我想要测试的。即使executeBatch()返回了一个jpype int[],表示插入成功,表也没有更新 然后我决定试用py4j 我的困境——我很难想出如何做与上述相同的事情。据说py4j不能单独启动JVM,Java代码需要预先安排一个GatewayServer(),所以我不确定它是否可行 另一方面

我正在尝试使用Python对JDBC驱动程序进行一些测试

最初我弄明白了JPype,最终我连接了驱动程序并执行了select查询,如下所示(复制了一个通用的代码片段):

然而,我无法批量插入,这正是我想要测试的。即使
executeBatch()
返回了一个jpype int[],表示插入成功,表也没有更新

然后我决定试用py4j

我的困境——我很难想出如何做与上述相同的事情。据说py4j不能单独启动JVM,Java代码需要预先安排一个GatewayServer(),所以我不确定它是否可行

另一方面,有一个名为的库正是这样做的

我修改了dbapi.py代码,但不太了解其流程,因此被卡住了


如果有人知道如何使用py4j从.jar文件加载JDBC驱动程序,并能为我指明正确的方向,我将不胜感激

在添加记录之后和检索之前添加提交

conn.commit()

在py4j中,使用各自的JDBCURI:

from py4j.JavaGateway import java_gateway

# Open JVM interface with the JDBC Jar
jdbc_jar_path = '/path/to/jdbc_driver.jar'
gateway = java_gateway(classpath=jdbc_jar_path) 

# Load the JDBC Jar
jdbc_class = "com.vendor.VendorJDBC"
gateway.jvm.class.forName(jdbc_class)

# Initiate connection
jdbc_uri = "jdbc://vendor:192.168.x.y:zzzz;..."
con =  gateway.jvm.DriverManager.getConnection(jdbc_uri)

# Run a query
sql = "select this from that"
stmt = con.createStatement(sql)
rs = stmt.executeQuery()
while rs.next():
    rs.getInt(1)
    rs.getFloat(2)
    .
    .
rs.close()
stmt.close()

我在airflow中遇到了类似的问题,我使用teradata jdbc jars和jaydebeapi连接teradata数据库并执行sql:

[root@myhost transfer]# cat test_conn.py 
import jaydebeapi
from contextlib import closing


jclassname='com.teradata.jdbc.TeraDriver'
jdbc_driver_loc = '/opt/spark-2.3.1/jars/terajdbc4-16.20.00.06.jar,/opt/spark-2.3.1/jars/tdgssconfig-16.20.00.06.jar'
jdbc_driver_name = 'com.teradata.jdbc.TeraDriver'
host='my_teradata.address'

url='jdbc:teradata://' + host + '/TMODE=TERA'
login="teradata_user_name"
psw="teradata_passwd"

sql = "SELECT COUNT(*) FROM  A_TERADATA_TABLE_NAME where month_key='202009'"


conn = jaydebeapi.connect(jclassname=jdbc_driver_name,
                                  url=url, 
                                  driver_args=[login, psw],
                                  jars=jdbc_driver_loc.split(","))

with closing(conn) as conn:
    with closing(conn.cursor()) as cur:
        cur.execute(sql)
        print(cur.fetchall())
   
[root@myhost transfer]# python test_conn.py
[(7734133,)]
[root@myhost transfer]# 

嗯,嘘**。。非常感谢。然而,返回int[]是非常罕见和随机的,大多数情况下,即使setInt()、setString()、addBatch()通过,我也不会在executeBatch()之后获得返回值。默认情况下,JDBC驱动程序必须处于自动提交模式。在这种情况下调用
commit()
会引发异常。下面是自动提交的字符串:java.sql.Connection.setAutocommit()。此外,类似sqlalchemy的东西可能会有用。在“选择”标题下。演示如何使用其模块查询python本机数据库并避免将字符串作为查询发送。我自己正在学习这个模块如果你感兴趣的话。
[root@myhost transfer]# cat test_conn.py 
import jaydebeapi
from contextlib import closing


jclassname='com.teradata.jdbc.TeraDriver'
jdbc_driver_loc = '/opt/spark-2.3.1/jars/terajdbc4-16.20.00.06.jar,/opt/spark-2.3.1/jars/tdgssconfig-16.20.00.06.jar'
jdbc_driver_name = 'com.teradata.jdbc.TeraDriver'
host='my_teradata.address'

url='jdbc:teradata://' + host + '/TMODE=TERA'
login="teradata_user_name"
psw="teradata_passwd"

sql = "SELECT COUNT(*) FROM  A_TERADATA_TABLE_NAME where month_key='202009'"


conn = jaydebeapi.connect(jclassname=jdbc_driver_name,
                                  url=url, 
                                  driver_args=[login, psw],
                                  jars=jdbc_driver_loc.split(","))

with closing(conn) as conn:
    with closing(conn.cursor()) as cur:
        cur.execute(sql)
        print(cur.fetchall())
   
[root@myhost transfer]# python test_conn.py
[(7734133,)]
[root@myhost transfer]#