0

I am a tester. As part of my tests, I have to extract data from two DB2 databases. One resides on z/OS, and the other resides on AS400

When I call the functions sequentially, the second one fails with TypeError: "Class com.ibm.db2.jcc.DB2Driver" or "com.ibm.as400.access.AS400JDBCDriver" regardless of the order in which function is called.

Could you please help me understand why the jaydebeapi.connect statement in the second statement fails with Class Not Found? Did I forget to close something (I used context manager for the connection)?

Individually, the functions work fine. But when I call one after the other, the second one fails. Please help.

Python Version: 3.7.0 JayDeBeApi==1.2.3 JPype1==1.1.2

Here's the function I wrote to extract data from DB2 database on zOS

 def query_zos_db2_database(hostname, port, database, username, password, sql_stmt, output_file_path, delimiter="|", header_flag=True):
    """
    Function to connect to a DB2 database hosted on z/OS Mainframe
    :param hostname:
    :param port:
    :param database:
    :param username:
    :param password:
    :param sql_stmt:
    :param output_file_path:
    :param delimiter:
    :param header_flag:
    :return:
    """

    my_name = "query_zos_db2_database()"
    st = timeit.default_timer()
    print("Entered :{}".format(my_name))
    curr_dir = os.getcwd()
    jar_file_path = "{}/../drivers/db2jcc/db2jcc4.jar".format(curr_dir)
    jar_file_path = os.path.abspath(jar_file_path)
    print(jar_file_path)
    if not os.path.exists(jar_file_path):
        logger.error("File not found: {}".format(jar_file_path))
        exit(1)

    list_credentials = list()
    list_credentials.append(username)
    list_credentials.append(password)
    jdbc_conn_str = "jdbc:db2://{0}:{1}/{2}".format(hostname, port, database)
    print("Before connection isJVMStarted: {}".format(jpype.isJVMStarted()))

    with jaydebeapi.connect('com.ibm.db2.jcc.DB2Driver', jdbc_conn_str, list_credentials, jar_file_path) as conn:
        # print(conn)
        cursor = conn.cursor()
        cursor.execute(sql_stmt)
        print("After connection isJVMStarted: {}".format(jpype.isJVMStarted()))

        if os.path.exists(output_file_path):
            os.remove(output_file_path)
        with codecs.open(output_file_path, 'wb', encoding='utf-8') as fout:
            csvwriter = csv.writer(fout, delimiter=delimiter, quoting=csv.QUOTE_MINIMAL)
            if header_flag is True or header_flag == 'True':
                if sys.version_info.major == 2:
                    column_names = [item[0].encode('utf-8') for item in cursor.description]
                    print(column_names)
                else:
                    column_names = [item[0] for item in cursor.description]
                csvwriter.writerow(column_names)

            for row in cursor.fetchall():
                try:
                    if sys.version_info.major == 2:
                        columns = [unicode(column or '') for column in row]
                    else:
                        columns = [str(column or '') for column in row]

                    out_rec = delimiter.join(columns)
                    fout.write(u"{}\n".format(out_rec))
                except UnicodeEncodeError:
                    print("UnicodeEncodeError- Skipping this record {}".format(row))

    et = timeit.default_timer() - st
    print("Exited: {}; Elapsed Time: {} s".format(my_name, et))

Here's the function I write to extract data from DB2 database on AS400:

def query_as400_db2_database(hostname, port, database, username, password, sql_stmt, output_file_path, delimiter="|", header_flag=True):
    """
    Function to connect to a DB2 database hosted on AS400 Mainframe
    :param hostname:
    :param port:
    :param database:
    :param username:
    :param password:
    :param sql_stmt:
    :param output_file_path:
    :param delimiter:
    :param header_flag:
    :return:
    """
    my_name = "query_as400_db2_database()"
    st = timeit.default_timer()

    print("Entered: {}".format(my_name))
    curr_dir = os.getcwd()
    jar_file_path = "{}/../drivers/jt400/jt400.jar".format(curr_dir)
    jar_file_path = os.path.abspath(jar_file_path)
    print(jar_file_path)
    if not os.path.exists(jar_file_path):
        logger.error("File not found: {}".format(jar_file_path))
        exit(1)

    list_credentials = list()
    list_credentials.append(username)
    list_credentials.append(password)
    jdbc_conn_str = "jdbc:as400://{};prompt=false;translate binary=true;naming=system".format(hostname)
    print("Before connection isJVMStarted: {}".format(jpype.isJVMStarted()))

    with jaydebeapi.connect('com.ibm.as400.access.AS400JDBCDriver', jdbc_conn_str, list_credentials, jar_file_path) as conn:
        # print(conn)
        print("After connection isJVMStarted: {}".format(jpype.isJVMStarted()))
        cursor = conn.cursor()
        cursor.execute(sql_stmt)

        if os.path.exists(output_file_path):
            os.remove(output_file_path)
        with codecs.open(output_file_path, 'wb', encoding='utf-8') as fout:
            csvwriter = csv.writer(fout, delimiter=delimiter, quoting=csv.QUOTE_MINIMAL)
            if header_flag is True or header_flag == 'True':
                if sys.version_info.major == 2:
                    column_names = [item[0].encode('utf-8') for item in cursor.description]
                    print(column_names)
                else:
                    column_names = [item[0] for item in cursor.description]
                csvwriter.writerow(column_names)

            for row in cursor.fetchall():
                try:
                    if sys.version_info.major == 2:
                        columns = [unicode(column or '') for column in row]
                    else:
                        columns = [str(column or '') for column in row]

                    out_rec = delimiter.join(columns)
                    fout.write(u"{}\n".format(out_rec))
                except UnicodeEncodeError:
                    print("UnicodeEncodeError- Skipping this record {}".format(row))

    et = timeit.default_timer() - st
    print("Exited: {}; Elapsed Time: {} s".format(my_name, et))
4

1 回答 1

0

对于那个特定的错误情况,有两个潜在的错误原因。

1- 通常在 Java 世界中,java.lang.RuntimeException: Class driverClassName not found当我们没有将 jar 文件的路径添加到 CLASSPATH 环境变量时会引发异常,这正是这里试图解释的内容

2-(最有可能的)Jaydebeapi似乎不支持同时为不同的数据源建立多个连接。

于 2021-05-14T16:49:42.960 回答