diff --git a/dj_db_conn_pool/backends/jdbc/__init__.py b/dj_db_conn_pool/backends/jdbc/__init__.py index 68ffccc..8b13789 100644 --- a/dj_db_conn_pool/backends/jdbc/__init__.py +++ b/dj_db_conn_pool/backends/jdbc/__init__.py @@ -1,72 +1 @@ -import logging -import threading -import jpype -import jpype.dbapi2 - -from dj_db_conn_pool.backends.jdbc.utils import CursorWrapper -from dj_db_conn_pool.core.mixins import PersistentDatabaseWrapperMixin - -logger = logging.getLogger(__name__) - -jdbc_type_converters = {} - -lock_check_jvm_status = threading.Lock() - - -class JDBCDatabaseWrapperMixin(PersistentDatabaseWrapperMixin): - Database = jpype.dbapi2 - - @property - def jdbc_driver(self): - raise NotImplementedError() - - @property - def jdbc_url_prefix(self): - raise NotImplementedError() - - @property - def jdbc_url(self): - return '{prefix}//{HOST}:{PORT}/{NAME}'.format( - prefix=self.jdbc_url_prefix, - **self.settings_dict - ) - - def create_cursor(self, name=None): - cursor = self.connection.cursor() - return CursorWrapper(cursor) - - def get_connection_params(self): - return self.settings_dict.get('OPTIONS', {}) - - def _get_new_connection(self, conn_params): - with lock_check_jvm_status: - if not jpype.isJVMStarted(): - jpype.startJVM(ignoreUnrecognized=True) - - conn = jpype.dbapi2.connect( - self.jdbc_url, - driver=self.jdbc_driver, - driver_args=dict( - user=self.settings_dict['USER'], - password=self.settings_dict['PASSWORD'], - **conn_params - ), - converters=jdbc_type_converters, - ) - - return conn - - def _close(self): - if self.connection is not None and self.connection.driver_connection.autocommit: - # if jdbc connection's autoCommit is on - # jpype will throw NotSupportedError after rollback called - # we make a little dynamic patch here, make sure - # SQLAlchemy will not do rollback before recycling connection - self.connection._pool._reset_on_return = None - - logger.debug( - "autoCommit of current JDBC connection to %s %s is on, won't do rollback before returning", - self.alias, self.connection.driver_connection) - - return super()._close() diff --git a/dj_db_conn_pool/backends/jdbc/mixins.py b/dj_db_conn_pool/backends/jdbc/mixins.py index 316534c..b58eb4c 100644 --- a/dj_db_conn_pool/backends/jdbc/mixins.py +++ b/dj_db_conn_pool/backends/jdbc/mixins.py @@ -1,5 +1,18 @@ +import logging +import threading + +import jpype import jpype.dbapi2 +from dj_db_conn_pool.backends.jdbc.utils import CursorWrapper +from dj_db_conn_pool.core.mixins import PersistentDatabaseWrapperMixin + +logger = logging.getLogger(__name__) + +jdbc_type_converters = {} + +lock_check_jvm_status = threading.Lock() + class JdbcDialectMixin: def do_ping(self, dbapi_connection): @@ -7,3 +20,61 @@ def do_ping(self, dbapi_connection): return super().do_ping(dbapi_connection) except jpype.dbapi2.DatabaseError: return False + + +class JDBCDatabaseWrapperMixin(PersistentDatabaseWrapperMixin): + Database = jpype.dbapi2 + + @property + def jdbc_driver(self): + raise NotImplementedError() + + @property + def jdbc_url_prefix(self): + raise NotImplementedError() + + @property + def jdbc_url(self): + return '{prefix}//{HOST}:{PORT}/{NAME}'.format( + prefix=self.jdbc_url_prefix, + **self.settings_dict + ) + + def create_cursor(self, name=None): + cursor = self.connection.cursor() + return CursorWrapper(cursor) + + def get_connection_params(self): + return self.settings_dict.get('OPTIONS', {}) + + def _get_new_connection(self, conn_params): + with lock_check_jvm_status: + if not jpype.isJVMStarted(): + jpype.startJVM(ignoreUnrecognized=True) + + conn = jpype.dbapi2.connect( + self.jdbc_url, + driver=self.jdbc_driver, + driver_args=dict( + user=self.settings_dict['USER'], + password=self.settings_dict['PASSWORD'], + **conn_params + ), + converters=jdbc_type_converters, + ) + + return conn + + def _close(self): + if self.connection is not None and self.connection.driver_connection.autocommit: + # if jdbc connection's autoCommit is on + # jpype will throw NotSupportedError after rollback called + # we make a little dynamic patch here, make sure + # SQLAlchemy will not do rollback before recycling connection + self.connection._pool._reset_on_return = None + + logger.debug( + "autoCommit of current JDBC connection to %s %s is on, won't do rollback before returning", + self.alias, self.connection.driver_connection) + + return super()._close() diff --git a/dj_db_conn_pool/backends/jdbc/oceanbase/mixins.py b/dj_db_conn_pool/backends/jdbc/oceanbase/mixins.py index feacd3f..33cd594 100644 --- a/dj_db_conn_pool/backends/jdbc/oceanbase/mixins.py +++ b/dj_db_conn_pool/backends/jdbc/oceanbase/mixins.py @@ -1,4 +1,4 @@ -from dj_db_conn_pool.backends.jdbc import JDBCDatabaseWrapperMixin +from dj_db_conn_pool.backends.jdbc.mixins import JDBCDatabaseWrapperMixin class JDBCOceanBaseDatabaseWrapperMixin(JDBCDatabaseWrapperMixin): diff --git a/dj_db_conn_pool/backends/jdbc/oracle/base.py b/dj_db_conn_pool/backends/jdbc/oracle/base.py index 87d746a..cecec9b 100644 --- a/dj_db_conn_pool/backends/jdbc/oracle/base.py +++ b/dj_db_conn_pool/backends/jdbc/oracle/base.py @@ -7,8 +7,7 @@ from django.db.backends.oracle import base from sqlalchemy.dialects.oracle.base import OracleDialect -from dj_db_conn_pool.backends.jdbc import JDBCDatabaseWrapperMixin -from dj_db_conn_pool.backends.jdbc.mixins import JdbcDialectMixin +from dj_db_conn_pool.backends.jdbc.mixins import JdbcDialectMixin, JDBCDatabaseWrapperMixin logger = logging.getLogger(__name__)