04 - JDBC
JDBC (*Java Database Connectivity*) es la API estándar de Java para conectarse a bases de datos y ejecutar SQL. Cada motor (MariaDB, PostgreSQL…) proporciona un driver que la implementa.
1. Conexión
La configuración se externaliza en un fichero de propiedades, no en el código:
db.url=jdbc:mariadb://localhost:3306/library db.user=library_user db.password=secret
public final class DbConnection {
private static final Properties PROPERTIES = loadProperties();
public static Connection get() throws SQLException {
return DriverManager.getConnection(
PROPERTIES.getProperty("db.url"),
PROPERTIES.getProperty("db.user"),
PROPERTIES.getProperty("db.password"));
}
}
DriverManager.getConnection abre una conexión con el driver del classpath.
2. PreparedStatement
String sql = "SELECT id, title, price FROM book WHERE publisher_id = ?";
try (Connection connection = DbConnection.get();
PreparedStatement statement = connection.prepareStatement(sql)) {
statement.setLong(1, publisherId);
try (ResultSet resultSet = statement.executeQuery()) {
while (resultSet.next()) {
long id = resultSet.getLong("id");
String title = resultSet.getString("title");
BigDecimal price = resultSet.getBigDecimal("price");
}
}
}
- El marcador
?se sustituye consetLong,setString… - El parametrizado evita la inyección SQL: el valor nunca se interpreta como parte de la sentencia. Concatenar SQL con datos del usuario es un error grave.
try-with-resourcescierraConnection,PreparedStatementyResultSetaunque ocurra una excepción.
3. Tipos de sentencias
| Método | Uso |
|---|---|
executeQuery() | SELECT; devuelve ResultSet |
executeUpdate() | INSERT/UPDATE/DELETE; devuelve filas afectadas |
execute() | Sentencias generales |
Para recuperar el id generado por un INSERT:
try (PreparedStatement statement = connection.prepareStatement(sql,
Statement.RETURN_GENERATED_KEYS)) {
statement.setString(1, book.title());
statement.executeUpdate();
try (ResultSet keys = statement.getGeneratedKeys()) {
if (keys.next()) {
long id = keys.getLong(1);
}
}
}
4. Transacciones
Por defecto cada sentencia se confirma al ejecutarse (autocommit). Cuando varias operaciones deben ser atómicas — todas o ninguna — se desactiva y se gestiona explícitamente:
Connection connection = DbConnection.get();
try {
connection.setAutoCommit(false);
// insertar pedido, actualizar stock...
connection.commit();
} catch (SQLException exception) {
connection.rollback();
throw exception;
} finally {
connection.setAutoCommit(true);
connection.close();
}
Si algo falla a mitad de camino, rollback() deshace todo lo pendiente.
5. SQLException
SQLException informa del problema: getErrorCode() y getSQLState() permiten distinguir, por ejemplo, una violación de clave única de un fallo de conexión. En la capa de persistencia se traduce a excepciones propias de la aplicación.