Python 通过JPype1调用JDBC实现多数据库连接实战指南

## 1. 为什么选择JPype1+JDBC这条路? 最近在做一个数据整合项目,需要让Python程序去连接一个比较小众的数据库——InterSystems Cache。说实话,一开始我也走了弯路,想着用Python生态里最常见的`pyodbc`配合ODBC驱动去连,毕竟这条路子听起来最“标准”。但实际一跑,问题就来了:中文数据读出来老是乱码,长一点的文本字段动不动就被截断,调试了半天,各种编码参数都试遍了,还是解决不了。后来查资料才知道,对于一些特定数据库(尤其是像Cache这种),其官方提供的ODBC驱动在某些版本或场景下,对非ASCII字符集的支持可能并不完善,这坑踩得我够呛。 就在我头疼的时候,突然想起了Java那庞大而成熟的数据库生态。几乎你能想到的任何数据库,官方或社区都会提供高质量、功能完整的JDBC驱动。那能不能让Python“借用”一下Java的JDBC驱动呢?这样一来,不就绕开了ODBC驱动的那些兼容性问题了吗?这个思路一打开,路子就宽了。 我最初尝试了`JayDeBeApi`这个库,它号称是Python里调用JDBC的桥梁。用了一下,基础功能是有的,但很快就遇到了新问题:当查询结果里包含`BLOB`(二进制大对象)这类特殊字段时,`JayDeBeApi`的类型转换会出问题,要么报错,要么返回一个无法直接处理的Java对象。好奇心驱使我去翻了翻它的源码,结果发现,它底层依赖的其实是另一个更基础的库——`JPype1`。`JayDeBeApi`相当于在`JPype1`之上封装了一层符合Python DB-API 2.0规范的接口。 既然底层都是`JPype1`,那我为什么不直接研究`JPype1`呢?说不定控制更精细,能解决的问题也更多。这一查,发现了个好消息:从`JPype1`的**1.1.1版本**开始,它原生内置了对Python DB-API 2.0规范的支持!这意味着,我们不再需要`JayDeBeApi`这个“中间商”,直接用`JPype1`就能以符合Python数据库编程习惯的方式(比如使用`connect`、`cursor`、`execute`)来操作JDBC了,代码会更简洁,对数据类型的掌控力也更强。 所以,如果你也在为Python连接某些数据库(特别是那些ODBC驱动不给力的小众或企业级数据库)而烦恼,或者需要利用某个只有JDBC驱动才提供的独家功能,那么`JPype1` + `JDBC`这条技术路线,绝对值得你花时间了解一下。它不是什么“屠龙之术”,而是一个能实实在在解决生产环境连接问题的实用方案。 ## 2. 手把手搭建你的开发环境 工欲善其事,必先利其器。用Python调JDBC,听起来有点“跨界”,但其实环境搭建并不复杂,核心就三样东西:合适的Java环境、正确版本的`JPype1`,以及你要连接的那个数据库的JDBC驱动JAR包。 ### 2.1 Java环境是基石 既然要调用JDBC,那Java运行环境(JRE)或者Java开发工具包(JDK)是必不可少的。我强烈推荐使用 **JDK 1.8(也就是Java 8)或更高版本**。Java 8是一个非常稳定且被广泛支持的长期支持版本,绝大多数JDBC驱动都能很好地兼容它。 安装好JDK后,**最关键的一步是设置`JAVA_HOME`环境变量**。这个变量告诉`JPype1`你的Java装在哪里。如果没设置,启动JVM时会报错。 - **在Windows上**:你可以在“系统属性” -> “高级” -> “环境变量”中,新建一个系统变量,变量名为`JAVA_HOME`,变量值是你的JDK安装路径,比如`C:\Program Files\Java\jdk1.8.0_301`。 - **在Linux/macOS上**:通常可以在你的shell配置文件(如`~/.bashrc`或`~/.zshrc`)里添加一行:`export JAVA_HOME=/usr/lib/jvm/java-8-openjdk`(具体路径请根据你的实际安装情况调整)。 设置完后,打开一个新的命令行终端,输入`echo $JAVA_HOME`(Linux/macOS)或在CMD里输入`echo %JAVA_HOME%`(Windows),如果能正确显示路径,就说明设置成功了。 ### 2.2 安装正确版本的JPype1 这是整个方案的核心Python库。前面我们提到了,必须使用 **1.1.1及以上版本**,因为它才内置了`dbapi2`模块,这是我们能像使用`sqlite3`或`pymysql`一样操作数据库的关键。 安装非常简单,直接用pip命令就行。我建议使用`>=`来指定最低版本,让pip自动安装最新的兼容版本,这样能获得最好的稳定性和功能支持。 ```bash pip install JPype1>=1.1.1 ``` 安装完成后,可以在Python交互环境里验证一下: ```python import jpype print(jpype.__version__) # 应该输出 1.1.1 或更高的版本号 ``` ### 2.3 准备你的“武器库”:JDBC驱动JAR包 这是连接特定数据库的钥匙。你需要从数据库的官方网站下载对应的JDBC驱动。通常是一个以`.jar`结尾的文件。 - **MySQL**:去MySQL官网下载`mysql-connector-java-x.x.xx.jar`。 - **Oracle**:去Oracle官网下载`ojdbcx.jar`(版本号如`ojdbc8.jar`对应Java 8)。 - **InterSystems IRIS/Cache**:从InterSystems的安装目录或官网获取,例如`intersystems-jdbc-3.1.0.jar`或更早的`cache-jdbc-2.0.0.jar`。 - **其他数据库(如PostgreSQL, SQL Server)**:同理,寻找其官方的JDBC驱动JAR包。 **一个小建议**:把这个JAR包放在你的项目目录里,或者一个固定的、好记的路径下。因为在代码里,我们需要指定这个JAR文件的路径来启动Java虚拟机(JVM)。 ## 3. 实战:从连接Cache数据库开始 理论说了不少,咱们直接上代码,看看怎么用`JPype1`连上那个让我一开始头疼的InterSystems Cache(及其新一代产品IRIS)数据库。这里会提供两个版本的示例,因为它的驱动有过变化,搞清楚区别能避免很多坑。 ### 3.1 连接InterSystems IRIS (新驱动) InterSystems把原来的Cache数据库升级整合成了IRIS数据平台。新版本对应的JDBC驱动包通常是`intersystems-jdbc-3.x.x.jar`。连接代码的结构非常清晰,我一步步拆开讲。 ```python #!/usr/bin/env python # -*- coding:utf-8 -*- try: # 1. 导入关键模块 import jpype.imports # 这个导入允许我们使用‘from java.xx import xx’的语法 from jpype import JInt, JShort # 用于处理Java的整数和短整数类型 from jpype import dbapi2 # 核心!DB-API 2.0接口 # 2. 启动Java虚拟机(JVM),并指定JDBC驱动JAR包路径 # 注意:classpath参数接受一个列表。路径是相对于你启动Python脚本的目录,不是脚本文件本身的位置。 # 比如你在 /home/user 目录下执行 python my_script.py,那么 classpath 里的路径就从 /home/user 开始找。 jpype.startJVM(classpath=['./drivers/intersystems-jdbc-3.1.0.jar']) # 3. 像导入Python模块一样导入Java类 # 这行代码之后,你就可以使用 com.intersystems.jdbc 包里的所有类了 from com.intersystems.jdbc import * # 4. 版本检查,确保JPype1版本符合要求 if jpype.__version__ < '1.1.0': raise EnvironmentError('jpype1 need version >=1.1.0, please check jpype1 version') except ImportError as e: # 如果导入失败,可能是JPype1没安装好 raise ImportError('Import jpype occurred an error: ', e) # 5. 构造JDBC连接字符串 # 这是JDBC连接的核心,格式是 `jdbc:子协议://主机:端口/数据库名?参数` # 对于IRIS,子协议是 `IRIS`。参数 `useUnicode=true&characterEncoding=UTF-8` 对解决中文乱码至关重要。 conn_url = "jdbc:IRIS://192.168.1.100:1972/MYDB?useUnicode=true&characterEncoding=UTF-8" # 6. 准备连接参数 # driver_args 是一个字典,里面放用户名、密码等认证信息 driver_args = {"user": "TEST_USER", "password": "MyPass123"} # 7. 建立数据库连接! # 使用 dbapi2.connect 方法,指定驱动类全名和参数 # 驱动类名可以在驱动文档里找到,对于IRIS新驱动是 `com.intersystems.jdbc.IRISDriver` conn = dbapi2.connect(conn_url, driver='com.intersystems.jdbc.IRISDriver', driver_args=driver_args) # 8. (可选但重要)自定义类型转换器 # Java的 Integer (JInt) 和 Short (JShort) 对象返回给Python时,默认可能是Java对象。 # 这里我们将其转换器设置为Python的 `str` 函数,让它们自动转成Python字符串。 # 你也可以定义更复杂的函数来处理,比如把特定的Java类型转成Python的datetime。 conn.converters[JInt] = str conn.converters[JShort] = str # 至此,连接已建立!后面的操作就和用pymysql、sqlite3一模一样了。 # 9. 创建游标,执行查询 cur = conn.cursor() # 使用参数化查询,防止SQL注入,也更清晰 sql_query = 'SELECT CODE, NAME FROM DEPARTMENT WHERE NAME = ?' cur.execute(sql_query, ("技术研发部",)) # 10. 获取结果 # fetchone() 取一条记录,fetchall() 取所有 row = cur.fetchone() print(f"查询结果(元组): {row}") # 输出类似:('D001', '技术研发部') # 11. 将结果转为字典(更易用) # cur.description 包含了字段的元信息,如字段名 if row and cur.description: # 提取字段名并转为大写(通常更规范) column_names = [col[0].upper() for col in cur.description] # 用zip将字段名和值配对,创建字典 row_dict = dict(zip(column_names, row)) print(f"查询结果(字典): {row_dict}") # 输出:{'CODE': 'D001', 'NAME': '技术研发部'} # 12. 别忘了关闭连接,释放资源 cur.close() conn.close() ``` **代码要点解析**: - **`jpype.imports`**:这个导入是魔法发生的关键,它启用了从Java包直接导入类的语法糖,让代码看起来更“Pythonic”。 - **`classpath`路径**:这是新手最容易出错的地方。`startJVM`中的`classpath`是相对于**你运行Python命令的当前工作目录**,而不是脚本文件所在的目录。我建议使用绝对路径,或者用`os.path`模块来构造相对路径,这样最稳妥。 - **连接字符串参数**:`useUnicode=true&characterEncoding=UTF-8` 这两个参数对于处理中文等非拉丁字符集几乎是必须的,能确保数据在传输和转换过程中编码正确。 - **类型转换器**:`conn.converters` 是一个字典,你可以为不同的Java类型注册Python转换函数。这是一个非常强大的功能,可以优雅地解决Java和Python类型系统之间的差异。 ### 3.2 连接旧版Cache数据库 如果你的环境还在使用更早的Cache数据库和对应的`cache-jdbc-2.0.0.jar`驱动,代码只有细微差别,主要体现在驱动类名和连接字符串的子协议上。 ```python # ... 前面的导入和JVM启动代码类似,但classpath指向旧版jar包 ... jpype.startJVM(classpath=['./drivers/cache-jdbc-2.0.0.jar']) from com.intersys.jdbc import * # 注意包名是 intersys,不是 intersystems # 连接字符串的子协议变成了 `Cache` conn_url = "jdbc:Cache://192.168.1.100:1972/MYDB?useUnicode=true&characterEncoding=UTF-8" driver_args = {"user": "TEST_USER", "password": "MyPass123"} # 驱动类名也变了 conn = dbapi2.connect(conn_url, driver='com.intersys.jdbc.CacheDriver', # 这里是 CacheDriver driver_args=driver_args) # ... 后续的查询、类型转换、关闭连接等操作完全一样 ... ``` **关键区别总结**: - **JAR包和包名**:旧驱动是`com.intersys`,新驱动是`com.intersystems`。导入时写错会报`ClassNotFound`错误。 - **驱动类**:旧的是`CacheDriver`,新的是`IRISDriver`。 - **连接子协议**:旧的是`jdbc:Cache://`,新的是`jdbc:IRIS://`。 ## 4. 举一反三:连接Oracle与MySQL 掌握了Cache/IRIS的连接方法,其他数据库就是“换汤不换药”了。核心步骤永远是:**找对JAR包、写对连接字符串、用对驱动类名**。下面我给出Oracle和MySQL的完整连接示例,你可以对比着看,理解其中的模式。 ### 4.1 连接Oracle数据库 Oracle的JDBC驱动(ojdbc)版本比较多,需要根据你的Java版本和Oracle数据库版本来选择。这里以常用的`ojdbc8.jar`为例。 ```python #!/usr/bin/env python # -*- coding:utf-8 -*- import jpype.imports from jpype import dbapi2 import os # 假设我们把 ojdbc8.jar 放在项目根目录的 libs 文件夹下 jar_path = os.path.join(os.path.dirname(__file__), 'libs', 'ojdbc8.jar') jpype.startJVM(classpath=[jar_path]) # 导入Oracle JDBC相关的Java类(非必须,但有时IDE需要) # from oracle.jdbc.driver import * # Oracle JDBC连接字符串 # 格式:jdbc:oracle:thin:@//主机:端口/服务名 # 也可以是:jdbc:oracle:thin:@主机:端口:实例名 (老格式) host = "10.10.10.5" port = "1521" service_name = "ORCLPDB" # 或者是SID conn_url = f"jdbc:oracle:thin:@//{host}:{port}/{service_name}" # 连接参数 driver_args = { "user": "scott", "password": "tiger" } # 建立连接 # Oracle的驱动类名是 `oracle.jdbc.OracleDriver` conn = dbapi2.connect(conn_url, driver='oracle.jdbc.OracleDriver', driver_args=driver_args) cur = conn.cursor() # 执行一个简单的查询 cur.execute("SELECT EMPNO, ENAME, JOB FROM EMP WHERE DEPTNO = :1", (20,)) # 获取所有结果 rows = cur.fetchall() for empno, ename, job in rows: print(f"员工号: {empno}, 姓名: {ename}, 职位: {job}") # 关闭连接 cur.close() conn.close() ``` **Oracle连接注意事项**: - **驱动版本**:`ojdbc8.jar` 适用于Java 8及更高版本,连接Oracle 11g、12c、19c等主流版本。如果Java版本是11+,也可以考虑`ojdbc10.jar`或`ojdbc11.jar`。 - **服务名 vs SID**:现代Oracle数据库多使用“服务名”(Service Name),连接字符串格式如示例所示。如果是老式的“系统标识符”(SID),格式可能是`jdbc:oracle:thin:@host:port:SID`。 - **`useUnicode`参数**:对于Oracle,如果遇到中文乱码,通常需要确保数据库服务器字符集、客户端NLS_LANG环境变量和Python代码的编码一致,JDBC连接字符串本身相关参数较少。 ### 4.2 连接MySQL数据库 MySQL的JDBC驱动(Connector/J)是下载和使用最方便的之一。 ```python #!/usr/bin/env python # -*- coding:utf-8 -*- import jpype.imports from jpype import dbapi2 import os # 加载MySQL驱动jar包 jar_path = os.path.join(os.path.dirname(__file__), 'drivers', 'mysql-connector-java-8.0.33.jar') jpype.startJVM(classpath=[jar_path]) # MySQL JDBC连接字符串 # 格式:jdbc:mysql://主机:端口/数据库名?参数1=值1&参数2=值2 host = "localhost" port = "3306" database = "testdb" conn_url = f"jdbc:mysql://{host}:{port}/{database}?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai" # 连接参数 driver_args = { "user": "root", "password": "your_password" } # 建立连接 # MySQL的驱动类名是 `com.mysql.cj.jdbc.Driver` (8.0版本) # 如果是老版本(5.x),可能是 `com.mysql.jdbc.Driver` conn = dbapi2.connect(conn_url, driver='com.mysql.cj.jdbc.Driver', driver_args=driver_args) cur = conn.cursor() # 执行查询 cur.execute("SELECT id, username, email FROM users WHERE active = %s", (True,)) # 遍历结果 for user_id, username, email in cur.fetchall(): print(f"ID: {user_id}, 用户名: {username}, 邮箱: {email}") # 插入数据的例子 insert_sql = "INSERT INTO logs (message, level) VALUES (%s, %s)" cur.execute(insert_sql, ("系统启动完成", "INFO")) conn.commit() # 记住要提交事务! print(f"插入成功,影响行数: {cur.rowcount}") cur.close() conn.close() ``` **MySQL连接关键点**: - **驱动类名**:MySQL Connector/J 8.0及以上版本使用`com.mysql.cj.jdbc.Driver`。5.x版本使用`com.mysql.jdbc.Driver`。用错了会报错。 - **连接参数**: - `useUnicode=true&characterEncoding=utf8`:确保正确处理中文。 - `serverTimezone=Asia/Shanghai`:**非常重要!** 如果不设置,在处理数据库的`DATETIME`或`TIMESTAMP`字段时,可能会遇到时区转换错误或时间不对的问题。请根据你的服务器所在地设置正确的时区。 - **参数化查询**:MySQL使用`%s`作为占位符,而不是`?`。这是Python DB-API规范中一个常见的数据库差异点。 ## 5. 进阶技巧与避坑指南 当你成功连接并执行了基本查询后,可能会遇到一些更复杂的情况。下面这些技巧是我在实际项目中踩过坑后总结出来的,能帮你走得更稳。 ### 5.1 处理复杂数据类型与自定义转换 JDBC驱动返回的数据类型是Java类型。`JPype1`的`dbapi2`模块会尝试进行一些基础转换,但遇到`BLOB`、`CLOB`、`TIMESTAMP WITH TIME ZONE`或者自定义的Java对象时,可能就需要我们手动干预了。 假设我们有一个表,其中包含一个`BLOB`类型的头像图片字段。 ```python from jpype import JByte, JArray, JClass import io # ... 连接数据库的代码 ... # 假设我们想读取用户ID为1的头像(BLOB字段) cur.execute("SELECT avatar FROM user_profile WHERE user_id = ?", (1,)) row = cur.fetchone() if row: avatar_blob = row[0] # 此时avatar_blob是一个Java的byte[]数组对象 # 方法1:使用JPype工具转换为Python bytes if avatar_blob: # 将Java的byte[]转换为Python的bytes python_bytes = bytes(avatar_blob) # 或者使用 jpype.JArray(JByte)(avatar_blob) 进行转换 # 现在你可以用PIL(Pillow)等库打开这个图片了 # from PIL import Image # image = Image.open(io.BytesIO(python_bytes)) print(f"成功读取BLOB,长度:{len(python_bytes)} 字节") # 更通用的方法是注册一个自定义转换器 def handle_blob(java_blob_obj): """将Java byte[]对象转换为Python bytes""" if java_blob_obj is None: return None # 获取java.sql.Blob对象的内容 # 注意:这里假设驱动返回的是byte[],有些驱动可能直接返回java.sql.Blob对象 # 如果是java.sql.Blob,需要调用其 getBytes(1, int(blob.length())) 方法 if hasattr(java_blob_obj, '__java_name__') and 'byte[' in java_blob_obj.__java_name__: return bytes(java_blob_obj) else: # 处理其他可能的Blob类型 return None # 假设我们通过某种方式知道了某个列返回的Java类型是 byte[] ByteArrayClass = JClass("byte[]") conn.converters[ByteArrayClass] = handle_blob ``` **自定义转换器的核心思路**:`conn.converters`是一个映射字典,键是Java的类(或`jpype`类型,如`JInt`),值是一个Python可调用对象(函数)。当从结果集中读取数据时,如果遇到匹配的Java类型,就会调用你注册的函数进行转换,返回值将作为Python端的结果。 ### 5.2 管理JVM生命周期与资源 `jpype.startJVM()`启动的是一个真正的Java虚拟机。它比较“重”,通常一个Python进程只需要启动一次。 - **不要重复启动JVM**:在同一个Python进程中多次调用`startJVM()`会报错。最佳实践是在程序入口(如主函数开头)启动一次,然后在整个程序生命周期内使用它。 - **关闭JVM**:虽然Python程序退出时会自动清理,但显式关闭是个好习惯,尤其是在长时间运行的后台脚本或Web应用中。使用`jpype.shutdownJVM()`来关闭。 - **内存与性能**:JVM本身会占用一定内存。如果你的Python程序只是偶尔操作数据库,频繁启动/关闭JVM开销会很大。可以考虑将数据库操作封装成一个常驻服务,或者使用连接池来复用连接和JVM环境。 ### 5.3 连接池与多线程考量 在生产环境中,为每个请求都新建一个数据库连接是非常低效的。虽然`JPype1` + `JDBC`本身不直接提供连接池,但我们可以利用Java生态中成熟的连接池库,比如**HikariCP**或**Apache DBCP**。 思路是:在JVM中初始化一个Java侧的连接池对象,然后Python代码每次从这个池子里“借”连接来用。 ```python import jpype.imports from jpype import JClass, JString # 启动JVM,需要加载连接池和数据库驱动两个JAR jpype.startJVM(classpath=[ './libs/hikaricp-4.0.3.jar', './libs/mysql-connector-java-8.0.33.jar' ]) # 导入Java类 HikariConfig = JClass('com.zaxxer.hikari.HikariConfig') HikariDataSource = JClass('com.zaxxer.hikari.HikariDataSource') # 配置连接池 config = HikariConfig() config.setJdbcUrl("jdbc:mysql://localhost:3306/testdb?useUnicode=true&characterEncoding=utf8") config.setUsername("root") config.setPassword("your_password") config.setMaximumPoolSize(10) # 最大连接数 config.setMinimumIdle(5) # 最小空闲连接 # 创建数据源 data_source = HikariDataSource(config) # 现在,我们可以从数据源获取连接,但注意获取到的是Java的Connection对象 # 需要将其“包装”成dbapi2的连接对象(如果dbapi2支持的话,或者直接使用Java方式操作) # 一个更直接的方式是:在Python端维护一个简单的连接队列(非生产级),或者直接使用Java Connection对象。 # 对于复杂场景,可能需要更深入的jpype交互。 # 示例:直接使用Java Connection(非dbapi2风格) try: java_conn = data_source.getConnection() java_stmt = java_conn.createStatement() java_rs = java_stmt.executeQuery("SELECT 1") if java_rs.next(): print(f"查询结果: {java_rs.getInt(1)}") java_rs.close() java_stmt.close() finally: if java_conn: java_conn.close() # 这里close()实际是将连接归还给池 # 程序结束时关闭数据源(从而关闭整个连接池) data_source.close() ``` 这种方式更进阶,需要对Java和`JPype1`的交互有更深的理解。对于大多数Python项目,如果只是需要连接池,使用纯Python的数据库库(如`aiomysql`、`asyncpg`配合异步框架,或`SQLAlchemy`的池化功能)连接主流数据库可能是更简单的选择。但对于必须通过JDBC连接的数据库,上述Java侧连接池方案是可行的生产级路径。 ### 5.4 常见错误与排查方法 1. **`ClassNotFoundException` 或 `NoClassDefFoundError`**: - **原因**:JVM在`classpath`中找不到指定的类。 - **排查**: - 检查`startJVM(classpath=[...])`中的JAR包路径是否正确、绝对。 - 检查驱动类名是否拼写正确,比如`com.mysql.cj.jdbc.Driver` vs `com.mysql.jdbc.Driver`。 - 确认JAR包版本与数据库版本兼容。 2. **`SQLException: No suitable driver found`**: - **原因**:连接字符串的URL格式不对,或者驱动类没有正确加载(虽然JAR包在classpath里,但有些旧驱动需要显式调用`Class.forName`)。 - **排查**: - 检查连接字符串的`jdbc:子协议://`部分是否正确。每个数据库的“子协议”不同(`mysql`、`oracle:thin`、`IRIS`等)。 - 对于极少数老驱动,可能需要在Python中手动加载一下驱动类:`JClass('com.xxx.xxxDriver')`,然后再调用`dbapi2.connect`。 3. **中文乱码问题**: - **原因**:数据在传输、转换过程中编码不一致。 - **解决**: - **确保连接字符串包含编码参数**:如MySQL的`characterEncoding=utf8`,Oracle的`useUnicode=true`等。 - **检查数据库、表、字段的字符集**:确保它们都是`UTF-8`或`GBK`等与你程序匹配的编码。 - **统一Python文件编码**:在脚本开头使用`# -*- coding:utf-8 -*-`。 4. **性能问题**: - **现象**:查询速度慢,尤其是批量操作。 - **优化**: - 使用**参数化查询**(`cursor.execute(sql, params)`),不要拼接SQL字符串,这既能防注入也能利用数据库的查询缓存。 - 对于批量插入,考虑使用`cursor.executemany()`(如果驱动支持)。 - 查询时只选取需要的列,避免`SELECT *`。 - 合理使用事务。 这条路子虽然看起来比直接使用`pymysql`或`cx_Oracle`绕了一点,但它为你打开了一扇门,让你能用Python几乎无限制地访问任何提供了JDBC驱动的数据源。当你下一次遇到一个冷门数据库,或者需要用到某个只有JDBC驱动才支持的高级功能时,希望这篇文章和这些代码能成为你工具箱里一件趁手的武器。

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

Python内容推荐

python 利用 jpype 调用java代码

python 利用 jpype 调用java代码

Python是一种强大的脚本语言,广泛应用于数据处理、...`test1`可能是一个测试脚本,而`mython`可能是一个包含Python代码的模块,演示如何使用`jpype`调用Java代码。你可以查看这些文件以获取更具体的例子和实现细节。

Python通过JDBC连接数据库[源码]

Python通过JDBC连接数据库[源码]

JPype1是一个开源库,使得Python程序可以调用JVM(Java虚拟机)上的Java代码,从而可以使用JDBC来连接数据库。 在处理数据库连接问题时,作者首先尝试了使用pyodbc通过ODBC驱动来连接数据库。ODBC(Open Database ...

Python库 | JPype1-1.2.0-cp37-cp37m-manylinux1_x86_64.whl

Python库 | JPype1-1.2.0-cp37-cp37m-manylinux1_x86_64.whl

这意味着Python程序员可以通过JPype1调用Java类库,使用Java的功能,如处理大规模数据、利用现有的Java企业级框架等。这在需要跨平台兼容性或者希望利用Java生态系统的丰富资源时非常有用。 在实际应用中,例如,...

jpype1for python3.6

jpype1for python3.6

主要用于手动安装python3.6.1对应的jpype1 库。使用pip install wheel 安装wheel成功后,再次安装该文件 pip install ****.whl 即可。

python/jpype资料大全

python/jpype资料大全

Python和JPype是两个在IT领域中非常重要的技术。Python是一种高级编程语言,以其简洁的语法和强大的功能受到广大...通过深入学习这些内容,不仅可以掌握Python编程,还能熟练运用JPype实现Python和Java的高效协作。

Python3通过连接池高效调用MySQL数据库实现多线程并发访问与连接复用管理工具_连接池管理数据库连接复用多线程并发控制MySQL数据库操作Python3编程性能优化.zip

Python3通过连接池高效调用MySQL数据库实现多线程并发访问与连接复用管理工具_连接池管理数据库连接复用多线程并发控制MySQL数据库操作Python3编程性能优化.zip

本文将详细介绍如何利用Python3编程语言高效地调用MySQL数据库,并通过连接池技术实现多线程并发访问以及数据库连接的复用管理,从而提高数据库操作的性能。 首先,需要了解连接池的概念。连接池是一种通过预先建立...

Jpype1 64位 python3.6

Jpype1 64位 python3.6

《Jpype1 64位 Python3.6:连接Python与Java的桥梁》 在IT行业中,Python作为一门强大的脚本语言,被广泛应用于数据分析、机器学习、网络编程等领域。而Java则以其跨平台性及企业级应用的广泛支持而闻名。有时候,...

python实现连接数据库账号注册和登录

python实现连接数据库账号注册和登录

1. Python数据库连接:使用Python数据库接口库连接和操作数据库。 2. 用户注册和登录:处理用户信息的增删改查,尤其是密码的安全存储。 3. 哈希算法:用于密码的加密存储,提供不可逆的密码验证方式。 4. 网络编程...

python 连接达梦数据库

python 连接达梦数据库

Python 连接达梦数据库 Python 连接达梦数据库是指在 Python 编程语言中连接达梦数据库,以便在 Python 应用程序中使用达梦数据库。下面是 Python 连接达梦数据库的详细步骤和知识点: 检查 Python 是否安装 在...

Python 使用Pandas实现数据库的读、写操作 Python源码

Python 使用Pandas实现数据库的读、写操作 Python源码

Python 使用Pandas实现数据库的读、写操作 Python源码Python 使用Pandas实现数据库的读、写操作 Python源码Python 使用Pandas实现数据库的读、写操作 Python源码Python 使用Pandas实现数据库的读、写操作 Python源码...

Python连接Access数据库

Python连接Access数据库

### Python连接Access数据库:深入解析与实践指南 在IT领域,数据管理是核心任务之一,而使用编程语言如Python操作数据库则成为了一项必备技能。本文将深入探讨如何使用Python连接并操作Microsoft Access数据库,这...

python 通过数据库连接池访问数据库

python 通过数据库连接池访问数据库

python 通过数据库连接池访问数据库工具,支持可配置数据连接池大小,并发连接数配置

服务器python通过JDBC连接到位于Linux远程服务器上的Oracle数据库

服务器python通过JDBC连接到位于Linux远程服务器上的Oracle数据库

【服务器】python通过JDBC连接到位于Linux远程服务器上的Oracle数据库 参考:https://blog.csdn.net/WTYuong/article/details/138167739

Python操作数据库和实现mysql数据库连接池

Python操作数据库和实现mysql数据库连接池

在本主题中,我们将深入探讨如何使用Python操作MySQL数据库以及如何实现数据库连接池。 首先,Python中常用的数据库操作库是`pymysql`和`mysql-connector-python`,它们提供了对MySQL数据库的接口。`pymysql`是...

Python的Flask框架与数据库连接的教程

Python的Flask框架与数据库连接的教程

在数据库模型部分,我们学习了如何定义数据库模型,这是通过创建Python类并将它们映射到数据库表中来实现的。在模型中,每个属性都可以映射到一个数据库字段,并且可以指定字段类型和大小等属性。模型中的id字段通常...

Python操作三大主流数据库 实战网易新闻客户端视频教程2022

Python操作三大主流数据库 实战网易新闻客户端视频教程2022

在本教程“Python操作三大主流数据库 实战网易新闻客户端”中,我们将深入学习如何使用Python语言与MySQL、PostgreSQL和SQLite这三大主流数据库进行交互,从而实现类似网易新闻客户端的数据管理功能。通过这个实战...

Python操作数据库及Python实现mysql数据库连接池源代码

Python操作数据库及Python实现mysql数据库连接池源代码

Python操作数据库及Python实现mysql数据库连接池源代码。python编程中可以使用MySQLdb进行数据库的连接及诸如查询/插入/更新等操作,但是每次连接mysql数据库请求时,都是独立的去请求访问,相当浪费资源,而且访问...

Python数据库连接池实现:深入指南与代码示例

Python数据库连接池实现:深入指南与代码示例

在Python中,我们可以通过使用第三方库,比如DBUtils,或者手动实现连接池来构建这种高效的数据库连接管理机制。本文将详细介绍连接池的基本原理、使用第三方库和手动实现的具体方法,并提供代码示例,帮助读者在...

达梦数据库python 操作手册

达梦数据库python 操作手册

近年来,随着Python编程语言的广泛应用,越来越多的开发者开始探索如何利用Python脚本来操作达梦数据库,以实现高效的数据处理和管理。dmPython库的诞生,正是为了满足这一需求。 dmPython库是一个专门为Python开发...

python连接firebird数据库方法

python连接firebird数据库方法

### Python连接Firebird数据库方法详解 #### 一、前言 在现代软件开发过程中,数据库技术扮演着极其重要的角色。Python作为一种广泛使用的编程语言,在处理数据方面提供了强大的支持。Firebird是一款高性能的关系...

最新推荐最新推荐

recommend-type

Python调用C# Com dll组件实战教程

总结来说,当需要在Python中使用C#特有的功能时,可以通过创建C# COM组件并在Python中调用的方式来实现跨语言交互。这种方法相比于直接使用IronPython,可能需要更多的步骤,但它允许你充分利用C#的特性,并在Python...
recommend-type

Python连接Impala实现步骤解析

首先,要实现Python连接到Impala,我们需要一个名为`impyla`的库,它是Python与HiveServer2(包括Impala和Hive)交互的客户端。安装`impyla`库可以通过Python的包管理器`pip`来完成: ```bash pip install impyla `...
recommend-type

Python操作mysql数据库实现增删查改功能的方法

本篇文章将详细讲解如何使用Python实现对MySQL数据库的增删查改(CRUD)操作。 首先,我们需要导入Python中的MySQL数据库连接库`MySQLdb`。`MySQLdb`是Python的一个MySQL接口,它允许我们通过Python代码连接到MySQL...
recommend-type

python调用系统ffmpeg实现视频截图、http发送

标题中的“python调用系统ffmpeg实现视频截图、http发送”是指使用Python编程语言结合系统级调用ffmpeg工具来实现从视频中抓取帧并转换为图片,然后将这些图片通过HTTP协议发送到指定的服务器。这通常用于视频处理、...
recommend-type

python实现多层感知器MLP(基于双月数据集)

在本教程中,我们将深入探讨如何使用Python实现一个多层感知器(MLP,Multilayer Perceptron)神经网络,特别是在处理双月数据集时。多层感知器是一种前馈神经网络,它允许非线性建模,适用于解决复杂的分类和回归...
recommend-type

学生成绩管理系统C++课程设计与实践

资源摘要信息:"学生成绩信息管理系统-C++(1).doc" 1. 系统需求分析与设计 在进行学生成绩信息管理系统开发前,首先需要进行系统需求分析,这是确定系统开发目标与范围的过程。需求分析应包括数据需求和功能需求两个方面。 - 数据需求分析: - 学生成绩信息:需要收集学生的姓名、学号、课程成绩等数据。 - 数据类型和长度:明确每个数据项的数据类型(如字符串、整型等)和长度,例如学号可能是字符串类型且长度为一定值。 - 描述:详细描述每个数据项的意义,以确保系统能够准确处理。 - 功能需求分析: - 列出功能列表:用户界面应提供清晰的操作指引,列出所有可用功能。 - 查询学生成绩:系统应能通过学号或姓名查询学生的成绩信息。 - 增加学生成绩信息:允许用户添加未保存的学生成绩信息。 - 删除学生成绩信息:能够通过学号或姓名删除已经保存的成绩信息。 - 修改学生成绩信息:通过学号或姓名修改已有的成绩记录。 - 退出程序:提供安全退出程序的选项,并确保所有修改都已保存。 2. 系统设计 系统设计阶段主要完成内存数据结构设计、数据文件设计、代码设计、输入输出设计、用户界面设计和处理过程设计。 - 内存数据结构设计: - 使用链表结构组织内存中的数据,便于动态增删查改操作。 - 数据文件设计: - 选择文本文件存储数据,便于查看和编辑。 - 代码设计: - 根据功能需求,编写相应的函数和模块。 - 输入输出设计: - 设计简洁明了的输入输出提示信息和操作流程。 - 用户界面设计: - 用户界面应为字符界面,方便在命令行环境下使用。 - 处理过程设计: - 设计数据处理流程,确保每个操作都有明确的处理逻辑。 3. 系统实现与测试 实现阶段需要根据设计阶段的成果编写程序代码,并进行系统测试。 - 程序编写: - 完成系统设计中所有功能的程序代码编写。 - 系统测试: - 设计测试用例,通过测试用例上机测试系统。 - 记录测试方法和测试结果,确保系统稳定可靠。 4. 设计报告撰写 最后,根据系统开发的各个阶段,撰写详细的设计报告。 - 系统描述:包括问题说明、数据需求和功能需求。 - 系统设计:详细记录内存数据结构设计、数据文件设计、代码设计、输入/输出设计、用户界面设计、处理过程设计。 - 系统测试:包括测试用例描述、测试方法和测试结果。 - 设计特点、不足、收获和体会:反思整个开发过程,总结经验和教训。 时间安排: - 第19周(7月12日至7月16日)完成项目。 - 7月9日8:00到计算机学院实验中心(三楼)提交程序和课程设计报告。 指导教师和系主任(或责任教师)需要在文档上签名确认。 系统需求分析: - 使用表格记录系统需求分析的结果,包括数据项、数据类型、数据长度和描述。 - 分析数据项如学生成绩信息、状态器、链表节点等,确定其属性和行为。 以上就是文档中提到的学生成绩信息管理系统开发的关键知识点。开发此类系统需要熟练掌握C++编程基础,了解面向对象的程序设计思想,以及熟悉文件操作和链表等数据结构的应用。此外,良好的软件开发流程意识、测试意识和文档撰写能力也是必不可少的。
recommend-type

别再手动拖拽了!用Lumerical脚本批量创建FDTD仿真结构(附完整代码)

# 告别低效建模:Lumerical脚本自动化实战指南 在光子学仿真领域,时间就是科研生命线。当同行还在GUI界面里反复点击菜单时,你已经用脚本批量生成了20组参数化结构——这不是未来场景,而是每位FDTD用户都应该掌握的基础生产力革命。本文将彻底改变你与Lumerical的交互方式,从手动拖拽的农耕时代,跃迁到自动化建模的工业文明。 ## 1. 为何脚本建模是必然选择 2019年Nature Photonics的一项研究显示,科研工作者在仿真工具上平均浪费37%的时间在重复性操作上。对于需要参数扫描的纳米光学结构设计,这个数字可能更高。手动创建10个不同尺寸的纳米柱阵列意味着: -
recommend-type

Java邮件解析任务中,如何安全高效地提取HTML邮件内容并避免硬编码、资源泄漏和类型转换异常?

<think>我们被要求优化一段Java代码,该代码用于处理邮件(特别是来自特定发件人的构建通知邮件)。代码的主要问题包括: 1. 重复获取邮件内容:在检查MIME类型后,多次调用`msg[i].getContent()`,这可能导致性能问题或流关闭异常。 2. 类型转换问题:直接将邮件内容转换为`Multipart`而不进行类型检查,可能引发`ClassCastException`。 3. 代码结构问题:逻辑嵌套过深,可读性差,且存在重复代码(如插入邮件详情的操作在两个地方都有)。 4. 硬编码和魔法值:例如在解析HTML表格时使用了硬编码的索引(如list3.get(10)),这容易因邮件
recommend-type

RH公司应收账款管理优化策略研究

资源摘要信息:"本文针对RH公司的应收账款管理问题进行了深入研究,并提出了改进策略。文章首先分析了应收账款在企业管理中的重要性,指出其对于提高企业竞争力、扩大销售和充分利用生产能力的作用。然后,以RH公司为例,探讨了公司应收账款管理的现状,并识别出合同管理、客户信用调查等方面的不足。在此基础上,文章提出了一系列改善措施,包括完善信用政策、改进业务流程、加强信用调查和提高账款回收力度。特别强调了建立专门的应收账款回收部门和流程的重要性,并建议在实际应用过程中进行持续优化。同时,文章也意识到企业面临复杂多变的内外部环境,因此提出的策略需要根据具体情况调整和优化。 针对财务管理领域的专业学生和从业者,本文提供了一个关于应收账款管理问题的案例研究,具有实际指导意义。文章还探讨了信用管理和征信体系在应收账款管理中的作用,强调了它们对于提升企业信用风险控制和市场竞争能力的重要性。通过对比国内外企业在应收账款管理上的差异,文章总结了适合中国企业实际环境的应收账款管理方法和策略。" 根据提供的文件内容,以下是详细的知识点: 1. 应收账款管理的重要性:应收账款作为企业的一项重要资产,其有效管理关系到企业的现金流、财务健康以及市场竞争力。不良的应收账款管理会导致资金链断裂、坏账损失增加等问题,严重影响企业的正常运营和长远发展。 2. 应收账款的信用风险:在信用交易日益频繁的商业环境中,企业必须对客户信用进行评估,以便采取合理的信用政策,降低信用风险。 3. 合同管理的薄弱环节:合同是应收账款管理的法律基础,严格的合同管理能够保障企业权益,减少因合同问题导致的应收账款风险。 4. 客户信用调查:了解客户的信用状况对于预测和控制应收账款风险至关重要。企业需要建立有效的客户信用调查机制,识别和筛选信用良好的客户。 5. 应收账款回收策略:企业应建立有效的账款回收机制,包括定期的账款跟进、逾期账款的催收等。同时,建立专门的应收账款回收部门可以提升回收效率。 6. 应收账款管理流程优化:通过改进企业内部管理流程,如简化审批流程、提高工作效率等措施,能够提升应收账款的管理效率。 7. 应收账款管理策略的调整和优化:由于企业的内外部环境复杂多变,因此制定的管理策略需要根据实际情况进行动态调整和持续优化。 8. 信用管理和征信体系的作用:建立和完善企业内部信用管理体系和征信体系,有助于企业更好地控制信用风险,并在市场竞争中占据有利地位。 9. 对比国内外应收账款管理实践:通过研究国内外企业在应收账款管理上的不同做法和经验,可以借鉴先进的管理理念和方法,提升国内企业的应收账款管理水平。 综上所述,本文深入探讨了应收账款管理的多个方面,为RH公司乃至其他同类型企业提供了应收账款管理的改进方向和策略,对于财务管理专业的教育和实践都具有重要的参考价值。
recommend-type

新手别慌!用BingPi-M2开发板带你5分钟搞懂Tina Linux SDK目录结构

# 新手别慌!用BingPi-M2开发板带你5分钟搞懂Tina Linux SDK目录结构 第一次拿到BingPi-M2开发板时,面对Tina Linux SDK里密密麻麻的文件夹,我完全不知道从哪下手。就像走进一个陌生的大仓库,每个货架上都堆满了工具和零件,却找不到操作手册。这种困惑持续了整整两天,直到我意识到——理解目录结构比死记硬背每个文件更重要。 ## 1. 为什么SDK目录结构如此重要 想象你正在组装一台复杂的模型飞机。如果所有零件都混在一个箱子里,你需要花大量时间寻找每个螺丝和面板。但如果有分门别类的隔层,标注着"机身部件"、"电子设备"、"紧固件",组装效率会成倍提升。Ti