Consultor tecnológico de desarrollo de proyectos informáticos.
Ingeniero Técnico en Telecomunicaciones
Puedes encontrarme en Autentia: Ofrecemos servicios de soporte a desarrollo, factoría y formación
Somos expertos en Java/J2EE
Fecha de publicación del tutorial: 2006-09-26
Siguiendo un poco con los tutoriales sobre JDBC, en este pretendo poner de manifiesto, si el lector aun no las conoce, algunas posibilidades que nos permite el API de JDBC (y si el driver nos lo permite) que son menos conocidas.
Los ejemplos de este tutorial están hechos con el siguiente entorno de desarrollo:
-
Jboss Eclipse IDE Milestone 5.
-
JDK 1.4
-
MySQL 5.0
-
MySQL Administrator (opcional)
-
MySQL Connector/J (Driver tipo 4 que implementa la versión JDBC 3.0)
Para los ejemplos del tutorial usaremos la tabla USUARIOS:

Vamos a crear una nueva clase que denominaremos CaracteristicasJDBC:

Copiamos el método getConnection() de otros tutoriales y las constantes que usa:
protected static String dbClass = "com.mysql.jdbc.Driver";
protected static String dbUrl = "jdbc:mysql:///paco";
protected Connection getConnection() {
Properties props = new Properties();
props.put("user","<tu_usuario>");
props.put("password","<tu_password>");
Connection conBBDD = null;
try {
Class.forName(dbClass);
conBBDD=DriverManager.getConnection(dbUrl, props);
} catch(Exception e) {
return null;
}
return conBBDD;
}
Ya podemos empezar:
Ejecutar sentencias por lotes.
Nos basaremos para el ejemplo en tres métodos de Statement:
- addBatch(String sentencia). Añade una sentencia a la lista de sentencias por lotes.
- executeBatch(). Ejecuta la lista de sentencias por lotes. Retorna un array de enteros con el resultado de cada sentencia.
- clearBatch(). Limpia la lista de sentencias por lotes.
Creamos un método que reciba una lista de sentencias y las ejecuta por lotes:
public int[] ejecutaPorLotes(List sentencias) {
Connection conn = getConnection();
int[] resultado = null;
Statement st = null;
try {
st = conn.createStatement();
for (int i = 0; i < sentencias.size(); i++) {
String sentencia = (String) sentencias.get(i);
st.addBatch(sentencia);
}
resultado = st.executeBatch();
st.clearBatch();
return resultado;
} catch (SQLException e) {
e.printStackTrace();
return resultado;
} finally {
if (st != null) {
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
Vamos a probar el código:
public static void main(String[] args) {
CaracteristicasJDBC car = new CaracteristicasJDBC();
ArrayList lista = new ArrayList();
lista.add("INSERT INTO USUARIOS VALUES ('Pepe',19)");
lista.add("INSERT INTO USUARIOS VALUES ('Juan',21)");
int[] resultado = car.ejecutaPorLotes(lista);
for(int i=0;i<resultado.length;i++) {
System.out.println("resultado: "+resultado[i]);
}
}
Ejecutamos y vemos la consola:

Comprobamos los datos en la tabla:

Sería buena idea también modificar el código para desactivar el modo autocommit (setAutoCommit(false)) en la conexión y realizar un rollback en caso de encontrarnos algún error en el array de enteros.
Utilizar un ResultSet Modificable.
En el siguiente ejemplo vamos a modificar el primero de los registros que introdujimos en el ejemplo anterior, usando algunos métodos de ResultSet.
El código del siguiente ejemplo lo vamos a realizar directamente en el método main y lo explicaremos en los comentarios del código:
public static void main(String[] args) {
CaracteristicasJDBC car = new CaracteristicasJDBC();
Connection conn = car.getConnection();
Statement st = null;
ResultSet rs = null;
try {
// Creamos un objeto de tipo Statement y le decimos al driver que vamos
// a usar un ResultSet Scrollable y Updatable.
st = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_UPDATABLE);
String query = "SELECT NOMBRE, EDAD FROM USUARIOS";
// Obtenemos el ResultSet que debería contener dos registros.
rs = st.executeQuery(query);
// Nos situamos sobre el primero de ellos.
rs.first();
// Modificamos la columna EDAD del primer registro del ResultSet
// (sólo en el ResultSet y no en la tabla)
rs.updateInt("EDAD", 29);
// Cancelamos el UPDATE que acabamos de realizar
rs.cancelRowUpdates();
// Volvemos a modificar la columna EDAD del primer registro del
// ResultSet con el nuevo valor
rs.updateInt("EDAD", 30);
// Enviamos los cambios a la base de datos.
rs.updateRow();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (st != null) {
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
Una vez ejecutado el código, comprobamos el resultado en la tabla:

Vamos a modificar el código anterior para eliminar el último registro (Pepe)
public static void main(String[] args) {
CaracteristicasJDBC car = new CaracteristicasJDBC();
Connection conn = car.getConnection();
Statement st = null;
ResultSet rs = null;
try {
// Creamos un objeto de tipo Statement y le decimos al driver que vamos
// a usar un ResultSet Scrollable y Updatable.
st = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_UPDATABLE);
String query = "SELECT NOMBRE, EDAD FROM USUARIOS";
// Obtenemos el ResultSet que debería contener dos registros.
rs = st.executeQuery(query);
// Nos situamos sobre el último de ellos.
rs.last();
// Eliminamos el registro actual.
rs.deleteRow();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (st != null) {
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
Una vez ejecutado el código, comprobamos el resultado en la tabla:

Vamos a modificar de nuevo el código anterior para insertar de nuevo a Pepe y a un amigo de Pepe que se llama Lucas.
public static void main(String[] args) {
CaracteristicasJDBC car = new CaracteristicasJDBC();
Connection conn = car.getConnection();
Statement st = null;
ResultSet rs = null;
try {
// Creamos un objeto de tipo Statement y le decimos al driver que
// vamos a usar un ResultSet Scrollable y Updatable.
st = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_UPDATABLE);
String query = "SELECT NOMBRE, EDAD FROM USUARIOS";
// Obtenemos el ResultSet que debería contener dos registros.
rs = st.executeQuery(query);
// Nos situamos sobre el primero de ellos.
rs.first();
// Nos situamos sobre "insertRow". Esta fila no es más que un buffer
// que nos permite construir un registro para insertarlo en la base
// de datos.
rs.moveToInsertRow();
// Creamos el registro Lucas,34
rs.updateString("NOMBRE", "Lucas");
rs.updateInt("EDAD", 34);
// Lo insertamos en la base de datos.
rs.insertRow();
// Creamos el resgistro Pepe,24
rs.updateString("NOMBRE", "Pepe");
rs.updateInt("EDAD", 24);
// Lo insertamos en la base de datos.
rs.insertRow();
// Volvemos a situarnos sobre el registro en el que estábamos
// previamente a invocar al método moveToInsertRow() (el primero)
rs.moveToCurrentRow();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (st != null) {
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
Una vez ejecutado el código, comprobamos el resultado en la tabla:

Claves autogeneradas.
Algunos motores de base de datos (como mysql) permiten usar claves autogeneradas, es decir, como clave primaria de la tabla un campo autonumérico.
El problema viene cuando insertamos un registro en una tabla con claves autogeneradas y queremos saber cual es el valor de esa clave sin tener que hacer una consulta posterior. ¿ Es posible esto ? vamos a verlo.
Lo primero que vamos a hacer es crearnos una tabla llamada provincias con claves autogeneradas usando MySQLAdministrator:
La tabla tendrá dos campos:
- ID_PROV (Primary Key autogenerada)
- NOMBRE

Para recuperar las claves autogeneradas haremos uso del método de Statement:
- getGeneratedKeys(): Devuelve un ResultSet donde se almacenan las claves creadas.
public static void main(String[] args) {
CaracteristicasJDBC car = new CaracteristicasJDBC();
Connection conn = car.getConnection();
Statement st = null;
ResultSet rs = null;
try {
st = conn.createStatement();
// Insertamos un registro.
st.executeUpdate("INSERT INTO PROVINCIAS (NOMBRE) VALUES ('Madrid')");
// Obtenemos las claves autogeneradas y las mostramos por pantalla
rs=st.getGeneratedKeys();
while(rs.next()) {
int id = rs.getInt(1);
System.out.println("CLAVE: "+id);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (st != null) {
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
Ejecutamos el código y mostramos la consola:

Vamos a ver los registros en la tabla:

Puntos intermedios de rollback.
JDBC permite manejar la transaccionalidad desactivando el modo autocommit (autoentrega) con el método de Connection: setAutoCommit(false). Todos conocemos además los métodos:
- commit(). Realiza los cambios
- rollback(). Deshace los cambios
SavePoint sp = conn.setSavePoint(“NOMBRE”);
....
conn.rollback(sp);
Vamos a hacer un ejemplo y comentaremos en el código lo interesante:
public static void main(String[] args) {
CaracteristicasJDBC car = new CaracteristicasJDBC();
Connection conn = car.getConnection();
Statement st = null;
ResultSet rs = null;
try {
// desactivamos el método de autoentrega.
conn.setAutoCommit(false);
st = conn.createStatement();
// Insertamos un registro en la tabla de usuarios
st.executeUpdate("INSERT INTO USUARIOS VALUES ('Federico',50)");
// Creamos un punto de salvaguarda en este momento.
Savepoint sp = conn.setSavepoint("PUNTO1");
// Modificamos la edad de Federico:
st.executeUpdate("UPDATE USUARIOS SET EDAD = 45 WHERE NOMBRE = 'Federico'");
// Hacemos un rollback al punto PUNTO1:
conn.rollback(sp);
// Entregamos los cambios anteriores a punto1 a la BBDD:
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (st != null) {
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
Si ejecutamos el código anterior, deberíamos insertar un nuevo registro en la tabla de usuarios con nombre Federico y con edad 50, ya que el cambio posterior lo hemos anulado. Una vez ejecutado comprobamos la tabla:
Bueno, pues no ha sido demasiado dificil.
Lo de siempre, si quereis ayuda no tenéis mas que poneros en contacto con nosotros: http://www.autentia.com
A continuación puedes evaluarlo:
Fecha publicación: 2008-02-13-02:29:26
Autor:
Fecha publicación: 2007-01-26-05:45:55
Autor:











