파이썬 네이티브 드라이버가 없거나, 접속 제어 게이트웨이가 JDBC 만 허용하는 경우가 있다. JayDeBeApi 는 JPype 로 JVM 을 띄워 JDBC 드라이버를 그대로 호출하고 DB-API 2.0 인터페이스로 감싼다.
네이티브 드라이버가 있으면 그쪽이 낫다. JVM 기동 비용과 타입 변환 문제를 피할 수 있다. PostgreSQL 은 psycopg, Oracle 은 python-oracledb, MySQL 은 mysqlclient 를 먼저 검토한다.
pip install JayDeBeApi JPype1
JDK 가 필요하다. JRE 만으로는 JPype 가 동작하지 않는 경우가 있다.
dnf install -y java-17-openjdk-devel
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk
import os
import jaydebeapi
jar = "/opt/jdbc/postgresql-42.7.9.jar"
conn = jaydebeapi.connect(
"org.postgresql.Driver",
"jdbc:postgresql://gateway.example.com:5432/appdb",
{"user": "appuser", "password": os.environ["DB_PASSWORD"]},
jar,
)
cur = conn.cursor()
cur.execute("SELECT id, name FROM app.users WHERE id = ?", (1001,))
for row in cur.fetchall():
print(row)
cur.close()
conn.close()
세 번째 인자는 리스트([user, password])로도 되고 딕셔너리로도 된다. 드라이버가 추가 속성을 요구하면 딕셔너리로 넣는 편이 명확하다.
jar 가 여럿이면 리스트로 준다. 의존 jar 가 빠지면 ClassNotFoundException 이 난다.
jars = ["/opt/jdbc/ojdbc11.jar", "/opt/jdbc/orai18n.jar"]
QueryPie 같은 DB 접근 제어 게이트웨이는 클라이언트 입장에서는 그냥 다른 호스트·포트의 DB 다. URL 의 호스트를 게이트웨이로 바꾸고 계정은 게이트웨이가 발급한 것을 쓰면 된다.
url = "jdbc:mysql://querypie.example.com:40000/appdb"
MySQL JDBC URL 에 useProxy=true&proxyHost=... 같은 속성은 존재하지 않는다. 인터넷 예시에 보이더라도 그대로 쓰면 Unsupported connection property 로 실패한다. 실제로 필요한 것은 게이트웨이가 요구하는 접속 정보와, 대개 TLS 관련 속성이다.
url = "jdbc:mysql://querypie.example.com:40000/appdb?useSSL=true&requireSSL=true"
JVM 에 자바 표준 프록시를 걸어야 하는 상황이라면 JPype 시작 시 시스템 속성으로 준다. 이것은 HTTP 프록시용이고 JDBC 의 TCP 접속에는 대개 적용되지 않는다.
import jpype
jpype.startJVM(classpath=jars, *["-Dhttps.proxyHost=proxy.example.com", "-Dhttps.proxyPort=3128"])
한 프로세스에서 JVM 은 한 번만 뜨고 다시 띄울 수 없다. 접속을 여러 번 만들더라도 클래스패스는 처음 한 번에 모두 넘겨야 한다.
멀티스레드에서 쓰려면 각 스레드에서 jpype.attachThreadToJVM() 을 호출해야 한다. 하지 않으면 조용히 죽는다.
반환 타입이 자바 객체 그대로인 경우가 있다. Decimal · Date · Clob 은 파이썬 타입으로 자동 변환되지 않을 수 있으므로 확인하고 필요하면 변환 함수를 등록한다.
import jaydebeapi
jaydebeapi._DEFAULT_CONVERTERS.update({"BIGINT": int})
대량 조회는 느리다. 행마다 JNI 경계를 넘기 때문이다. cur.arraysize 를 키우고, 그래도 부족하면 DB 쪽에서 파일로 내보내 옮기는 방법을 고려한다.
pip download -d ./wheels JayDeBeApi JPype1
# 같은 파이썬 버전·플랫폼의 서버로 옮긴 뒤
pip install --no-index --find-links=./wheels JayDeBeApi JPype1
pip download 는 내려받는 장비의 파이썬 버전과 플랫폼 기준으로 휠을 고른다. JPype1 은 C 확장이 있으므로 대상 서버와 환경이 다르면 맞지 않는 휠을 받는다. --platform · --python-version · --only-binary=:all: 을 명시하거나 대상과 같은 환경에서 받는다.