Click here to view and discuss this page in DocCommentXchange. In the future, you will be sent there automatically.

SAP Sybase SQL Anywhere 16.0 (Deutsch) » SQL Anywhere Server - Programmierung » JDBC-Unterstützung

 

JDBC-Callbacks

Der SQL Anywhere-JDBC-Treiber unterstützt zwei asynchrone Callbacks, einen für die Verarbeitung der SQL MESSAGE-Anweisung und den anderen für die Validierung von Dateiübertragungsanforderungen. Diese ähneln den Callbacks, die vom SQL Anywhere-ODBC-Treiber unterstützt werden.

Nachrichten können unter Verwendung der SQL MESSAGE-Anweisung vom Datenbankserver an die Clientanwendung gesendet werden. Außerdem können Nachrichten aufgrund von lang laufenden Datenbankserver-Anweisungen generiert werden.

Es kann eine Message-Handler-Routine erstellt werden, um diese Nachrichten abzufangen. Nachstehend finden Sie ein Beispiel für die Message-Handler-Callback-Routine.



class T_message_handler implements sybase.jdbc4.sqlanywhere.ASAMessageHandler
{
    private final int MSG_INFO      = 0x80 | 0;
    private final int MSG_WARNING   = 0x80 | 1;
    private final int MSG_ACTION    = 0x80 | 2;
    private final int MSG_STATUS    = 0x80 | 3;
    T_message_handler()
    {
    }

    public SQLException messageHandler(SQLException sqe)
    {
        String msg_type = "unknown";
        
        switch( sqe.getErrorCode() ) {
            case MSG_INFO:      msg_type = "INFO   ";   break;
            case MSG_WARNING:   msg_type = "WARNING";   break;
            case MSG_ACTION:    msg_type = "ACTION ";   break;
            case MSG_STATUS:    msg_type = "STATUS ";   break;
        }
        
        System.out.println( msg_type + ": " + sqe.getMessage() );
        return sqe;
    }
}

Eine Client-Dateiübertragungsanforderung kann validiert werden. Bevor der JDBC-Treiber eine Übertragung zulässt, ruft er die Validierungs-Callback-Funktion auf, falls vorhanden. Falls die Clientdatenübertragung während der Ausführung von indirekten Anweisungen angefordert wird, lässt der JDBC-Treiber die Übertragung nur zu, wenn die Clientanwendung einen Validierungs-Callback registriert hat. Die Bedingungen, unter denen ein Validierungsaufruf durchgeführt wird, werden unten ausführlicher beschrieben. Das Folgende ist ein Beispiel für eine Callback-Routine zur Dateiübertragungsvalidierung .



class T_filetrans_callback implements sybase.jdbc4.sqlanywhere.SAValidateFileTransferCallback
{
    T_filetrans_callback()
    {
    }
    
    public int callback(String filename, int is_write)
    {
        System.out.println( "File transfer granted for file " + filename +                          
                            " with an is_write value of " + is_write );                         
        return( 1 ); // 0 to disallow, non-zero to allow
    }
}

Das Argument filename ist der Name der zu lesenden bzw. zu schreibenden Datei. Der Parameter is_write ist 0, wenn ein Lesevorgang (Übertragung vom Client zum Datenbankserver) angefordert wird, und Nicht-Null bei einem Schreibvorgang. Die Callback-Funktion sollte 0 zurückgeben, wenn die Übertragung nicht zulässig ist, ansonsten Nicht-Null.

Aus Gründen der Datensicherheit protokolliert der Datenbankserver den Ursprung von Anweisungen, die eine Dateiübertragung anfordern. Der Datenbankserver ermittelt, ob die Anweisung direkt von der Clientanwendung empfangen wurde. Wenn er die Datenübertragung vom Client initiiert, sendet der Datenbankserver die Informationen über den Ursprung der Anweisung an die Clientsoftware. Seinerseits erlaubt der JDBC-Treiber nur dann eine bedingungslose Datenübertragung, wenn diese aufgrund der Ausführung einer Anweisung angefordert wird, die direkt von der Clientanwendung gesendet wurde. Ansonsten muss die Anwendung den oben beschriebenen Validierungs-Callback registriert haben. Wenn dieser fehlt, wird die Übertragung verweigert und die Anweisung schlägt mit einem Fehler fehl. Wenn die Clientanweisung eine bereits in der Datenbank vorhandene gespeicherte Prozedur aufruft, wird die Ausführung der gespeicherten Prozedur selbst nicht als vom Client initiierte Anweisung angesehen. Wenn die Clientanwendung allerdings explizit eine temporäre gespeicherte Prozedur erstellt, führt die Ausführung der gespeicherten Prozedur dazu, dass der Datenbankserver die Prozedur als eine vom Client initiierte behandelt. Wenn die Clientanwendung eine Batchanweisung ausführt, wird auf gleiche Weise die Ausführung der Batchanweisung als eine angesehen, die direkt von der Clientanwendung durchgeführt wird.

Das folgende Beispiel einer Java-Anwendung veranschaulicht die Verwendung der vom SQL Anywhere JDBC 4.0-Treiber unterstützten Callbacks. Sie müssen die Datei %SQLANY16%\java\sajdbc4.jar in den Classpath einfügen.



import java.io.*;
import java.sql.*;
import java.util.*;

public class callback
{
    public static void main (String args[]) throws IOException
    {
        Connection          con = null;
        Statement           stmt;

        System.out.println ( "Starting... " );
        con = connect();
        if( con == null )
        {
            return; // exception should already have been reported
        }
        System.out.println ( "Connected... " );
        try
        {
            // create and register message handler callback
            T_message_handler message_worker = new T_message_handler();
            ((sybase.jdbc4.sqlanywhere.IConnection)con).setASAMessageHandler( message_worker );
            
            // create and register validate file transfer callback
            T_filetrans_callback filetran_worker = new T_filetrans_callback();
            ((sybase.jdbc4.sqlanywhere.IConnection)con).setSAValidateFileTransferCallback( filetran_worker );
            
            stmt = con.createStatement();
            
            // execute message statements to force message handler to be called
            stmt.execute( "MESSAGE 'this is an info   message' TYPE INFO TO CLIENT" );
            stmt.execute( "MESSAGE 'this is an action message' TYPE ACTION TO CLIENT" );
            stmt.execute( "MESSAGE 'this is a warning message' TYPE WARNING TO CLIENT" );
            stmt.execute( "MESSAGE 'this is a status  message' TYPE STATUS TO CLIENT" );
            
            System.out.println( "\n==================\n" );
            
            stmt.execute( "set temporary option allow_read_client_file='on'" );
            try
            {
                stmt.execute( "drop procedure read_client_file_test" );
            }
            catch( SQLException dummy )
            {
                // ignore exception if procedure does not exist
            }
            // create procedure that will force file transfer callback to be called
            stmt.execute( "create procedure read_client_file_test()" +
                          "begin" +
                          "    declare v long binary;" +
                          "    set v = read_client_file('sample.txt');" +
                          "end" );
            
            // call procedure to force validate file transfer callback to be called
            try
            {
                stmt.execute( "call read_client_file_test()" );
            }
            catch( SQLException filetrans_exception )
            {
                // Note: Since the file transfer callback returns 1,  
                // do not expect a SQL exception to be thrown
                System.out.println( "SQLException: " +
                                    filetrans_exception.getMessage() );
            }
            stmt.close();
            con.close();
            System.out.println( "Disconnected" );
        }
        catch( SQLException sqe )
        {
            printExceptions(sqe);
        }
    }
   
    private static Connection connect()
    {
        Connection  connection;
        
        System.out.println( "Using jdbc4 driver"  );
        try
        {
            connection = DriverManager.getConnection(
                    "jdbc:sqlanywhere:uid=DBA;pwd=sql" );
        }
        catch( Exception e )
        {
            System.err.println( "Error! Could not connect" );
            System.err.println( e.getMessage() );
            printExceptions( (SQLException)e );
            connection = null;
        }
        return connection;
    }

    static private void printExceptions(SQLException sqe)
    {
        while (sqe != null)
        {

            System.out.println("Unexpected exception : " +
                "SqlState: " + sqe.getSQLState()  +
                " " + sqe.toString() +
                ", ErrorCode: " + sqe.getErrorCode());
            System.out.println( "==================\n" );
            sqe = sqe.getNextException();
        }
    }
}
 Siehe auch