Buscar
Social
Ofertas laborales ES

Foro sobre Java SE > Resultset vacio o null

Realizo una consulta a mi base mysql, buscando en una tabla todas las facturas que hayan en la misma por el campo idFactura que se recibe por parametro. El problema lo tengo cuando en dicha tabla no se encuentra factura alguna con ese "idFactura" buscado. ya que el resultset devuelve null y por lo tanto me genera mi aplicacion un error : java.sql.SQLException: Illegal operation on empty result set.
Como puedo solucionar eso ??

junio 22, 2012 | Registered Commenterdmorales

¿Qué código usas para obtener el ResultSet?.

junio 22, 2012 | Registered Commenterchoces

public VinculaReciboFactura buscarReciboXIdFactura(int idFactura) {
VinculaReciboFactura unVinculaReciboFactura = null;
Connection con;
Statement st;
try {
con = DriverManager.getConnection(url, login, password);
st = con.createStatement();
ResultSet rs = st.executeQuery("SELECT * FROM VinculaReciboFactura WHERE idFacturaVinculaReciboFactura =" + idFactura);
rs.next();
unVinculaReciboFactura = new VinculaReciboFactura();

unVinculaReciboFactura.setIdVinculaReciboFactura(rs.getInt(1));
unVinculaReciboFactura.setIdReciboVinculaReciboFactura(rs.getInt(2));
unVinculaReciboFactura.setIdFacturaVinculaReciboFactura(rs.getInt(3));

con.close();

} catch (SQLException ex) {
ex.printStackTrace();
}

return unVinculaReciboFactura;
}

junio 22, 2012 | Registered Commenterdmorales

Ya veo donde hay un par de problemas.

1.- ResultSet es un interface. No puedes dar por supuesto que alguna de sus implementaciones no vaya a dar un valor null.
Debes usar un
if(rs!=null)
para asegurarte de que al llamar a alguno de sus métodos, como next, no te lance una excepción.

2.- Acuérdate de cerrar el ResultSet y el Statement después de usarlos, no solo la conexión. Si no lo haces, tendrás un memory leak, porque el Garbage Collector no puede eliminarlos del heap.

junio 22, 2012 | Registered Commenterchoces

perfecto, gracias como siempre por la ayuda.

junio 23, 2012 | Registered Commenterdmorales

Con más calma, te adjunto dos maneras de abordar la cuestión, la 2ª usando JavaSE 1.7 try-with-resources.

public VinculaReciboFactura buscarReciboXIdFactura(int idFactura) {
VinculaReciboFactura unVinculaReciboFactura = null;
Connection con = null;
Statement st = null;
ResultSet rs = null;
try {
con = DriverManager.getConnection(url, login, password);
st = con.createStatement();
rs = st.executeQuery("SELECT * FROM VinculaReciboFactura WHERE idFacturaVinculaReciboFactura =" + idFactura);
if (rs != null) {
rs.next();
unVinculaReciboFactura = new VinculaReciboFactura();

unVinculaReciboFactura.setIdVinculaReciboFactura(rs.getInt(1));
unVinculaReciboFactura.setIdReciboVinculaReciboFactura(rs.getInt(2));
unVinculaReciboFactura.setIdFacturaVinculaReciboFactura(rs.getInt(3));
}
} catch (SQLException ex) {
} finally {
try {
rs.close();
st.close();
con.close();
} catch (SQLException ex) {
}
}
return unVinculaReciboFactura;
}

public VinculaReciboFactura buscarReciboXIdFactura(int idFactura) {
VinculaReciboFactura unVinculaReciboFactura = null;
try (Connection con = DriverManager.getConnection(url, login, password);
Statement st = con.createStatement();
ResultSet rs = st.executeQuery("SELECT * FROM VinculaReciboFactura WHERE idFacturaVinculaReciboFactura =" + idFactura)) {
if (rs != null) {
rs.next();
unVinculaReciboFactura = new VinculaReciboFactura();

unVinculaReciboFactura.setIdVinculaReciboFactura(rs.getInt(1));
unVinculaReciboFactura.setIdReciboVinculaReciboFactura(rs.getInt(2));
unVinculaReciboFactura.setIdFacturaVinculaReciboFactura(rs.getInt(3));
}
} catch (SQLException ex) {
}
return unVinculaReciboFactura;
}

junio 23, 2012 | Registered Commenterchoces

excelente, gracias nuevamente. Saludos.

junio 24, 2012 | Registered Commenterdmorales

ResultSet null???????????????

El contrato de JDBC especifica muy claramente que jamas sera null.
DEBE devolver un ResultSet, pero puede que este no contenga datos.

Esto se prueba con :
if(rs.next) {
// Se trata el registro
....
} else {
// No hay registros
...
}

Salut,
Paposo

junio 27, 2012 | Unregistered CommenterPaposo

Éste es el método genérico que utilizo para los ResulSet:

@SuppressWarnings("unchecked")
private <T> Map<Integer, List<T>> processQuery(final Connection connection, final PreparedStatement preSQLstatement) throws SQLException {
Map<Integer, List<T>> tableData = null;
try (final ResultSet results = preSQLstatement.executeQuery();
final ResultSet rowCount = connection.prepareStatement(("SELECT COUNT(*) AS rows FROM ".concat(results.getMetaData().getTableName(1)))).executeQuery()) {
if (rowCount.next()) {
final int rows = rowCount.getInt("rows");
if (rows > 0) {
tableData = new HashMap<>(2 * rows);
// we first get the number of columns from the table metadata
final int tableColumns = results.getMetaData().getColumnCount();
// now we can loop through every row in the table to fetch data
// by walking down the table rows, moving the cursor one at a time
while (results.next()) {
// we create the row contents list
final List<T> rowElements = new ArrayList<>(2 * tableColumns);
// now we loop through every column in the row
for (int column = 1; column <= tableColumns; column++) {
// to fill the list with row contents
rowElements.add((T) results.getObject(column));
}
// we set the data map with the row data fetched
// the database counts rows from 1, so we adjust the map key
tableData.put(results.getRow() - 1, rowElements);
}
}
}
}
return tableData == null ? new HashMap<Integer, List<T>>(0) : tableData;
}

Con H2 me funciona a la perfección; pero tratándose de un driver JDBC de MySQL, como es el caso de la cuestión en este hilo, ¡No pongo la mano en el fuego!, que ya he tenido demasiadas "rarezas" con varios de ellos, en el pasado.

junio 27, 2012 | Registered Commenterchoces

Guenas.

Veo que el método genérico no cierra el ResultSet rowCount ni el statement que lo genera.
En principio al cerrar la conexion se cerraran ambos, pero si usas este metodo varias veces con la misma conexion puedes llegar a consumir muchos recursos. Pienso que cualquier metodo que abre un nuevo recurso deberia liberarlo y no confiar en que el que lo llama hara las cosas como supone.

Un saludo

junio 29, 2012 | Unregistered CommenterPaposo

Ese código usa try-with-resources de JavaSE 1.7, en el que tanto ResultSet como PreparedStatement implementan AutoCloseable.

junio 29, 2012 | Registered Commenterchoces

Ahhhh! Entiendo.

Realmente la 1.7 tiene grandes mejoras.
Me encanta lo del try-with-resources y las excepciones multiples!!!!
Por otra parte el fork tambien es una eficiente ayuda.
Lastima que en el trabajo aun estamos con la 1.5 :(

Un saludo,
Paposo

julio 1, 2012 | Unregistered CommenterPaposo

Gracias ante todo. Mi problema es que necesito hacer una excepcion con un mensaje cuando hago una consulta a la base de datos y el resultset sale vacio es decir cuando la consulta no encuentra datos en la base de datos, y cuando el resultset no este vacio ejecutar un codigo para llenar una tabla con los datos encontrados al ejecutar la consulta. saludos javier

septiembre 17, 2015 | Unregistered CommenterJavier