Provavelmente quando você ouve falar de JDBC, você deve imaginar o seguinte código:
Connection conn = getConnection();
PreparedStatetemt p = conn.prepareStatement("select * from AnyTable");
ResultSet rs = p.executeQuery();
while(rs.next()) {
// mapeia o ResultSet para algum conjunto de objetos
}
Muita gente imagina que JDBC é apenas isso, o que é uma pena. E é uma pena pois ao Java SE 5.0 passou a suportar o JDBC 3.0 (sob o pacote javax.sql), oferecendo uma nova API para facilitar a vida dos desenvolvedores na manipulação e transformação de dados. Neste artigo, vamos ver como manipular os resultados de uma consulta de maneira desconectada do banco de dados, usando o CachedRowSet, e como transformar seus dados em XML e vice-versa, usando WebRowSet.
Ando meio desligado...
Manter uma conexão com o banco de dados aberta por muito tempo pode não ser uma boa estratégia em alguns casos, pois isso reduz a escalabilidade do banco de dados, uma vez que conexão é um recurso limitado. No entanto, algumas vezes é preciso que você manipule alguns dados durante um longo tempo e consista estas atualizações no seu repositório novamente (como pode ser o caso de uma aplicação rich client). Neste caso, trabalhar com o seu conjunto de dados de maneira desconectada do banco é a melhor solução. Contudo, usando a API clássica do JDBC, seria necessário mapear os dados retornados por uma consulta SQL em um ResultSet para objetos Java, desconectar-se do banco de dados, atualizar estes objetos, conectar-se ao banco novamente e reenviar os novos dados - uma tarefa muito trabalhosa e propensa a erros. Porém, se você utilizar um CachedRowSet, esta tarefa se torna "brincadeira de criança".
A interface javax.sql.CachedRowSet, cuja principal implementação é feita pela Sun Microsystems (sob o pacote com.sun.rowset), representa um conjunto de dados resultantes de uma consulta, bem similar à interface java.sql.ResultSet, com uma sutil diferença: quando a conexão com o banco de dados é fechada, um CachedRowSet mantém uma cópia dos dados acessível offline, permitindo que você os manipule mesmo que você já esteja desconectado do seu servidor de banco de dados. Além disso, o CachedRowSet (como todo objeto que estende a interface javax.sql.RowSet) permite que você altere e navegue através do conjunto de dados que ele armazena.
Para ilustrar o uso básico do CachedRowSet, abaixo temos um simples teste que mostra algumas de suas funcionalidades básicas, como iteração, atualização e renovação de dados.
package org.nullability.rowset.demo;
import static java.lang.System.out;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.sql.rowset.CachedRowSet;
import com.sun.rowset.CachedRowSetImpl;
public class CachedRowSetDemo {
public static void main(String... args) throws Exception{
Connection conn = getConnection();
PreparedStatement p = conn.prepareStatement("SELECT * FROM SOME_TABLE");
ResultSet rs = p.executeQuery();
CachedRowSet wrs = new CachedRowSetImpl(); // criando nosso CachedRowSet
wrs.populate(rs); // preenchendo com dados da consulta
p.close();
conn.close(); // fechando a conexão
while(wrs.next()){
out.printf("%s: %d - %s: %d \n", wrs.getMetaData().getColumnName(1), wrs.getInt(1),
wrs.getMetaData().getColumnName(2), wrs.getInt(2));
wrs.updateInt(2,10); // atualiza a segunda coluna da linha atual com o valor "10"
wrs.updateRow(); // efetiva a atualização sobre o modelo
}
wrs.absolute(2); // posiciona o cursor sobre a segunda linha
wrs.deleteRow(); // remove a linha para a qual o cursor está apontando
conn = getConnection();
wrs.acceptChanges(conn); // efetiva as alterações no banco de dados
wrs.close();
conn.close();
}
private static Connection getConnection() throws ClassNotFoundException, SQLException {
Class.forName("");
Connection conn = DriverManager.getConnection("SUA STRING DE CONEXAO");
return conn;
}
}
Pronto. Sem necessidade de fazer mapeamentos temporários, conseguimos manipular nossos dados e refletir estas alterações no banco de dados de maneira bem simples. Mas, e se quiséssemos exportar nossos dados para um outro formato, como XML?
Então você quer XML?
Então você vai precisar trabalhar com um WebRowSet. Assim como o CachedRowSet, o WebRowSet permite que você manipule dados de uma consulta de maneira desconectada do banco de dados. Adicionalmente, o WebRowSet permite que você exporte e importe dados para um formato XML pré-definido (a definição do schema está aqui), dividido em três partes: propriedades, meta-dados e dados. Abaixo, temos um exemplo simples de como exportar um conjunto de dados para XML a partir de um WebRowSet.
package org.nullability.rowset.demo;
import java.io.FileOutputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.sql.rowset.WebRowSet;
import com.sun.rowset.WebRowSetImpl;
public class WebRowSetDemo {
/**
* @param args
*/
public static void main(String... args) throws Exception{
Connection conn = getConnection();
PreparedStatement p = conn.prepareStatement("SELECT * FROM SOME_TABLE");
ResultSet rs = p.executeQuery();
WebRowSet wrs = new WebRowSetImpl();
wrs.populate(rs);
p.close();
conn.close();
wrs.writeXml(new FileOutputStream("output.xml"));
wrs.close();
}
private static Connection getConnection() throws ClassNotFoundException, SQLException {
Class.forName("");
Connection conn = DriverManager.getConnection("SUA STRING DE CONEXAO");
return conn;
}
}
Por que deveria usar?
Os motivos principais para se usar tanto o CachedRowSet quanto o WebRowSet são:
- Facilidade para manipulação de dados
- Menor quantidade de atualizações sendo feitas diretamente no banco
- Facilidade para transformação de dados para um outro formato, sendo possível utilizar um WebRowSet para a criação de RESTful Web Services simples
Ainda assim, é preciso ficar atento a dois pontos:
- Concorrência na atualização de dados, uma vez que, tanto no caso do CachedRowSet quanto no caso do WebRowSet, os dados são manipulados offline
- Versão nova do JDK, uma vez que o suporte ao JDBC 3.0 só existe a partir do Java SE 5.0
Bom, e por enquanto é isso. Até a próxima.