Java Хранимая процедура DB2, выпуск - PullRequest
0 голосов
/ 21 апреля 2020

В моем классе я создал простой метод ниже. Этот класс также имеет основную функцию. Я звоню getRes () из моего хранимого про DB2 c.

public static void getRes() {
   System.out.println("Start");
   try{  
       Class.forName("com.ibm.db2.jcc.DB2Driver");  
       con = DriverManager.getConnection(  
       "jdbc:db2://url:50003/DB","user","Password");  
       Statement stmt=con.createStatement();  
       stmt.executeUpdate("INSERT INTO schema.TEST(ID) VALUES(1)"); 
   } catch(Exception e){
       System.out.println(e);
   } finally {
       if(con!=null) {
           try {
               con.close();
           } catch (SQLException e) {
               // TODO Auto-generated catch block
               e.printStackTrace();
           }
       }
   }
   System.out.println("End");
}

Я вызываю эту функцию из хранимой DB2 версии pro c.

CREATE OR REPLACE PROCEDURE schema.sp_TEST1()
 FENCED
 MODIFIES SQL DATA
EXTERNAL NAME 'connection.Connect.getRes()'
LANGUAGE JAVA
PARAMETER STYLE JAVA;
call schema.sp_TEST1()

Эта хранимая процедура успешно выполняется. Но я сомневаюсь, что мой метод выполнен или нет. Поскольку в тестовой таблице после выполнения не делается никаких записей.

Ниже приведены шаги, которые я выполнил для развертывания этого файла JAR. 1. Экспортировал банку из Eclipse. Проверено, если банка работает нормально. 2. Выполнен вызов sqlj.install_jar (). Проверена установка в SYSIBM.SYSJARCONTENTS. 3. Укажите путь к классу при экспорте сервера БД. CLASSPATH = / home / db2inse5 / sqllib / function / jar / SchemaName / JarName.jar 4.создал sp и вызвал sp.

Ожидаемый вывод - запись сделана в таблице тест. Но я не получаю ожидаемого результата, хотя выполнение sp успешно.

updated-20200423 Я попытался зафиксировать часть соединения с базой данных и заменил ее созданием файла на сервере db. Это сработало, поэтому я могу подтвердить, что jar-файл был правильно вызван из SP, и файл jar-файлов работал правильно. Но вышеуказанная часть еще не решена

public static void getRes() {
    System.out.println("Start");
            File myObj = new File("/opt/filename.txt");
            myObj.createNewFile();
}

1 Ответ

0 голосов
/ 21 апреля 2020

Неправильный метод получения объекта Connection в процедуре Parameter style Java. Пожалуйста, прочитайте следующие топи c в документации: Стиль параметров JAVA процедуры .
Вы не должны получать его, как в обычном jdb c приложении. Не используйте Class.forName звонок. Вместо этого используйте следующее:

con = DriverManager.getConnection("jdbc:default:connection");

Читайте о Ограничения для внешних подпрограмм . Не используйте System.out.println(...) внутри подпрограммы Java.

Пример

Сделайте это без изменений на сервере базы данных от владельца экземпляра db2. Создайте указанную структуру каталогов. Убедитесь, что db2profile получен из вашего сеанса.

ExecAny. java:

package ru.ibm.db2udf;

import com.ibm.db2.jcc.DB2Diagnosable;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;

public class ExecAny 
{
  /*
  --SQL statement for the class file placement w/o jar:
  --${DB2_HOME}/function/ru/ibm/db2udf/ExecAny.class

  --Uncomment the commented out line instead
  --if you placed this class into jar file and deployed it.

  CREATE OR REPLACE PROCEDURE EXEC_ANY 
  (
    SQL VARCHAR(4000)
  , LOG VARCHAR(512) DEFAULT NULL
  )
  LANGUAGE Java
  EXTERNAL NAME 'ru.ibm.db2udf.ExecAny.exec'
  --EXTERNAL NAME 'EXEC_ANY:ru.ibm.db2udf.ExecAny.exec'
  FENCED THREADSAFE
  MODIFIES SQL DATA
  PARAMETER STYLE JAVA;

  Usage:
    call exec_any('declare global temporary table test(i int) on commit preserve rows not logged', '/tmp/exec_any.txt');
    call exec_any('insert into session.test values 1', '/tmp/exec_any.txt');
    -- W/o logging
    call exec_any('insert into session.test values 2');

    select * from session.test;
  */
  public static void exec (String sql, String logfile) throws Exception 
  {
    Logger logger = null;
    FileHandler fhdl = null;
    Connection con = null;
    CallableStatement cst = null;
    try 
    {
      if (logfile != null && ! "".equals((logfile=logfile.trim())))
      {
        logger = Logger.getAnonymousLogger();
        fhdl = new FileHandler(logfile, true);
        fhdl.setFormatter(new SimpleFormatter());
        logger.addHandler(fhdl);
        logger.setLevel(Level.INFO);
        logger.info("***");
      }
      con = DriverManager.getConnection("jdbc:default:connection");
      con.setAutoCommit(false);
      if (logger != null) logger.info("Trying to prepare: " + sql);
      cst = con.prepareCall(sql);
      if (logger != null) logger.info("Prepared: " + sql);
      cst.execute();
      if (logger != null) logger.info("Executed: " + sql);
    } 
    catch (SQLException ex)
    {
      if (logger != null) 
      {
        while (ex != null) 
        {
          if (ex instanceof DB2Diagnosable) 
          {
            DB2Diagnosable db2ex = (DB2Diagnosable) ex;
            com.ibm.db2.jcc.DB2Sqlca sqlca = db2ex.getSqlca();
            if (sqlca != null) 
              logger.severe("\nSQLCODE: " + sqlca.getSqlCode() + "\nMESSAGE: " + sqlca.getMessage());
            else 
              logger.severe("\nError code: " + ex.getErrorCode() + "\nError msg : " + ex.getMessage());
          } 
          else 
            logger.severe("\nError code (no db2): " + ex.getErrorCode() + "\nError msg  (no db2): " + ex.getMessage());
          logger.log(Level.SEVERE, ex.getMessage(), ex);
          ex = ex.getNextException();
        }
      }
    } 
    finally
    {
      if (fhdl != null) {fhdl.close(); fhdl = null;}
      if (cst != null) {cst.close(); cst = null;}
      if (con != null) {con.close(); con = null;}
    }
  }

}

Инструкция по его сборке и развертыванию:

# Suppose we are on a Db2 server and !!!db2profile is sourced in the session!!!
# java sources are in source
# java classes are in classes

$ ls -l
drwxr-xr-x classes
drwxr-xr-x source
drwxr-xr-x sql

$ find source -name '*.java'
source/ru/ibm/db2udf/ExecAny.java

# Compile
$ (cd source; ${DB2_HOME}/java/jdk64/bin/javac -d ../classes ru/ibm/db2udf/ExecAny.java)
# Create jar
$ ${DB2_HOME}/java/jdk64/bin/jar cvf exec_any.jar -C classes ru/ibm/db2udf/ExecAny.class

# Deploy jar
$ db2 connect to mydb
#$ db2 "call sqlj.replace_jar('file:${PWD}/exec_any.jar', 'EXEC_ANY')"
$ db2 "call sqlj.install_jar('file:${PWD}/exec_any.jar', 'EXEC_ANY')"
$ db2 "call sqlj.refresh_classes()"

# Jar file must appear in the ${DB2_HOME}/function/jar directory
$ find ${DB2_HOME}/function/jar -name '*.jar'
.../sqllib/function/jar/<USER_NAME>/EXEC_ANY.jar

# SP CREATE and CALL commands
$ cat sql/exec_any.sql
CREATE OR REPLACE PROCEDURE EXEC_ANY
(
  SQL VARCHAR(4000)
, LOG VARCHAR(512) DEFAULT NULL
)
LANGUAGE Java
EXTERNAL NAME 'EXEC_ANY:ru.ibm.db2udf.ExecAny.exec'
FENCED THREADSAFE
MODIFIES SQL DATA
PARAMETER STYLE JAVA;

(=
-- W/ logging to some file accessible by the db2 instance fenced user on the server
-- $ stat -c "%U" ${DB2_HOME}/ctrl/.fencedID
call exec_any('declare global temporary table test(i int) on commit preserve rows not logged', '/tmp/exec_any.txt');
call exec_any('insert into session.test values 1', '/tmp/exec_any.txt');
-- W/o logging
call exec_any('insert into session.test values 2');
select * from session.test;
=)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...