Microsoft JDBC driver para Microsoft Fabric Data Engineering

JDBC (Java Database Connectivity) é um padrão amplamente adotado que permite que aplicações clientes se liguem e trabalhem com dados provenientes de bases de dados e plataformas de big data.

O Driver Microsoft JDBC para Engenharia de Dados Fabric permite-lhe ligar, consultar e gerir cargas de trabalho Spark no Fabric com a fiabilidade e simplicidade do padrão JDBC. Construído sobre as APIs Livy da Fabric, o driver oferece conectividade Spark SQL segura e flexível para as suas aplicações Java e ferramentas de BI. Esta integração permite-lhe submeter e executar código Spark diretamente, sem necessidade de criar itens separados de definição de cadernos ou tarefas Spark. O driver é compatível com clientes JDBC populares como o DbVisualizer e o DBeaver, bem como com ferramentas de BI que suportam conectividade JDBC, incluindo o Tableau.

Principais características

  • APIs do JDBC 4.2: Implementa as APIs do JDBC 4.2 para a conectividade do Spark SQL, com limitações do Spark e do Livy, como a ausência de transações JDBC e conjuntos de resultados apenas de avanço e apenas de leitura
  • Autenticação Microsoft Entra ID: Múltiplos fluxos de autenticação, incluindo credenciais interativas de cliente e autenticação baseada em certificados
  • Sessões de elevada concorrência: Partilha de sessões do Fabric, mediante adesão, para cargas de trabalho simultâneas
  • Agrupamento explícito de ligações: Escolha o HikariCP, um gestor de agrupamento padrão, ou LivyBuiltInPooledDataSource; os pontos de entrada diretos nunca fazem agrupamento
  • Suporte nativo para consultas SQL do Spark: Execução direta de instruções SQL do Spark sem tradução
  • Suporte Abrangente de Tipos de Dados: Suporte para todos os tipos de dados SQL Spark, incluindo tipos complexos (ARRAY, MAP, STRUCT)
  • Pré-busca de Conjuntos de Resultados Assíncronos: Carregamento de dados em segundo plano para melhorar o desempenho
  • Padrão de Disjuntor: Proteção contra falhas em cascata com repetição automática
  • Reconexão Automática: Recuperação transparente de sessão em falhas de ligação
  • Lógica Avançada de Reintento: Reintentar com recuperação exponencial e recuperação de sessão para melhorar a resiliência
  • Suporte a Proxy: Configuração de proxy HTTP e SOCKS para ambientes empresariais

Pré-requisitos

Antes de usar o driver Microsoft JDBC para Fabric Data Engineering, certifique-se de que tem:

  • Java Development Kit (JDK): Java 11, 17 e 21 (recomendado Java 21)
  • Fabric Access: Acesso a um espaço de trabalho Fabric
  • Credenciais Microsoft Entra ID: Credenciais adequadas para autenticação
  • IDs de espaço de trabalho e casa do lago: identificadores GUID para o seu espaço de trabalho Fabric e casa do lago

Download e Instalação

O Microsoft JDBC Driver for Fabric Data Engineering versão 2.0.1 suporta Java 11, 17 e 21. Use a versão mais recente disponível.

  1. Descarregue o ficheiro zip ou tar dos links acima.
  2. Extrai o ficheiro descarregado para aceder aos ficheiros JAR do driver.
  3. Selecione o ficheiro JAR que corresponde à sua versão do JRE:
    • Para Java 11: ms-sparksql-jdbc-2.0.1.jre11.jar
    • Para Java 17: ms-sparksql-jdbc-2.0.1.jre17.jar
    • Para Java 21: ms-sparksql-jdbc-2.0.1.jre21.jar
  4. Adicione o ficheiro JAR selecionado ao percurso de classes da sua aplicação.
  5. Para clientes JDBC, configure a classe do driver JDBC: com.microsoft.spark.livy.jdbc.LivyDriver

Exemplo de Início Rápido

Este exemplo demonstra como se ligar ao Fabric e executar uma consulta utilizando o Microsoft JDBC Driver for Fabric Data Engineering. Antes de executar este código, certifique-se de cumprir os pré-requisitos e instalar o driver. Ao usar AuthFlow=2, o controlador usa DefaultAzureCredential. Para usar o CLI do Azure como origem das credenciais, instale o CLI do Azure e execute az login.

import java.sql.*;

public class QuickStartExample {
    public static void main(String[] args) {
        // Connection string with required parameters
        String url = "jdbc:fabricspark://api.fabric.microsoft.com;" +
                     "FabricWorkspaceID=<workspace-id>;" +
                     "FabricLakehouseID=<lakehouse-id>;" +
                     "AuthFlow=2;" +  // DefaultAzureCredential; Azure CLI can be one source
                     "LogLevel=INFO";
        
        try (Connection conn = DriverManager.getConnection(url)) {
            // Execute a simple query
            try (Statement stmt = conn.createStatement();
                 ResultSet rs = stmt.executeQuery("SELECT 'Hello from Fabric!' as message")) {
                
                if (rs.next()) {
                    System.out.println(rs.getString("message"));
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

Formato de Cadeia de Conexão

Cadeia de Conexão Básica

O Microsoft JDBC Driver for Fabric Data Engineering utiliza o seguinte formato de cadeia de ligação:

jdbc:fabricspark://<hostname>[:<port>][;<parameter1>=<value1>;<parameter2>=<value2>;...]

Componentes da Corda de Ligação

Componente Description Example
Protocol Identificador do protocolo URL JDBC jdbc:fabricspark://
Nome do host Nome do anfitrião do endpoint do Fabric api.fabric.microsoft.com
Porto Número de porta opcional (padrão: 443) :443
Parâmetros Pares chave=valor separados por ponto e vírgula FabricWorkspaceID=<guid>

Exemplos de Cordas de Ligação

Ligação Básica (Autenticação Interativa Baseada em Navegador)

jdbc:fabricspark://api.fabric.microsoft.com;FabricWorkspaceID=<workspace-id>;FabricLakehouseID=<lakehouse-id>;AuthFlow=1

Com Configuração de Recursos Spark

jdbc:fabricspark://api.fabric.microsoft.com;FabricWorkspaceID=<workspace-id>;FabricLakehouseID=<lakehouse-id>;DriverCores=4;DriverMemory=4g;ExecutorCores=4;ExecutorMemory=8g;NumExecutors=2;AuthFlow=2

Com as Propriedades da Sessão Spark

jdbc:fabricspark://api.fabric.microsoft.com;FabricWorkspaceID=<workspace-id>;FabricLakehouseID=<lakehouse-id>;spark.sql.adaptive.enabled=true;spark.sql.shuffle.partitions=200;AuthFlow=2

Com modo de alta concorrência

O modo de alta concorrência (HC) está disponível para ligações ao Microsoft Fabric na versão 1.1.0 do controlador e posteriores. Adicione hcEnabled=true para obter uma sessão HC em vez de uma sessão Livy clássica:

jdbc:fabricspark://api.fabric.microsoft.com;FabricWorkspaceID=<workspace-id>;FabricLakehouseID=<lakehouse-id>;AuthFlow=2;hcEnabled=true

Pode, opcionalmente, identificar a carga de trabalho com uma tag de sessão e selecionar um ambiente Fabric:

jdbc:fabricspark://api.fabric.microsoft.com;FabricWorkspaceID=<workspace-id>;FabricLakehouseID=<lakehouse-id>;AuthFlow=2;hcEnabled=true;sessionTag=orders_etl;FabricEnvironmentID=<environment-id>

O modo HC é de adesão opcional. Se hcEnabled for omitido ou definido para false, o condutor utiliza o percurso clássico da sessão de Livy.

Consulte a secção Modo de elevada concorrência (HC) para obter orientações completas para a configuração.


Authentication

O Microsoft JDBC Driver for Fabric Data Engineering suporta múltiplos métodos de autenticação através do Microsoft Entra ID (anteriormente Azure Active Directory). A autenticação é configurada usando o AuthFlow parâmetro na cadeia de ligação.

Fluxos de Autenticação

AuthFlow Método de autenticação Caso de uso
1 Navegador Interativo Autenticação interativa do utilizador usando OAuth 2.0
2 Cadeia de credenciais predefinida do Azure Desenvolvimento e autenticação gerida de aplicações; CLI do Azure pode ser uma fonte de credencial
3 Credenciais Secretas do Cliente (Principal de Serviço) Autenticação automatizada/serviço-para-serviço
4 Credencial de Certificado de Cliente Autenticação do principal de serviço baseada em certificado
5 Token de Acesso Token de acesso pré-adquirido ao portador

Autenticação Interativa do Navegador

Melhor para: Desenvolvimento e aplicações interativas

String url = "jdbc:fabricspark://api.fabric.microsoft.com;" +
             "FabricWorkspaceID=<workspace-id>;" +
             "FabricLakehouseID=<lakehouse-id>;" +
             "AuthFlow=1;" +
             "LogLevel=INFO";

Connection conn = DriverManager.getConnection(url);

Parâmetros:

  • AuthFlow=1: Especifica autenticação interativa do navegador

Comportamento:

  • Abre uma janela do navegador para autenticação do utilizador
  • Armazena em cache as credenciais das ligações subsequentes até que expirem
  • Adequado para aplicações de utilizador único

Credenciais do Cliente ou Autenticação do Principal de Serviço

Ideal para: Serviços automatizados e tarefas em segundo plano

String url = "jdbc:fabricspark://api.fabric.microsoft.com;" +
             "FabricWorkspaceID=<workspace-id>;" +
             "FabricLakehouseID=<lakehouse-id>;" +
             "AuthFlow=3;" +  
             "AuthClientID=<client-id>;" +
             "AuthClientSecret=<client-secret>;" +
             "AuthTenantID=<tenant-id>;" +
             "LogLevel=INFO";

Connection conn = DriverManager.getConnection(url);

Parâmetros Exigidos:

  • AuthFlow=3: Especifica a autenticação das credenciais do cliente
  • AuthClientID: ID da aplicação (cliente) a partir do ID Microsoft Entra
  • AuthClientSecret: Segredo do cliente do Microsoft Entra ID
  • AuthTenantID: ID de inquilino Microsoft Entra

Melhores Práticas:

  • Armazenar segredos de forma segura (Azure Key Vault, variáveis de ambiente)
  • Use identidades geridas sempre que possível
  • Alterne os segredos regularmente

Autenticação Baseada em Certificado

Ideal para: aplicações empresariais que requerem autenticação baseada em certificado

String url = "jdbc:fabricspark://api.fabric.microsoft.com;" +
             "FabricWorkspaceID=<workspace-id>;" +
             "FabricLakehouseID=<lakehouse-id>;" +
             "AuthFlow=4;" +  
             "AuthClientID=<client-id>;" +
             "AuthCertificatePath=/path/to/certificate.pem;" +
             "AuthCertificatePassword=<certificate-password>;" +
             "AuthTenantID=<tenant-id>;" +
             "LogLevel=INFO";

Connection conn = DriverManager.getConnection(url);

Parâmetros Exigidos:

  • AuthFlow=4: Especifica autenticação baseada em certificado
  • AuthClientID: ID da aplicação (cliente)
  • AuthCertificatePath: Caminho para um ficheiro de certificado PEM
  • AuthCertificatePassword: Palavra-passe do certificado
  • AuthTenantID: ID de inquilino Microsoft Entra

Autenticação por Token de Acesso

Melhor para: cenários de autenticação personalizados

// Acquire token through custom mechanism
String accessToken = acquireTokenFromCustomSource();

String url = "jdbc:fabricspark://api.fabric.microsoft.com;" +
             "FabricWorkspaceID=<workspace-id>;" +
             "FabricLakehouseID=<lakehouse-id>;" +
             "AuthFlow=5;" +  // Access token authentication
             "AuthAccessToken=" + accessToken + ";" +
             "LogLevel=INFO";

Connection conn = DriverManager.getConnection(url);

Cache de autenticação

O driver armazena em cache os tokens de autenticação e atualiza-os com base na expiração do token. As propriedades analisadas AuthEnableCaching e AuthCacheTTLMS não controlam este comportamento na versão 2.0.0.

Parâmetros de Configuração

Parâmetros necessários

Estes parâmetros devem estar presentes em cada cadeia de conexão:

Parâmetro Tipo Description Example
FabricWorkspaceID Identificador Único Universal (UUID) Identificador de espaço de trabalho Fabric <workspace-id>
FabricLakehouseID Identificador Único Universal (UUID) Identificador de Fabric lakehouse <lakehouse-id>
AuthFlow Número inteiro Tipo de fluxo de autenticação (1-5) 2

Parâmetros opcionais

Configuração da Versão API

Parâmetro Tipo Predefinido Description
FabricVersion Cordão v1 Versão da API Fabric
LivyApiVersion Cordão 2023-12-01 Versão da API do Livy

Configuração do ambiente

Parâmetro Tipo Predefinido Description
FabricEnvironmentID Identificador Único Universal (UUID) Nenhum Identificador de ambiente Fabric para referenciar o item de ambiente para a sessão do Spark

Configuração de sessões de alta concorrência

Definir hcEnabled=true para usar o modo HC. As restantes propriedades HC são usadas apenas quando o modo HC está ativado.

Parâmetro Tipo Predefinido Description
hcEnabled booleano false Utiliza uma sessão Fabric de alta concorrência.
sessionTag Cordão Nenhum Etiqueta de sessão opcional no servidor. Use as letras de 1 a 64, dígitos, sublinhados ou hífens.
hcAcquireTimeoutSeconds Número inteiro 300 Tempo máximo para esperar que a sessão de HC esteja pronta. Os valores válidos variam entre 120 e 3.600 segundos.
hcAcquirePollingIntervalMs Número inteiro 1000 Intervalo entre verificações de estado das sessões de HC. Os valores aceites variam de 50 até 30.000 milissegundos e são limitados em tempo de execução a um intervalo de 100 a 5.000 milissegundos.

Example:

hcEnabled=true;sessionTag=interactive_reporting;hcAcquireTimeoutSeconds=600;hcAcquirePollingIntervalMs=2000;FabricEnvironmentID=<environment-id>
  • FabricEnvironmentID Aplica-se tanto às sessões HC como clássicas
  • EnvironmentID é também aceite como pseudónimo cross-driver. Os nomes das propriedades são indiferentes a maiúsculas minúsculas.

Importante

Use sessionTag apenas para etiquetas operacionais não sensíveis. Não inclua segredos, tokens de acesso, dados pessoais, identificadores de clientes ou texto de consulta.

Consulte a secção Modo de Alta Concorrência (HC) para obter instruções completas para a configuração.

Configuração do Spark

Configuração dos Recursos de Sessão

Configure os recursos da sessão Spark para um desempenho ótimo:

Parâmetro Tipo Predefinido Description Example
DriverCores Número inteiro Spark predefinição Número de núcleos de CPU para o driver 4
DriverMemory Cordão Spark predefinição Alocação de memória para o driver 4g
ExecutorCores Número inteiro Spark predefinição Número de núcleos de CPU por executor 4
ExecutorMemory Cordão Spark predefinição Alocação de memória por executor 8g
NumExecutors Número inteiro Spark predefinição Número de executores 2
SessionName Cordão Gerado automaticamente Nome de sessão personalizado MySparkSession

Example:

DriverCores=4;DriverMemory=4g;ExecutorCores=4;ExecutorMemory=8g;NumExecutors=2; SessionName=MySparkSession

Propriedades Personalizadas da Sessão Spark

Qualquer parâmetro com o prefixo spark. é automaticamente aplicado à sessão Spark:

Exemplos de Configurações do Spark:

spark.sql.adaptive.enabled=true
spark.sql.adaptive.coalescePartitions.enabled=true
spark.sql.shuffle.partitions=200
spark.sql.autoBroadcastJoinThreshold=10485760
spark.dynamicAllocation.enabled=true
spark.dynamicAllocation.minExecutors=1
spark.dynamicAllocation.maxExecutors=10
spark.executor.memoryOverhead=1g

Motor de Execução Nativo (NEE):

spark.nee.enabled=true

Exemplo completo:

jdbc:fabricspark://api.fabric.microsoft.com;FabricWorkspaceID=<guid>;FabricLakehouseID=<guid>;DriverMemory=4g;ExecutorMemory=8g;NumExecutors=2;spark.sql.adaptive.enabled=true;spark.nee.enabled=true;AuthFlow=2

Definições de ligação ao cliente HTTP

Configure as ligações de transporte HTTP do driver para um desempenho de rede ótimo. Estas definições não configuram nem gerem o pooling de ligações JDBC:

Parâmetro Tipo Predefinido Description
HttpMaxTotalConnections Número inteiro 100 Número máximo total de ligações HTTP
HttpMaxConnectionsPerRoute Número inteiro 20 Ligações máximas por rota
HttpConnectionTimeoutInSeconds Número inteiro 30 Tempo limite de conexão
HttpSocketTimeoutInSeconds Número inteiro 60 Timeout de leitura do socket
HttpReadTimeoutInSeconds Número inteiro 60 Tempo limite de leitura HTTP
HttpConnectionRequestTimeoutSeconds Número inteiro 10 Pedido de ligação excedeu o tempo limite no pool
HttpEnableKeepAlive booleano true Ativar HTTP keep-alive
HttpKeepAliveTimeoutSeconds Número inteiro 60 Tempo limite de ligação ativa
HttpFollowRedirects booleano true Seguir redirecionamentos HTTP
HttpUseAsyncIO booleano true Utilizar E/S HTTP assíncrona

Example:

HttpMaxTotalConnections=200;HttpMaxConnectionsPerRoute=100;HttpConnectionTimeoutInSeconds=60

Configuração do Proxy

Configure as definições de proxy HTTP e SOCKS para ambientes empresariais:

Parâmetro Tipo Predefinido Description
UseProxy booleano false Ativar proxy
ProxyTransport Cordão http Tipo de transporte proxy (http/tcp)
ProxyHost Cordão Nenhum Nome de host proxy
ProxyPort Número inteiro Nenhum Porta proxy
ProxyAuthEnabled booleano false Ativar autenticação por proxy
ProxyUsername Cordão Nenhum Nome de utilizador de autenticação por proxy
ProxyPassword Cordão Nenhum Palavra-passe de autenticação por proxy
ProxyAuthScheme Cordão basic Esquema de autenticação (básico/digest/ntlm)
ProxySocksVersion Número inteiro 5 Versão SOCKS (4/5)

Exemplo de Proxy HTTP:

UseProxy=true;ProxyTransport=http;ProxyHost=proxy.company.com;ProxyPort=8080;ProxyAuthEnabled=true;ProxyUsername=user;ProxyPassword=pass

Exemplo de Proxy SOCKS:

UseProxy=true;ProxyTransport=tcp;ProxyHost=socks.company.com;ProxyPort=1080;ProxySocksVersion=5

Configuração de registro em log

Parâmetro Tipo Predefinido Description
LogLevel Cordão WARN Nível de registro: TRACE, DEBUG, INFO, WARN, ERROR

Example:

LogLevel=DEBUG

Localização do Registo Predefinido:

${user.home}/.microsoft/livy-jdbc-driver/logs/driver.log

Configuração do Log Personalizado: Utilize um ficheiro log4j2.xml ou logback.xml personalizado no teu classpath.

Modo de alta concorrência (HC)

O modo de alta concorrência (HC) foi concebido para aplicações JDBC que abrem múltiplas ligações ao mesmo espaço de trabalho Fabric e lakehouse. Em vez de provisionar uma sessão clássica Spark separada para cada ligação, o Fabric serve essas ligações com capacidade Spark partilhada e gerida pelo servidor.

O modo HC pode reduzir o tempo de arranque da ligação, evitar o provisionamento repetido das sessões Spark e utilizar a capacidade disponível de forma mais eficiente para cargas de trabalho concorrentes. Cada ligação JDBC continua a executar instruções SQL através do respetivo contexto atribuído na sessão HC.

O modo HC é de adesão opcional e complementa o agrupamento de ligações JDBC. O modo HC gere as sessões Fabric Spark no servidor, enquanto o pooling de conexões JDBC gere as ligações na aplicação cliente. Se não ativares o modo HC, o controlador cria uma sessão clássica do Livy.

Escolha entre o modo HC e o modo clássico

Use o modo HC quando:

  • Um serviço de aplicações processa pedidos concorrentes que executam Spark SQL através de múltiplas ligações JDBC.
  • Uma ferramenta de BI ou de relatórios abre várias ligações ao mesmo espaço de trabalho e à mesma casa do lago.
  • Tarefas ETL paralelas ou trabalhos agendados criam rajadas de ligações JDBC.
  • As ligações utilizam configurações Spark compatíveis e podem partilhar a capacidade Spark gerida pelo servidor.
  • Reduzir o tempo de arranque da ligação e o provisionamento repetido das sessões Spark é importante.

Use o modo clássico quando:

  • A sua aplicação utiliza apenas uma ou algumas ligações JDBC de longa duração.
  • Cada ligação requer uma sessão Spark dedicada para carga de trabalho rigorosa ou isolamento de recursos.
  • As ligações requerem configurações Spark ou ambientes Fabric substancialmente diferentes.
  • O ponto final do Fabric Livy para o espaço de trabalho de destino e o armazém de dados não é compatível com o modo HC.

Ativar o modo de alta concorrência

O modo HC é de adesão voluntária. Se omitir hcEnabled ou o definir como false, o controlador utiliza o caminho clássico da sessão Livy. Defina hcEnabled como true para adquirir uma sessão HC:

hcEnabled=true;

Parâmetros necessários no modo HC

A ativação HC requer os seguintes identificadores válidos:

Parâmetro Observações
WorkspaceId Tem de ser um GUID válido da área de trabalho do Fabric.
LakehouseId Tem de ser um GUID válido da Fabric lakehouse.

Inclui SessionTag porque influencia o matching do lado do servidor para sessões quentes.

Associação de sessões

O modo HC não garante que todas as ligações reutilizam uma sessão existente. Para cada solicitação de obtenção de sessão, o controlador envia:

  • O valor SessionTag.
  • A configuração efetiva do Spark, incluindo as definições de conf.* e EnvironmentId.

O serviço Fabric Livy avalia estes valores e decide se deve ligar a ligação a uma sessão quente ou criar uma nova sessão. Para melhorar a reutilização da sessão, utilize valores consistentes entre as ligações que pretendam partilhar a capacidade do Spark gerido pelo servidor.

Desativar o modo HC

Pode desativar a obtenção de novas sessões HC sem voltar a implementar o driver, definindo a cadeia de ligação HC para false ou removendo os parâmetros HC:

hcEnabled=false;

Reversões de emergência: Para uma reversão de emergência, inicie a JVM com -Dcom.microsoft.fabric.jdbc.hc.disable=true. Esta opção de toda a JVM força o modo clássico mesmo quando uma cadeia de ligação contém hcEnabled=true.

Compreenda o comportamento em tempo de execução do HC

  • A aquisição da sessão HC fica bloqueada até que a sessão esteja pronta ou hcAcquireTimeoutSeconds expire.
  • Fechar uma conexão enquanto a aquisição está em curso interrompe a aquisição e aciona a limpeza da sessão HC na medida do possível.
  • Autenticação, execução de consultas, cancelamento, instruções preparadas, tratamento de resultados e FabricEnvironmentID funcionam através das interfaces JDBC padrão em ambos os modos.

Exemplos de uso

Conexão Básica

import java.sql.*;

public class BasicConnectionExample {
    public static void main(String[] args) {
        String url = "jdbc:fabricspark://api.fabric.microsoft.com;" +
                     "FabricWorkspaceID=<workspace-id>;" +
                     "FabricLakehouseID=<lakehouse-id>;" +
                     "AuthFlow=2";
        
        try (Connection conn = DriverManager.getConnection(url)) {
            System.out.println("Connected successfully!");
            System.out.println("Database: " + conn.getMetaData().getDatabaseProductName());
            System.out.println("Driver: " + conn.getMetaData().getDriverName());
            System.out.println("Driver Version: " + conn.getMetaData().getDriverVersion());
        } catch (SQLException e) {
            System.err.println("Connection failed: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

Conexão em modo de elevada concorrência

O exemplo seguinte abre uma ligação JDBC em modo HC, executa uma consulta e liberta a ligação automaticamente:

String url = "jdbc:fabricspark://api.fabric.microsoft.com;" +
             "FabricWorkspaceID=<workspace-id>;" +
             "FabricLakehouseID=<lakehouse-id>;" +
             "AuthFlow=2;" +
             "hcEnabled=true;" +
             "sessionTag=dashboard_queries;" +
             "FabricEnvironmentID=<environment-id>";

try (Connection conn = DriverManager.getConnection(url);
     Statement stmt = conn.createStatement();
     ResultSet rs = stmt.executeQuery("SELECT current_timestamp()")) {
    while (rs.next()) {
        System.out.println(rs.getTimestamp(1));
    }
}

Executando consultas

Consulta simples

public void executeSimpleQuery(Connection conn) throws SQLException {
    String sql = "SELECT current_timestamp() as now";
    
    try (Statement stmt = conn.createStatement();
         ResultSet rs = stmt.executeQuery(sql)) {
        
        if (rs.next()) {
            Timestamp now = rs.getTimestamp("now");
            System.out.println("Current timestamp: " + now);
        }
    }
}

Consulta com filtro

public void executeQueryWithFilter(Connection conn) throws SQLException {
    String sql = "SELECT * FROM sales WHERE amount > 1000 ORDER BY amount DESC";
    
    try (Statement stmt = conn.createStatement();
         ResultSet rs = stmt.executeQuery(sql)) {
        
        while (rs.next()) {
            int id = rs.getInt("id");
            double amount = rs.getDouble("amount");
            Date date = rs.getDate("sale_date");
            
            System.out.printf("ID: %d, Amount: %.2f, Date: %s%n", 
                            id, amount, date);
        }
    }
}

Consulta com Limite

public void executeQueryWithLimit(Connection conn) throws SQLException {
    String sql = "SELECT * FROM customers LIMIT 10";
    
    try (Statement stmt = conn.createStatement();
         ResultSet rs = stmt.executeQuery(sql)) {
        
        ResultSetMetaData metaData = rs.getMetaData();
        int columnCount = metaData.getColumnCount();
        
        // Print column names
        for (int i = 1; i <= columnCount; i++) {
            System.out.print(metaData.getColumnName(i) + "\t");
        }
        System.out.println();
        
        // Print rows
        while (rs.next()) {
            for (int i = 1; i <= columnCount; i++) {
                System.out.print(rs.getString(i) + "\t");
            }
            System.out.println();
        }
    }
}

Trabalhar com Conjuntos de Resultados

Percorrer conjuntos de resultados

public void navigateResultSet(Connection conn) throws SQLException {
    String sql = "SELECT id, name, amount FROM orders";
    
    try (Statement stmt = conn.createStatement();
         ResultSet rs = stmt.executeQuery(sql)) {

        while (rs.next()) {
            System.out.printf(
                "Order %d: %s, %.2f%n",
                rs.getInt("id"),
                rs.getString("name"),
                rs.getDouble("amount"));
        }
    }
}

Os conjuntos de resultados são apenas para a frente e só de leitura. O driver não suporta métodos como first(), last(), e absolute().

Processamento de Grandes Conjuntos de Resultados

O driver pagina os resultados pelo tamanho da resposta. Configure LivyStatementPageSize no URL JDBC para definir o tamanho da página solicitado em bytes. O Statement.setFetchSize() método não controla a recuperação nem o uso de memória.

jdbc:fabricspark://api.fabric.microsoft.com;FabricWorkspaceID=<workspace-id>;FabricLakehouseID=<lakehouse-id>;AuthFlow=2;LivyStatementPageSize=1048576
public void processLargeResultSet(Connection conn) throws SQLException {
    String sql = "SELECT * FROM large_table";
    
    try (Statement stmt = conn.createStatement()) {
        try (ResultSet rs = stmt.executeQuery(sql)) {
            int rowCount = 0;
            while (rs.next()) {
                // Process row
                processRow(rs);
                rowCount++;
                
                if (rowCount % 10000 == 0) {
                    System.out.println("Processed " + rowCount + " rows");
                }
            }
            System.out.println("Total rows processed: " + rowCount);
        }
    }
}

private void processRow(ResultSet rs) throws SQLException {
    // Process individual row
}

Utilização de Declarações Preparadas

public void usePreparedStatement(Connection conn) throws SQLException {
    String sql = "SELECT * FROM products WHERE category = ? AND price > ?";
    
    try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
        // Set parameters
        pstmt.setString(1, "Electronics");
        pstmt.setDouble(2, 100.0);
        
        try (ResultSet rs = pstmt.executeQuery()) {
            while (rs.next()) {
                String name = rs.getString("name");
                double price = rs.getDouble("price");
                System.out.printf("Product: %s, Price: $%.2f%n", name, price);
            }
        }
    }
}

Operações em Lote

O driver não suporta transações JDBC. A execução em lote não é transacional e pode ter sucesso parcial. Uma falha posterior não reverte declarações anteriores bem-sucedidas.

public void executeBatchInsert(Connection conn) throws SQLException {
    String sql = "INSERT INTO logs (timestamp, level, message) VALUES (?, ?, ?)";
    int pendingStatements = 0;
    
    try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
        // Add multiple statements to batch
        for (int i = 0; i < 1000; i++) {
            pstmt.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
            pstmt.setString(2, "INFO");
            pstmt.setString(3, "Log message " + i);
            pstmt.addBatch();
            pendingStatements++;
            
            // Execute batch every 100 statements
            if ((i + 1) % 100 == 0) {
                pstmt.executeBatch();
                pstmt.clearBatch();
                pendingStatements = 0;
            }
        }
        
        if (pendingStatements > 0) {
            pstmt.executeBatch();
        }
        
        System.out.println("Batch insert completed successfully");
    }
}

Escolha um proprietário de ligação

Escolha um componente para dominar o ciclo de vida da ligação. Não coloque um pool de ligação dentro de outro.

Modelo de utilização Ponto de entrada Proprietário da piscina Fechar um empréstimo Connection Responsável pelo desligamento
Direct DriverManager, LivyDriver ou LivyDataSource Nenhum Fecha fisicamente a sua ligação Livy independente e sessão. A aplicação fecha todas as ligações. Um direto LivyDataSource não tem um ciclo de vida próximo separado.
HikariCP Externo HikariDataSource apoiado por um URL JDBC ou LivyDataSource Apenas HikariCP Devolve a ligação proxy do Hikari ao HikariCP. A aplicação fecha os seus itens retidos HikariDataSource.
Pool explícito incorporado LivyBuiltInPooledDataSource Uma criada LivyConnectionPool preguiçosamente para cada geração de fonte de dados configurada Cancela o contrato lógico e só reutiliza a sessão física após uma limpeza segura. A aplicação fecha a sua fonte de dados incorporada retida.
SPI de agrupamento padrão LivyConnectionPoolDataSource cria PooledConnection objetos para um gestor de pools de nível intermédio O gestor de pool de nível intermédio, não a fábrica Fecha o handle lógico e notifica sincronizadamente o gestor após a limpeza. O gestor chama PooledConnection.close() para destruir cada ligação física.

ConnectionPoolEnabled tem como valor por predefinição false tanto no código do controlador como nos ficheiros de propriedades distribuídos. Não é um interruptor opt-in para os pontos de entrada atuais. Utilize LivyBuiltInPooledDataSource quando o driver deverá gerir o pool, ou configure um pool externo, como o HikariCP. Os outros pontos de entrada criam ligações diretas, não proprietárias do pool.

Partilha de ligações com o HikariCP

O HikariCP pode criar ligações a partir de LivyDataSource ou do URL JDBC através de LivyDriver. Crie uma instância HikariCP, reutilize-a durante a vida útil da aplicação e use apenas um pool de ligação em cada configuração.

Dependência de Maven

<dependency>
    <groupId>com.zaxxer</groupId>
    <artifactId>HikariCP</artifactId>
    <version>5.0.1</version>
</dependency>

Utilize LivyDataSource

LivyDataSource cria ligações físicas independentes e não possui um pool de ligações nem um ciclo de vida próximo separado. Forneça diretamente à HikariCP para que a HikariCP seja a única proprietária da piscina:

import com.microsoft.spark.livy.jdbc.LivyDataSource;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public final class ConnectionPoolExample implements AutoCloseable {
    private final HikariDataSource hikariDataSource;

    public ConnectionPoolExample(String url) {
        LivyDataSource configuredDataSource = new LivyDataSource();
        configuredDataSource.setUrl(url);

        HikariConfig config = new HikariConfig();
        config.setDataSource(configuredDataSource);
        config.setMaximumPoolSize(2);
        config.setMinimumIdle(0);
        config.setConnectionTimeout(900000);     // Wait up to 15 minutes for a connection
        config.setInitializationFailTimeout(-1); // Connect on demand
        config.setIdleTimeout(600000);           // 10 minutes
        config.setMaxLifetime(1800000);          // 30 minutes
        config.setPoolName("FabricSparkPool");

        hikariDataSource = new HikariDataSource(config);
    }

    public Connection getConnection() throws SQLException {
        return hikariDataSource.getConnection();
    }

    @Override
    public void close() {
        hikariDataSource.close();
    }

    public static void main(String[] args) throws SQLException {
        String url = "jdbc:fabricspark://api.fabric.microsoft.com;" +
                     "FabricWorkspaceID=<workspace-id>;" +
                     "FabricLakehouseID=<lakehouse-id>;" +
                     "AuthFlow=AZURE_CLI;" +
                     "hcEnabled=true;" +
                     "sessionTag=pooled_app;" +
                     "hcAcquireTimeoutSeconds=600";

        try (ConnectionPoolExample pool = new ConnectionPoolExample(url);
             Connection conn = pool.getConnection();
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery("SELECT 'Pooled connection!' as message")) {

            if (rs.next()) {
                System.out.println(rs.getString("message"));
            }
        }
    }
}

O exemplo ativa o modo HC no URL do JDBC. O HikariCP gere as ligações do lado do cliente, enquanto o modo HC gere sessões Spark partilhadas no Fabric. Remover hcEnabled e sessionTag se a aplicação exigir sessões clássicas.

Utilizar LivyDriver diretamente

Configure a URL JDBC e a classe do driver para que o HikariCP crie ligações físicas através de LivyDriver. Definir de forma explícita a classe do controlador é opcional quando a deteção automática do fornecedor de serviços JDBC está disponível. Esta configuração não instancia LivyDataSource, por isso o seu pool integrado não é utilizado:

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public final class DriverConnectionPoolExample {
    public static HikariDataSource createPool(String url) {
        HikariConfig config = new HikariConfig();
        config.setDriverClassName("com.microsoft.spark.livy.jdbc.LivyDriver");
        config.setJdbcUrl(url);

        // Keep pool sizes small: each classic-mode physical connection owns a Livy session.
        config.setMaximumPoolSize(2);
        config.setMinimumIdle(0);
        config.setConnectionTimeout(900000);     // Wait up to 15 minutes to borrow a connection
        config.setInitializationFailTimeout(-1); // Skip startup validation; connect on demand
        config.setIdleTimeout(600000);           // 10 minutes
        config.setMaxLifetime(1800000);          // 30 minutes
        config.setPoolName("FabricSparkDriverPool");

        return new HikariDataSource(config);
    }

    public static void main(String[] args) throws SQLException {
        String url = "jdbc:fabricspark://api.fabric.microsoft.com;" +
                     "FabricWorkspaceID=<workspace-id>;" +
                     "FabricLakehouseID=<lakehouse-id>;" +
                     "AuthFlow=AZURE_CLI;" +            // Uses the DefaultAzureCredential chain
                     "hcEnabled=true;" +
                     "sessionTag=pooled_app;" +
                     "hcAcquireTimeoutSeconds=600";  // Poll up to 10 minutes for HC readiness

        // Reuse this pool for the application lifetime; main closes it at process exit.
        try (HikariDataSource pool = createPool(url);
             Connection conn = pool.getConnection();
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery("SELECT 'Pooled LivyDriver connection!' as message")) {

            if (rs.next()) {
                System.out.println(rs.getString("message"));
            }
        }
    }
}

Use as seguintes orientações ao configurar o pool:

Ambiente ou comportamento Guidance
Propriedade do pool LivyDataSource é apenas de acesso direto. Quando o forneces ao HikariCP, o HikariCP é o dono do pool. Use-o LivyBuiltInPooledDataSource em vez disso quando o condutor deveria ser dono da piscina.
Tamanho da piscina Comece com um pool pequeno e aumente-o apenas depois de medir a concorrência da carga de trabalho e o uso de capacidade. No modo clássico, cada ligação física possui a sua própria sessão Livy. No modo HC, as ligações podem partilhar a capacidade Spark gerida pelo servidor.
connectionTimeout Controla quanto tempo um chamador espera para pedir emprestada uma ligação, mas não cancela uma tentativa de ligação já em andamento. Para URLs HC, permita hcAcquireTimeoutSeconds; para o modo clássico, permita LivySessionTimeoutSeconds, autenticação, tentativas HTTP e validação. O HikariCP expressa esta definição em milissegundos.
initializationFailTimeout Um valor negativo ignora a ligação inicial e a tentativa de validação. Falhas de conectividade surgem quando a aplicação solicita pela primeira vez uma ligação. Use um valor positivo se a aplicação tiver de verificar a conectividade durante o arranque.
Validação de ligação O HikariCP utiliza Connection.isValid(). A sua duração efetiva é controlada pelas definições de timeout HTTP e de retentativa/backoff do driver, e não pelo validationTimeout do HikariCP. Não configure uma consulta de teste de ligação porque substitui a verificação de validação mais leve por uma instrução Spark.

Para a lista completa de opções de configuração do HikariCP, veja:

Mapeamento de Tipos de Dados

O driver mapeia os tipos de dados SQL do Spark para tipos SQL JDBC e tipos Java:

Tipo SQL Spark Tipo SQL JDBC Tipo Java Observações
BOOLEAN BOOLEAN Boolean
BYTE TINYINT Byte
SHORT SMALLINT Short
INT INTEGER Integer
LONG BIGINT Long
FLOAT FLOAT Float
DOUBLE DOUBLE Double
DECIMAL DECIMAL BigDecimal Precisão e escala preservadas
STRING VARCHAR String
VARCHAR(n) VARCHAR String
CHAR(n) CHAR String
BINARY BINARY byte[]
DATE DATE java.sql.Date
TIMESTAMP TIMESTAMP java.sql.Timestamp
ARRAY ARRAY String Recuperado como texto JSON; o tipo de metadados não garante suporte completo java.sql.Array aos acessores
MAP JAVA_OBJECT String Consultado como texto JSON
STRUCT STRUCT String Recuperado como texto JSON; o tipo de metadados não garante suporte completo java.sql.Struct aos acessores