最近项目上要用python对接intersystems-cache 数据库。尝试过使用pyodbc 通过odbc驱动连接,但是一直出现字符编码数据截断问题。想到了java 的强大生态。觉定用 python 调用 jdbc 去尝试下。
考虑过使用JayDeBeApi 去调用jar包。实现jdbc 去连接。开始发现JayDeBeApi 这个包对类型转换做的并是不很好,比如BLOB字段不能正确转换,查看源码时发现它其实调用的是JPype1 通过JPype1 调用的jar包。然后觉定去看JPype1 的 文档说明。刚好发现。JPype1的 1.1.1 已经发布 并且从这个版本开始支持 dbapi2 也就是说我们直接使用JPype1 就可以更好的是想python 通过jdbc 去连接种数据库了。所以只要你安装了JPype1的 1.1.1 及以上的版本,就可以直接实现jdbc 的调用了
环境准备
- java 1.8 以及以上。需要配置java_home
- JPype1的版本要在1.1.1以上
pip install JPype1>=1.1.1
- 要使用的jdbc Jar 包
这里简单的提供intersystems cache数据库的连接样例 ,因为这个数据库 odbc 不完善比较常用。
python通过jdbc 连接intersystems cache 数据库
用的是 名字 为这个的 intersystems-jdbc-3.1.0.jar 包。如果有需要可以站内私我。如果用其他版本的也是可以的
伪代码如下:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
try:
import jpype.imports
from jpype import JInt, JShort
from jpype import dbapi2
# 这个目录以启动文件所在位置开始算起,不是当前文件开始。这很重要,否则可能找不到jar包
# 加载jdbc -jar 包
jpype.startJVM(classpath=['intersystems-jdbc-3.1.0.jar'])
# python 语法导入java 类
from com.intersystems.jdbc import *
if jpype.__version__ < '1.1.0':
raise EnvironmentError('jpype1 need version >=1.1.0,please check jpype1 version')
except ImportError:
raise ImportError('improt jpype occurred an error ')
# jdbc连接串 不同的jar 包连接串不同 1972 是端口 dbname 是数据库名称
conn_url = "jdbc:IRIS://10.xxx.xxx.4x:1972/dbname?useUnicode=true&characterEncoding=UTF-8"
# 用户名和密码设置
driver_args={"user":"TEST","password":"test"}
# 通过dbapi2中的connect 方法设置获取到数据库连接
conn = dbapi2.connect(conn_url,driver='com.intersystems.jdbc.IRISDriver',driver_args=driver_args)
conn.converters[JInt] = str
conn.converters[JShort] = str
# 获取到cursor
cur = conn.cursor()
# 执行sql 传参
cur.execute('SELECT CODE, NAME FROM DICT where NAME=? ',("办公室",))
res = cur.fetchone()
print(res)
#['1', '办公室']
# 结果字典类型输出
columns = [column[0].upper() for column in cur.description]
dict_res = dict(zip(columns, res))
print(dict_res)
#{'CODE': '1', 'NAME': '办公室'}
intersystems-jdbc-3.1.0.jar 这个jar包 是提供给 IRIS 的intersystems 把cache 又整合了一下变成了iris 如果还是用原来的jar包cache-jdbc-2.0.0.jar 则连接串会发生变化如下
#!/usr/bin/env python
# -*- coding:utf-8 -*-
try:
import jpype.imports
from jpype import JInt, JShort
from jpype import dbapi2
# 这个目录以启动文件所在位置开始算起,不是当前文件开始。这很重要,否则可能找不到jar包
# 加载jdbc -jar 包
jpype.startJVM(classpath=['cache-jdbc-2.0.0.jar'])
# python 语法导入java 类
from com.intersys.jdbc import *
if jpype.__version__ < '1.1.0':
raise EnvironmentError('jpype1 need version >=1.1.0,please check jpype1 version')
except ImportError:
raise ImportError('improt jpype occurred an error ')
# jdbc连接串 不同的jar 包连接串不同 1972 是端口 dbname是连接名
conn_url = "jdbc:Cache://10.xxx.xx.xx:1972/dbname?useUnicode=true&characterEncoding=UTF-8"
# 用户名和密码设置
driver_args={"user":"TEST","password":"test"}
# 通过dbapi2中的connect 方法设置获取到数据库连接
conn = dbapi2.connect(conn_url,driver='com.intersys.jdbc.CacheDriver',driver_args=driver_args)
#顺便说下获取到连接后可以自定义 类型转换 比如有点数据是Jint java bytes 类型的到python下可能要转换。可以给connect 增加转换方法,如下 下面的str 意思是 将数据直接转换成python(str) 类型,类似 str(value),当然也可以是一个方法,这个很重要可以解决数据类型不兼容的问题
conn.converters[JInt] = str
conn.converters[JShort] = str
# 获取到cursor
cur = conn.cursor()
# 执行sql 传参
cur.execute('SELECT CODE, NAME FROM DICT where NAME=? ',("办公室",))
res = cur.fetchone()
print(res)
#['1', '办公室']
# 结果字典类型输出
columns = [column[0].upper() for column in cur.description]
dict_res = dict(zip(columns, res))
print(dict_res)
#{'CODE': '1', 'NAME': '办公室'}
其他类型的数据库连接方式大同小异吧 oracle,mysql,mssql 这里就不赘述了.如有问题,可以给我留言