JDBC de uma forma diferente: RowSet

O RowSet é uma classe que tem a função de adicionar o suporte ao padrão JavaBean ao JDBC.

Ao invés de realizarmos as operações desse jeito:

		Connection conn = null;
		Statement stmt = null;

		try {
			conn = DriverManager.getConnection("jdbc:oracle:thin:@//database:1521/orcl.localdomain", "thiago", "senha");

			stmt = conn.createStatement();
			ResultSet rs = stmt.executeQuery("SELECT * FROM CLIENTE");

			while(rs.next()) {
				ResultSetMetaData rsMetaData = rs.getMetaData();
				int columnCount = rsMetaData.getColumnCount();
				for(int colIdx = 0; colIdx<columnCount; colIdx++) {
					System.out.print(rs.getObject(colIdx+1) + "|");
				}
				System.out.println();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}

Realizamos de uma maneira "mais JavaBean":

		RowSetFactory rowSetFactory = null;
		JdbcRowSet jdbcRs = null;

		try {
			rowSetFactory = RowSetProvider.newFactory();

			jdbcRs = rowSetFactory.createJdbcRowSet();

			jdbcRs.setUrl("jdbc:oracle:thin:@//database:1521/orcl.localdomain");
			jdbcRs.setUsername("thiago");
			jdbcRs.setPassword("senha");

			jdbcRs.setCommand("SELECT * FROM CLIENTE");
			jdbcRs.execute();
			while(jdbcRs.next()) {
				ResultSetMetaData rsMetaData = jdbcRs.getMetaData();
				int columnCount = rsMetaData.getColumnCount();
				for(int colIdx = 0; colIdx<columnCount; colIdx++) {
					System.out.print(jdbcRs.getObject(colIdx+1) + "|");
				}
				System.out.println();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}

A vantagem dessa segunda abordagem é que com o padrão JavaBean permitimos que outros componentes sejam notificados quando um evento ocorre no RowSet, como por exemplo uma alteração de valor. Essa implementação é executada "por cima" do JDBC, ou seja, no fundo é tudo JDBC.

Existem dois tipos de RowSet:

  • RowSet conectado: A conexão com a fonte de dados é mantida por todo ciclo de vida do RowSet
  • RowSet desconectado: A conexão pode ser fechado durante o ciclo de vida, mas para recuperar ou atualizar dados é necessário restabelecer a conexão.

Um RowSet desconectado pode ter um objeto para leitura do tipo RowSetReader e um objeto para escrita do tipo RowSetWriter. O RowSet herda do ResultSet, por isso as operações de recuperação de dados podem ser feitas da mesma forma, como podemos ver nos dois primeiros exemplos. Além disso, temos um RowSetMetaData (que herda de ResultSetMetaData) para recuperação dos metadados associados.

Outra vantagem é que o ResultSet sempre precisa de uma conexão ativa, já o RowSet, como podemos ver existem opções para se trabalhar com conexões não ativas (desconectado).

Desde o Java 5 temos as seguintes implementações de RowSet: JdbcRowSet, CachedRowSet, WebRowSet, FilteredRowSet, e JoinRowSet:

  • O JdbcRowSet é um RowSet conectado e, por isso, é necessário estar conectado na base de dados para utilizá-lo. Ele é na verdade um wrapper pro ResultSet, mas com a possibilidade de podemos navegar pra frente e para trás (scrollable) e os dados serem atualizáveis (updatable) por padrão.
  • O  CachedRowSet mantém os dados em memória. Dessa forma, conseguimos trabalhar com os dados sem estar conectado na fonte de dados. Por esse motivo ele é um RowSet desconectado.
  • O WebRowSet é a implementação de referência com modelo de dados baseado em XML. Mais informações podem ser encontradas aqui.
  • O FilteredRowSet permite que os dados sejam filtrados. É necessário implementar a inteface Predicate com o método evaluate que retorna true se o objeto deve ser recuperado.
  • O JoinRowSet representa o JOIN do SQL. Ele combina dados de RowSet diferentes em um único objeto utilizando o método addRowSet com as opções:
    • CROSS_JOIN
    • FULL_JOIN
    • INNER_JOIN (default)
    • LEFT_OUTER_JOIN
    • RIGHT_OUTER_JOIN

Para criar esses tipos de RowSet, basta utilizar o RowSetProvider com o método RowSetProvider.newFactory() (linha 4 do segundo exemplo) ou passando a classe que tenha a implementação a ser utilizada no seu driver JDBC: RowSetProvider.newFactory("pacote.Classe");

Após isso, é só utilizar o método adequado da factory de RowSet criada (linha 5 do segundo exemplo):

  • CachedRowSet createCachedRowSet()
  • FilteredRowSet createFilteredRowSet()
  • JdbcRowSet createJdbcRowSet()
  • JoinRowSet createJoinRowSet()
  • WebRowSet createWebRowSet()

Sobre: Thiago Galbiatti Vespa

Thiago Galbiatti Vespa é mestre em Ciências da Computação e Matemática Computacional pela USP e bacharel em Ciências da Computação pela UNESP. Coordenador de projetos do JavaNoroeste, membro do JCP (Java Community Process), consultor Oracle, arquiteto de software de empresas de médio e grande porte, palestrante de vários eventos e colaborador de projetos open source. Possui as certificações: Oracle Certified Master, Java EE 5 Enterprise Architect – Step 1, 2 and 3; Oracle WebCenter Portal 11g Certified Implementation Specialist; Oracle Service Oriented Architecture Infrastructure Implementation Certified Expert; Oracle Certified Professional, Java EE 5 Web Services Developer; Oracle Certified Expert, NetBeans Integrated Development Environment 6.1 Programmer; Oracle Certified Professional, Java Programmer; Oracle Certified Associate, Java SE 5/SE 6