Introdução

JDBC padroniza com sucesso o acesso à diferentes SGBDs, mas a sua utilização não é trivial e muitas vezes é contra-producente.

Assim, faremos uso de sql2o, uma pequena biblioteca Java que facilita executar instruções SQL em qualquer banco de dados compatível com JDBC.

Em outras palavras, a biblioteca utiliza JDBC, mas oculta seu uso fornecendo métodos mais fáceis de lidar com os bancos de dados.

Pré-requisitos

Baixe o arquivo https://github.com/aaberg/sql2o/releases/download/sql2o-1.5.4/sql2o-1.5.4.zip, antes de tudo, descompacte e adicione sql2o-1.5.4.jar como biblioteca do projeto.

Utilização do sql2o

Primeiramente, você precisará de uma instância da classe org.sql2o.Sql2o, normalmente criada apenas uma vez, como uma constante (atributo static final), conforme exemplo:

Sql2o sql2o = new Sql2o("jdbc:sqlserver://localhost;databaseName=PROGWEB", "sa", "123456");

Depois, utilizando essa instância, você poderá iniciar quantas conexões quiser:

try (Connection con = sql2o.open()) {
    //
    // Realiza queries com a conexão aberta
    //
}

O bloco try irá fechar a conexão ao acabar o escopo. Note que a classe de conexão é org.sql2o.Connection em vez de java.sql.Connection que é a usada quando usamos JDBC diretamente.

Fazendo inserção de dados

Um INSERT, UPDATE ou DELETE pode ser feito simplesmente da seguinte forma:

String query = "INSERT INTO Pessoas (id, nome, idade) " +
               "VALUES (7, 'Maria', 20)";

try (Connection con = sql2o.open()) {
    con.createQuery(query).executeUpdate();
}

Inserção parametrizada

Fazer um INSERT livre de SQL Injection é só uma questão de adicionar marcadores na query. Uma grande vantagem do sql2o sobre o JDBC nesse quesito é que os parâmetros não são posicionais, mas nomeados. Veja exemplo abaixo:

// Parâmetros obtidos do usuário
int paramId      = Integer.parseInt( request.getParameter("id") );
String paramNome = request.getParameter("nome");
int paramIdade   = Integer.parseInt( request.getParameter("idade") );

// Query parametrizada
String query = "INSERT INTO Pessoas (id, nome, idade) " +
               "VALUES (:id, :nome, :idade)";

try (Connection con = sql2o.open()) {
    // Adiciona parâmetros e executa a query
    con.createQuery(query)
        .addParameter("id", paramId)
        .addParameter("nome", paramNome)
        .addParameter("idade", paramIdade)
        .executeUpdate();
}

Buscando resultados

A obtenção de dados é o maior forte da biblioteca sql2o.

Para obter uma lista de resultados, é interessante uma classe para guardar os valores:

public class Pessoa {
    private int id;
    private String nome;
    private int idade;
    
    // getters e setters
}

Assim, com sql2o basta o seguinte código para criar e preencher uma lista de pessoas:

try (Connection con = sql2o.open()) {
    List<Pessoa> pessoas =
            con.createQuery("SELECT id, nome, idade FROM Pessoas")
                .executeAndFetch(Pessoa.class);
}

O truque é que os atributos da classe tenham o mesmo nome das colunas do resultado. Dessa forma, o mapeamento é automático.

Busca parametrizada

O trecho de código a seguir faz uma busca por todas as pessoas com certa idade:

// Parâmetro obtido do usuário
int paramIdade = Integer.parseInt( request.getParameter("idade") );

// Query parametrizada
String query = "SELECT id, nome, idade FROM Pessoas " +
               "WHERE idade=:idade";

try (Connection con = sql2o.open()) {
    List<Pessoa> pessoas =
            con.createQuery(query)
                .addParameter("idade", paramIdade)
                .executeAndFetch(Pessoa.class);
}

Obtendo apenas a primeira linha

Para que seja retornada apenas a primeira linha, chame executeAndFetchFirst(), nesse caso não retornará uma lista, mas apenas um registro:

try (Connection con = sql2o.open()) {
    Pessoa pessoa =
            con.createQuery("SELECT id, nome, idade FROM Pessoas")
                .executeAndFetchFirst(Pessoa.class);
}

Transações

Para realizar transações, basta chamar o método beginTransaction() em vez de open():

try (Connection con = sql2o.beginTransaction()) {
    //
    // Envia instruções SQL que modifica os dados 
    //
    
    // Numa transação, lembre de chamar commit(), o padrão é rollback!
    con.commit();
}

Quantidade de linhas em uma tabela

Para vermos a quantidade de registros em uma tabela, usamos a função SQL COUNT e chamamos o método executeScalar():

try (Connection con = sql2o.beginTransaction()) {
    String query = "SELECT COUNT(*) FROM Pessoas";
    
    Integer count = con.createQuery(query)
            .executeScalar(Integer.class);
}

Obter valor de auto incremento

Usando a palavra-chave IDENTITY, especificamos uma coluna no SQL Server como auto-incremento:

CREATE TABLE Notas (
    id INT IDENTITY PRIMARY KEY,
    texto VARCHAR(500)
);

De forma que a inserção pode ser feita sem especificar a coluna id:

INSERT INTO Notas (texto) VALUES ('Um dia, eu quero uma casa de praia');
INSERT INTO Notas (texto) VALUES ('Feira do final de semana: ...');

Como o id é incrementado automaticamente pelo SQL Server, se no código Java necessitarmos desse valor, será necessário um passo extra após a inserção, chamando o método getKey():

String query = "INSERT INTO Notas (texto) " +
               "VALUES ('Feira do final de semana: ...')";

try (Connection con = sql2o.open()) {
    // Executa inserção
    con.createQuery(query).executeUpdate();

    // Obtém chave auto incrementada
    int id = con.getKey(Integer.class);
}

Referência

Site oficial (https://www.sql2o.org/)