Microsoft driver JDBC para engenharia de dados Microsoft Fabric

O JDBC (Conectividade de Banco de Dados Java) é um padrão amplamente adotado que permite que os aplicativos cliente se conectem e trabalhem com dados de bancos de dados e plataformas de Big Data.

O driver Microsoft JDBC para Fabric Data Engineering permite conectar, consultar e gerenciar cargas de trabalho do Spark no Fabric com a confiabilidade 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 suas aplicações Java e ferramentas de BI. Essa integração permite que você envie e execute código Spark diretamente, sem precisar criar itens separados de definição de notebooks ou tarefas do Spark. O driver é compatível com clientes JDBC populares, como DbVisualizer e DBeaver, bem como ferramentas de BI que dão suporte à conectividade JDBC, incluindo o Tableau.

Principais características

  • APIs JDBC 4.2: Implementa as APIs JDBC 4.2 para conectividade do Spark SQL, com limitações do Spark e do Livy, como ausência de transações JDBC e conjuntos de resultados somente de avanço e somente leitura
  • Autenticação da ID do Microsoft Entra: vários fluxos de autenticação, incluindo interativas, credenciais do cliente e autenticação baseada em certificado
  • Sessões de alta concorrência: Compartilhamento opcional de sessões do Fabric para cargas de trabalho concorrentes
  • Pool de conexões explícito: Escolha o HikariCP, um gerenciador de pool padrão, ou LivyBuiltInPooledDataSource; pontos de entrada diretos nunca usam pool
  • Suporte nativo para consultas SQL do Spark: execução direta de instruções SQL do Spark sem tradução
  • Suporte a tipos de dados abrangentes: suporte para todos os tipos de dados SQL do Spark, incluindo tipos complexos (ARRAY, MAP, STRUCT)
  • Pré-busca de Conjunto de Resultados Assíncronos: carregamento de dados em segundo plano para aprimorar o desempenho
  • Padrão de disjuntor: proteção contra falhas em cascata com repetição automática
  • Reconexão automática: recuperação de sessão transparente em falhas de conexão
  • Lógica de Repetição Avançada: Realizar nova tentativa com retrocesso exponencial e recuperação de sessão para aumentar 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 você tem:

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

Baixar e instalar

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

  1. Baixe o arquivo zip ou tar dos links acima.
  2. Extraia o arquivo baixado para acessar os arquivos JAR do driver.
  3. Selecione o arquivo 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 arquivo JAR selecionado ao classpath do aplicativo.
  5. Para clientes JDBC, configure a classe de driver JDBC: com.microsoft.spark.livy.jdbc.LivyDriver

Exemplo de Início Rápido

Este exemplo demonstra como conectar ao Fabric e executar uma consulta usando o driver Microsoft JDBC para Fabric Data Engineering. Antes de executar esse código, certifique-se de cumprir os pré-requisitos e instalar o driver. Ao usar AuthFlow=2, o driver usa DefaultAzureCredential. Para usar a CLI do Azure como fonte de credenciais, instale a 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 da cadeia de conexão

Cadeia de conexão básica

O driver Microsoft JDBC para Fabric Data Engineering utiliza o seguinte formato de cadeia de conexão:

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

Componentes da cadeia de conexão

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

Exemplo de cadeias de conexão

Conexão básica (autenticação baseada em navegador interativo)

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

Com a configuração de recursos do 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 propriedades de sessão do 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 conexões do Microsoft Fabric na versão 1.1.0 do driver e em versões posteriores. Adicione hcEnabled=true para obter uma sessão HC em vez de uma sessão clássica do Livy:

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

Você 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 é opcional. Se hcEnabled for omitido ou definido como false, o driver usa o caminho clássico da sessão de Livy.

Veja a seção High-Concurrency (HC) Mode para orientações completas de configuração.


Authentication

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

Fluxos de autenticação

AuthFlow Método de autenticação Caso de Uso
1 Navegador Interativo Autenticação interativa de usuário usando o OAuth 2.0
2 Cadeia de credenciais padrão do Azure Desenvolvimento e autenticação gerenciada de aplicações; CLI do Azure pode ser uma fonte de credencial
3 Credenciais de Segredo do Cliente (Principal de Serviço) Autenticação automatizada/serviço a serviço
4 Credencial de Certificado de Cliente Autenticação de entidade de serviço baseada em certificado
5 Token de acesso Token de acesso do portador pré-adquirido

Autenticação interativa do navegador

Melhor para: desenvolvimento e aplicativos interativos

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 a autenticação interativa do navegador

Comportamento:

  • Abre uma janela do navegador para autenticação do usuário
  • Armazena em cache credenciais para conexões subsequentes até que elas expirem
  • Adequado para aplicativos de usuário único

Credenciais do cliente ou autenticação de entidade de serviço

Melhor para: serviços automatizados e trabalhos 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 necessários:

  • AuthFlow=3: especifica a autenticação de credenciais do cliente
  • AuthClientID: ID do aplicativo (cliente) da Microsoft Entra ID
  • AuthClientSecret: segredo do cliente do Microsoft Entra ID
  • AuthTenantID: ID do locatário Microsoft Entra

Melhores Práticas:

  • Armazenar segredos com segurança (Azure Key Vault, variáveis de ambiente)
  • Usar identidades gerenciadas quando possível
  • Girar segredos regularmente

Autenticação Baseada em Certificado

Melhor para: aplicativos empresariais que exigem 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 necessários:

  • AuthFlow=4: especifica a autenticação baseada em certificado
  • AuthClientID: ID do aplicativo (cliente)
  • AuthCertificatePath: Caminho para um arquivo de certificado PEM
  • AuthCertificatePassword: senha do certificado
  • AuthTenantID: ID do locatário Microsoft Entra

Autenticação de 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 os atualiza com base na expiração do token. As propriedades analisadas AuthEnableCaching e AuthCacheTTLMS não controlam esse comportamento na versão 2.0.0.

Parâmetros de configuração

Parâmetros necessários

Esses parâmetros devem estar presentes em todas as cadeias de conexão:

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

Parâmetros opcionais

Configuração de versão da API

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

Configuração do Ambiente

Parâmetro Tipo Padrão Description
FabricEnvironmentID Identificador Único Universal (UUID) None Identificador de ambiente de malha para referenciar item de ambiente para sessão do Spark

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

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

Parâmetro Tipo Padrão Description
hcEnabled booleano false Usa uma sessão de alta concorrência no Fabric.
sessionTag String None Tag opcional de sessão no servidor. Use as letras, dígitos, sublinhados ou hífens de 1 a 64.
hcAcquireTimeoutSeconds Integer 300 Tempo máximo de espera para a sessão de HC ficar pronta. Valores válidos variam de 120 a 3.600 segundos.
hcAcquirePollingIntervalMs Integer 1000 Intervalo entre as verificações do status da sessão de HC. Os valores aceitos variam de 50 a 30.000 milissegundos e, durante a execução, são limitados ao intervalo de 100 a 5.000 milissegundos.

Example:

hcEnabled=true;sessionTag=interactive_reporting;hcAcquireTimeoutSeconds=600;hcAcquirePollingIntervalMs=2000;FabricEnvironmentID=<environment-id>
  • FabricEnvironmentID Vale tanto para sessões de HC quanto para as clássicas
  • EnvironmentID também é aceito como um pseudônimo cross-driver. Os nomes de propriedades não diferenciam maiúsculas de minúsculas.

Important

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

Veja a seção Modo de alta simultaneidade (HC) para obter instruções completas de configuração.

Configuração do Spark

Configuração de recursos de sessão

Configurar recursos de sessão do Spark para um desempenho ideal:

Parâmetro Tipo Padrão Description Example
DriverCores Integer Padrão do Spark Número de núcleos de CPU para controlador 4
DriverMemory String Padrão do Spark Alocação de memória para o driver 4g
ExecutorCores Integer Padrão do Spark Número de núcleos de CPU por executor 4
ExecutorMemory String Padrão do Spark Alocação de memória por executor 8g
NumExecutors Integer Padrão do Spark Número de executores 2
SessionName String Gerado automaticamente Nome de sessão personalizada MySparkSession

Example:

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

Propriedades personalizadas da sessão do Spark

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

Exemplo 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

NEE (Mecanismo de Execução Nativa):

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

Configurações de conexão com cliente HTTP

Configure as conexões de transporte HTTP do driver para obter o desempenho ideal da rede. Essas configurações não configuram nem gerenciam o pooling de conexões JDBC:

Parâmetro Tipo Padrão Description
HttpMaxTotalConnections Integer 100 Máximo total de conexões HTTP
HttpMaxConnectionsPerRoute Integer 20 Máximo de conexões por rota
HttpConnectionTimeoutInSeconds Integer 30 Tempo limite da conexão
HttpSocketTimeoutInSeconds Integer 60 Tempo limite de leitura do soquete
HttpReadTimeoutInSeconds Integer 60 Tempo limite de leitura HTTP
HttpConnectionRequestTimeoutSeconds Integer 10 Tempo limite de solicitação de conexão do pool
HttpEnableKeepAlive booleano true Manter conexão HTTP ativa
HttpKeepAliveTimeoutSeconds Integer 60 Tempo limite de manter-se vivo
HttpFollowRedirects booleano true Seguir redirecionamentos HTTP
HttpUseAsyncIO booleano true Usar E/S HTTP assíncrona

Example:

HttpMaxTotalConnections=200;HttpMaxConnectionsPerRoute=100;HttpConnectionTimeoutInSeconds=60

Configuração de proxy

Defina as configurações de proxy HTTP e SOCKS para ambientes empresariais:

Parâmetro Tipo Padrão Description
UseProxy booleano false Habilitar proxy
ProxyTransport String http Tipo de transporte de proxy (http/tcp)
ProxyHost String None Nome do host do proxy
ProxyPort Integer None Porta de proxy
ProxyAuthEnabled booleano false Habilitar a autenticação de proxy
ProxyUsername String None Nome de usuário de autenticação de proxy
ProxyPassword String None Senha de autenticação de proxy
ProxyAuthScheme String basic Esquema de autenticação (Basic/Digest/NTLM)
ProxySocksVersion Integer 5 Versão do 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 log

Parâmetro Tipo Padrão Description
LogLevel String WARN Nível de log: TRACE, DEBUG, INFO, WARN, ERROR

Example:

LogLevel=DEBUG

Local de log padrão:

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

Configuração de log personalizada: Use um arquivo personalizado log4j2.xml ou logback.xml no seu classpath.

Modo de alta concorrência (HC)

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

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

O modo HC é opcional e complementa o pool de conexões JDBC. O modo HC gerencia as sessões Fabric Spark no servidor, enquanto o pool de conexões JDBC gerencia as conexões no aplicativo cliente. Se você não ativar o modo HC, o driver cria uma sessão clássica do Livy.

Escolha entre HC e modo clássico

Use o modo HC quando:

  • Um serviço de aplicação lida com requisições simultâneas que executam SQL do Spark por meio de múltiplas conexões JDBC.
  • Uma ferramenta de BI ou de relatórios abre várias conexões para o mesmo espaço de trabalho e o mesmo lakehouse.
  • Tarefas paralelas de ETL ou trabalhos agendados criam rajadas de conexões JDBC.
  • As conexões utilizam configurações compatíveis com o Spark e podem compartilhar a capacidade do Spark gerenciada pelo servidor.
  • Reduzir o tempo de inicialização da conexão e o provisionamento repetido das sessões do Spark é importante.

Use o modo clássico quando:

  • Sua aplicação usa apenas uma ou algumas conexões JDBC de longa duração.
  • Cada conexão requer uma sessão dedicada do Spark para carga de trabalho rigorosa ou isolamento de recursos.
  • Conexões exigem configurações Spark ou ambientes Fabric substancialmente diferentes.
  • O endpoint do Fabric Livy para o workspace de destino e o lakehouse não é compatível com o modo HC.

Ativar o modo de alta concorrência

O modo HC é opcional. Se você omitir hcEnabled ou defini-lo como false, o driver usará o caminho clássico de sessão do Livy. Defina hcEnabled como true para obter uma sessão de HC:

hcEnabled=true;

Parâmetros necessários no modo HC

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

Parâmetro Anotações
WorkspaceId Deve ser um GUID válido do Fabric Workspace.
LakehouseId Deve ser um GUID válido da Fabric lakehouse.

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

Associação de sessões

O modo HC não garante que toda conexão reutilize uma sessão existente. Para cada solicitação de aquisição de sessão, o driver envia:

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

O serviço Fabric Livy avalia esses valores e decide se deve anexar a conexão a uma sessão quente ou criar uma nova sessão. Para melhorar o reuso das sessões, use valores consistentes entre conexões que tenham a intenção de compartilhar a capacidade do Spark gerenciado pelo servidor.

Desativar o modo HC

Você pode desativar novas aquisições de sessão HC, sem reimplantar o driver, definindo a string de conexão HC como 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. Essa opção em toda a JVM força o modo clássico mesmo quando uma cadeia de conexão contém hcEnabled=true.

Entenda 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 a conexão enquanto a aquisição está em andamento interrompe a aquisição e dispara 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 por meio das interfaces padrão JDBC 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 alta concorrência

O exemplo a seguir abre uma conexão JDBC no modo HC, executa uma consulta e libera a conexã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();
        }
    }
}

Trabalhando 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 somente para frente e somente 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 na URL do JDBC para definir o tamanho da página solicitado em bytes. O Statement.setFetchSize() método não controla a recuperação ou o uso da 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
}

Usando instruçõ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 dono de conexão

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

Modelo de uso Ponto de entrada Dono da piscina Encerrar um empréstimo Connection Proprietário do Shutdown
Direto DriverManager, LivyDriver ou LivyDataSource None Fecha fisicamente sua conexão e sessão independentes do Livy. A aplicação fecha todas as conexões. Um LivyDataSource direct não tem um ciclo de vida de fechamento separado.
HikariCP Externo HikariDataSource Respaldado por uma URL JDBC ou LivyDataSource Apenas HikariCP Retorna a conexão proxy do Hikari para o HikariCP. O aplicativo fecha seu HikariDataSource retido.
Pool explícito embutido LivyBuiltInPooledDataSource Um LivyConnectionPool é criado sob demanda para cada geração de fonte de dados configurada Encerra o contrato lógico e reutiliza a sessão física somente após uma limpeza segura. A aplicação fecha sua fonte de dados interna mantida.
SPI de agrupamento padrão LivyConnectionPoolDataSource cria PooledConnection objetos para um gerenciador de pools de nível médio O gerenciador de pool de camada intermediária, não a fábrica Fecha o identificador lógico e notifica o gerenciador de forma síncrona após a limpeza. O gerenciador chama PooledConnection.close() para encerrar cada conexão física.

ConnectionPoolEnabled tem como padrão false tanto no código do driver quanto nas propriedades fornecidas. Não é um interruptor opcional para os pontos de entrada atuais. Use LivyBuiltInPooledDataSource quando o driver deve gerenciar o pool, ou configure um pool externo, como HikariCP. Os outros pontos de entrada criam conexões diretas sem propriedade do pool.

Pool de conexões com o HikariCP

O HikariCP pode criar conexões tanto a partir de LivyDataSource quanto da URL JDBC por meio de LivyDriver. Crie uma instância HikariCP, reutilize-a durante a vida útil da aplicação e use apenas um pool de conexã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 conexões físicas independentes e não possui um pool de conexões nem um ciclo de vida de fechamento separado. Forneça diretamente para a HikariCP para que a HikariCP seja a única dona 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 na URL do JDBC. O HikariCP gerencia conexões do lado do cliente, enquanto o modo HC gerencia sessões compartilhadas do Spark no Fabric. Remova hcEnabled e sessionTag se a aplicação exigir sessões clássicas.

Usar LivyDriver diretamente

Configure a URL JDBC e a classe do driver para que o HikariCP crie conexões físicas através de LivyDriver. Definir explicitamente a classe do driver é opcional quando a detecção automática de provedores de serviço JDBC estiver disponível. Essa configuração não instancia LivyDataSource, portanto seu pool embutido 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:

Configuração ou comportamento Guidance
Propriedade do pool LivyDataSource é somente direto. Quando você o fornece ao HikariCP, o HikariCP passa a ser responsável pelo pool. Use LivyBuiltInPooledDataSource em vez disso quando o motorista deveria ser dono da piscina.
Tamanho do pool Comece com um pool pequeno e aumente-o apenas depois de medir a concorrência da carga de trabalho e a utilização da capacidade. No modo clássico, cada conexão física possui uma sessão do Livy. No modo HC, as conexões podem compartilhar a capacidade do Spark gerenciada pelo servidor.
connectionTimeout Ele controla quanto tempo o chamador espera para pegar uma conexão emprestada, mas não cancela uma tentativa de conexã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 essa configuração em milissegundos.
initializationFailTimeout Um valor negativo pula a conexão inicial e a tentativa de validação. Falhas de conectividade surgem quando a aplicação solicita uma conexão pela primeira vez. Use um valor positivo se o aplicativo precisar verificar a conectividade durante a inicialização.
Validação de conexão O HikariCP usa Connection.isValid(). Sua duração efetiva é controlada pelas configurações de timeout HTTP e de repetição/backoff do driver, e não por validationTimeout do HikariCP. Não configure uma consulta de teste de conexão porque ela substitui a verificação de validação mais leve por uma instrução do Spark.

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

Mapeamento de tipo de dados

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

Tipo SQL do Spark Tipo de SQL JDBC Tipo java Anotaçõ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 metadado não garante suporte completo java.sql.Array a acessores
MAP JAVA_OBJECT String Recuperado como texto JSON
STRUCT STRUCT String Recuperado como texto JSON; o tipo de metadado não garante suporte completo java.sql.Struct a acessores