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

SQL Anywhere 12.0.1 » SQL Anywhere 服务器 - 编程 » JDBC 支持

 

JDBC 回调

SQL Anywhere JDBC 驱动程序支持两个异步回调,一个用来处理 SQL MESSAGE 语句,另外一个用于校验文件传输请求。这些类似于 SQL Anywhere ODBC 驱动程序支持的回调。

可使用 SQL MESSAGE 语句将消息从数据库服务器发送到客户端应用程序。长时间运行的数据库服务器语句也可以生成消息。

可创建消息处理程序例程来拦截这些消息。以下是一个消息处理程序回调例程的示例:



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;
    }
}

可以校验客户端文件传输请求。在允许进行任何传输前,JDBC 驱动程序会调用校验回调函数(如果存在)。如果在执行间接语句(从存储过程内部)期间,请求进行客户端数据传输,则除非客户端应用程序注册了校验回调函数,否则 JDBC 驱动程序将不允许进行传输。下面更详尽地介绍了进行校验调用的条件。下面是一个文件传输校验回调例程的示例。



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
    }
}

filename 参数是要读取或写入的文件的名称。如果请求读取(从客户端传输到服务器),则 is_write 参数为 0;如果请求写入,则该参数为非零值。如果不允许进行文件传输,则回调函数应返回 0,否则返回非零值。

为确保数据安全,服务器会跟踪请求文件传输的语句的源。服务器会确定语句是否是从客户端应用程序直接接收的。从客户端启动数据传输时,服务器会将语句源的相关信息发送到客户端软件。对于 JDBC 驱动程序而言,仅当是由于执行客户端应用程序直接发送的语句而请求数据传输时,它才会允许无条件传输数据。否则,应用程序必须注册上文所述的校验回调函数,如果未注册该函数,则传输会被拒绝,而且语句失败并出现一个错误。请注意,如果客户端语句调用的某个存储过程在数据库中已经存在,则对该存储过程本身的执行不被视为是客户端启动的语句所完成的。但是,如果客户端应用程序显式地创建一个临时存储过程,则服务器会将对该存储过程的执行视为是由客户端启动的。同样,如果客户端应用程序执行一个批处理语句,则该批处理语句的执行被视为是直接由客户端应用程序完成的。

下面的 Java 应用程序示例演示了如何使用 SQL Anywhere JDBC 4.0 驱动程序支持的回调。需要将 %SQLANY12%\java\sajdbc4.jar 文件放入类路径中。



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();
        }
    }
}
 另请参见