INTRODUCCIÓN
Cuando desarrollamos una aplicación con JDBC, una de las tareas que programamos frecuentemente es pasar un objeto de tipo ResultSet a una lista de objetos Map, List<Map<String,Object>>.
Por ejemplo, cuando queremos hacer una consulta a varias tablas, luego el resultado se debe mostrar en una tabla o quisas en un reporte con Jasper Report.
En este oportunidad desarrollara la clase JdbcUtil con un método que permite pasar un objeto ResultSet a una lista, la base de datos a utilizar es EurekaBank.
Las pruebas se realizan con 3 motores de bases de datos diferentes: Oracle, MySQL y SQL Server.
La base de datos la puede descargar desde:
METADATA DEL ResultSet
Para acceder a la metadata de un objeto ResultSet se utiliza el metodo getMetaData(), para obtener la cantidad de columnas se utiliza el método getColumnCount() de la metadata, para obtener el nombre de la columna se utiliza el método getColumnName(i) de la metadata, para obtener la etiqueta de la columna se utiliza el método getColumnLabel(i) de la metadata, siendo i el número de la columna e inicia en 1.
PRUEBA CON ORACLE
La versión de Oracle utilizada es la 11.2 y el driver jdbc utilizado es ojdbc6.jar.:
SQL> select * from v$version; BANNER -------------------------------------------------------------------------------- Oracle Database 11g Express Edition Release 11.2.0.2.0 - Production PL/SQL Release 11.2.0.2.0 - Production CORE 11.2.0.2.0 Production TNS for 32-bit Windows: Version 11.2.0.2.0 - Production NLSRTL Version 11.2.0.2.0 - Production
El código base a utilizar es:
// Datos Oracle String driver = "oracle.jdbc.OracleDriver"; String url = "jdbc:oracle:thin:@localhost:1521:XE"; String user = "eureka"; String pass = "admin"; // Conexión Class.forName(driver).newInstance(); cn = DriverManager.getConnection(url, user, pass); // Consulta String sql = "aquí debe ir la consulta"; PreparedStatement pstm = cn.prepareStatement(sql); ResultSet rs = pstm.executeQuery(); // Obtener metadata ResultSetMetaData md = rs.getMetaData(); int columns = md.getColumnCount(); System.out.println("getColumnName()\tgetColumnLabel()"); for (int i = 1; i <= columns; i++) { System.out.println(md.getColumnName(i) + "\t" + md.getColumnLabel(i)); } rs.close(); pstm.close();
Consultando un tabla
La consulta a utilizar es la siguiente:
select chr_cliecodigo, vch_cliepaterno, vch_cliematerno, vch_clienombre from cliente
El resultado es el siguiente:
getColumnName() getColumnLabel() CHR_CLIECODIGO CHR_CLIECODIGO VCH_CLIEPATERNO VCH_CLIEPATERNO VCH_CLIEMATERNO VCH_CLIEMATERNO VCH_CLIENOMBRE VCH_CLIENOMBRE
Cambiando el titulo de las columnas
La consulta a utilizar es la siguiente:
select chr_cliecodigo cod, vch_cliepaterno pat, vch_cliematerno mat, vch_clienombre nom from cliente
El resultado es el siguiente:
getColumnName() getColumnLabel() COD COD PAT PAT MAT MAT NOM NOM
Consultando dos tablas
La consulta a utilizar es la siguiente:
select tm.vch_tipodescripcion tipo, sum(m.dec_moviimporte) importe from tipomovimiento tm join movimiento m on tm.chr_tipocodigo = m.chr_tipocodigo group by tm.vch_tipodescripcion
El resultado es el siguiente:
getColumnName() getColumnLabel() TIPO TIPO IMPORTE IMPORTE
De los resultados obtenidos se puede concluir que tanto getColumnName() y getColumnLabel() arrojan los mismos valores, se puede utilizar cualquiera de los dos métodos.
PRUEBA CON MYSQL
La versión de MySQL utilizada es la 5.6 y el driver jdbc utilizado es la versión 5.1.23:
Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 1 Server version: 5.6.12-log MySQL Community Server (GPL) Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners.
El código base a utilizar es:
// Datos MySQL String driver = "com.mysql.jdbc.Driver"; String url = "jdbc:mysql://localhost:3306/EUREKABANK"; String user = "eureka"; String pass = "admin"; // Conexión Class.forName(driver).newInstance(); cn = DriverManager.getConnection(url, user, pass); // Consulta String sql = "aquí debe ir la consulta"; PreparedStatement pstm = cn.prepareStatement(sql); ResultSet rs = pstm.executeQuery(); // Obtener metadata ResultSetMetaData md = rs.getMetaData(); int columns = md.getColumnCount(); System.out.println("getColumnName()\tgetColumnLabel()"); for (int i = 1; i <= columns; i++) { System.out.println(md.getColumnName(i) + "\t" + md.getColumnLabel(i)); } rs.close(); pstm.close();
Consultando un tabla
La consulta a utilizar es la siguiente:
select chr_cliecodigo, vch_cliepaterno, vch_cliematerno, vch_clienombre from cliente
El resultado es el siguiente:
getColumnName() getColumnLabel() chr_cliecodigo chr_cliecodigo vch_cliepaterno vch_cliepaterno vch_cliematerno vch_cliematerno vch_clienombre vch_clienombre
Cambiando el titulo de las columnas
La consulta a utilizar es la siguiente:
select chr_cliecodigo cod, vch_cliepaterno pat, vch_cliematerno mat, vch_clienombre nom from cliente
El resultado es el siguiente:
getColumnName() getColumnLabel() chr_cliecodigo cod vch_cliepaterno pat vch_cliematerno mat vch_clienombre nom
Consultando dos tablas
La consulta a utilizar es la siguiente:
select tm.vch_tipodescripcion tipo, sum(m.dec_moviimporte) importe from tipomovimiento tm join movimiento m on tm.chr_tipocodigo = m.chr_tipocodigo group by tm.vch_tipodescripcion
El resultado es el siguiente:
getColumnName() getColumnLabel() vch_tipodescripcion tipo importe importe
De los resultados obtenidos se puede concluir que getColumnLabel() sería la opción mas conveniente a utilizar.
PRUEBA CON SQL SERVER
La versión de SQL Server utilizada es la 2008 R2 y el driver jdbc utilizado es JTDS versión 1.2.5:
Microsoft SQL Server 2008 R2 (RTM) - 10.50.1600.1 (X64) Apr 2 2010 15:48:46 Copyright (c) Microsoft Corporation Enterprise Edition (64-bit) on Windows NT 6.1(Build 7601: Service Pack 1)
El código base a utilizar es:
// Datos SQL Server String driver = "net.sourceforge.jtds.jdbc.Driver"; String url = "jdbc:jtds:sqlserver://localhost:1433/EUREKABANK"; String user = "sa"; String pass = "sql"; // Conexión Class.forName(driver).newInstance(); cn = DriverManager.getConnection(url, user, pass); // Consulta String sql = "aquí debe ir la consulta"; PreparedStatement pstm = cn.prepareStatement(sql); ResultSet rs = pstm.executeQuery(); // Obtener metadata ResultSetMetaData md = rs.getMetaData(); int columns = md.getColumnCount(); System.out.println("getColumnName()\tgetColumnLabel()"); for (int i = 1; i <= columns; i++) { System.out.println(md.getColumnName(i) + "\t" + md.getColumnLabel(i)); } rs.close(); pstm.close();
Consultando un tabla
La consulta a utilizar es la siguiente:
select chr_cliecodigo, vch_cliepaterno, vch_cliematerno, vch_clienombre from cliente
El resultado es el siguiente:
getColumnName() getColumnLabel() chr_cliecodigo chr_cliecodigo vch_cliepaterno vch_cliepaterno vch_cliematerno vch_cliematerno vch_clienombre vch_clienombre
Cambiando el titulo de las columnas
La consulta a utilizar es la siguiente:
select chr_cliecodigo cod, vch_cliepaterno pat, vch_cliematerno mat, vch_clienombre nom from cliente
El resultado es el siguiente:
getColumnName() getColumnLabel() cod cod pat pat mat mat nom nom
Consultando dos tablas
La consulta a utilizar es la siguiente:
select tm.vch_tipodescripcion tipo, sum(m.dec_moviimporte) importe from tipomovimiento tm join movimiento m on tm.chr_tipocodigo = m.chr_tipocodigo group by tm.vch_tipodescripcion
El resultado es el siguiente:
getColumnName() getColumnLabel() vch_tipodescripcion tipo importe importe
De los resultados obtenidos se puede concluir que ambos metodos arrojan los mismos resultados, por lo tanto, se puede utilizar cualquiera de los dos.
CLASE UTILITARIA
A continuación tenemos la clase propuesta para pasar un objeto ResultSet a una List<Map<String,?>>.
package pe.egcc.app.util; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * * @author Eric Gustavo Coronel Castillo * @blog gcoronelc.blogspot.com */ public final class JdbcUtil { private JdbcUtil() { } public static List<Map<String, ?>> rsToList(ResultSet rs) throws SQLException { ResultSetMetaData md = rs.getMetaData(); int columns = md.getColumnCount(); List<Map<String, ?>> results = new ArrayList<Map<String, ?>>(); while (rs.next()) { Map<String, Object> row = new HashMap<String, Object>(); for (int i = 1; i <= columns; i++) { row.put(md.getColumnLabel(i).toLowerCase(), rs.getObject(i)); } results.add(row); } return results; } }
A continuación se tiene un ejemplo de como utilizar esta clase:
List<Map<String,?>> lista = JdbcUtil.rsToList(rs);
Siendo rs un objeto ResultSet.
Puede descargar el proyecto desde el siguiente enlace:
Descargar Proyecto
Descargar Proyecto
CÓDIGO FUENTE
En esta sección te presento un video que una aplicación CLIENTE-SERVIDOR desarrollada con Java y Oracle.
Tú tienes acceso al código fuente de esta aplicación, después del video tienes el enlace.