- Introducción a JDBC
- Interfaces y clases comunes para conexiones a bases de datos
- Acceso a bases de datos mediante JDBC
Contenido del capítulo
I. Introducción
1. Concepto
JDBC significa Java DataBase Connectivity. Es una especificación estándar desarrollada por Sun Microsystems (ahora Oracle) que permite a las aplicaciones Java interactuar con distintos sistemas de gestión de bases de datos.
La API JDBC se encuentra en el paquete java.sql, permitiendo a los desarrolladores crear programas que accedan a diversas bases de datos mediante sentencias SQL.
JDBC no puede conectarse directamente a una base de datos, sino que requiere un controlador específico proporcionado por el fabricante de la base de datos.
Las aplicaciones desarrolladas con Java y JDBC pueden ejecutarse en múltiples plataformas y bases de datos con mínima dependencia del sistema subyacente.
2. Componentes de programación JDBC
- Aplicación cliente: Código escrito por desarrolladores que utiliza la API JDBC para enviar consultas SQL y obtener resultados.
- Administrador de controladores: Gestiona las conexiones entre la aplicación Java y el sistema de base de datos, seleccionando el controlador adecuado.
- Controlador JDBC: Implementación específica proporcionada por cada proveedor de base de datos que traduce las instrucciones SQL a comandos compatibles con su sistema.
3. Flujo de comunicación desde JDBC hasta la base de datos
II. Paquete java.sql
El paquete java.sql incluye interfaces y clases fundamentales:
- Interfaz
Drivery claseDriverManager - Clase
Connection - Interfaz
StatementoPreparedStatement - Clase
ResultSet
1. Interfaz Driver y clase DriverManager
Todos los controladores JDBC deben implementar la interfaz Driver. Estos son proporcionados por los fabricantes de bases de datos y deben estar incluidos en el proyecto.
La clase DriverManager se encarga de establecer conexiones y gestionar los controladores.
Métodos principales de DriverManager
| Método | Descripción |
|---|---|
registerDriver(Driver driver) |
Registra un controlador JDBC |
getConnection(String url, String user, String password) |
Establece conexión a una base de datos usando una URL |
setLoginTimeout(int seconds) |
Establece tiempo máximo de espera para conexión |
setLogWriter(PrintWriter out) |
Configura salida de logs de la base de datos |
2. Clase Connection
Representa la conexión entre la aplicación Java y la base de datos. Permite ejecutar sentencias SQL y devolver resultados.
Métodos comunes de Connection
| Método | Descripción |
|---|---|
createStatement() |
Crea un objeto Statement |
prepareStatement(String sql) |
Crea un objeto PreparedStatement |
3. Interfaz Statement
Define métodos para ejecutar operaciones en la base de datos.
Métodos de Statement
| Método | Descripción | Ejemplo |
|---|---|---|
executeUpdate() |
Para INSERT, UPDATE, DELETE | stmt.executeUpdate(query) |
executeQuery() |
Para SELECT | stmt.executeQuery(query) |
execute() |
Para cualquier tipo de sentencia | stmt.execute() |
4. PreparedStatement
Es una versión optimizada de Statement que permite usar parámetros con marcadores de posición (?).
Métodos para establecer parámetros
| Método | Método | Método | Método |
|---|---|---|---|
setAsciiStream() |
setBigDecimal() |
setBinaryStream() |
setBoolean() |
setByte() |
setBytes() |
setDate() |
setDouble() |
setFloat() |
setInt() |
setLong() |
setNull() |
setObject() |
setShort() |
setString() |
setTime() |
setTimestamp() |
setUnicodeStream() |
Sintaxis: setXXXX(posición, valor)
- posición: índice del parámetro (comienza en 1)
- valor: dato real a insertar
5. ResultSet
Representa los resultados obtenidos tras ejecutar una consulta SELECT.
- Los registros comienzan desde el índice 1
- Un Statement solo puede tener un ResultSet activo al mismo tiempo
- El método
next()mueve el cursor a la siguiente fila - Se usan métodos como
getString(),getInt(), etc., para recuperar valores
Métodos comunes de ResultSet
| Método | Descripción |
|---|---|
getString(int index) |
Obtiene valor como cadena por posición |
getString(String indexName) |
Obtiene valor como cadena por nombre de columna |
getInt(int index) |
Obtiene valor entero por posición |
getInt(String indexName) |
Obtiene valor entero por nombre de columna |
getFloat(int index) |
Obtiene valor flotante por posición |
getFloat(String indexName) |
Obtiene valor flotante por nombre de columna |
6. Mapeo de tipos de datos SQL a Java
| Tipo SQL | Tipo Java |
|---|---|
| CHAR | String |
| VARCHAR | String |
| LONGVARCHAR | String |
| NUMERIC | java.math.BigDecimal |
| DECIMAL | java.math.BigDecimal |
| BIT | boolean |
| TINYINT | byte |
| SMALLINT | short |
| INTEGER | int |
| BIGINT | long |
| REAL | float |
| FLOAT | double |
| DOUBLE | double |
| BINARY | byte[] |
| VARBINARY | byte[] |
| LONGVARBINARY | byte[] |
| DATE | java.sql.Date |
| TIME | java.sql.Time |
| TIMESTAMP | java.sql.Timestamp |
III. Acceso a bases de datos mediante JDBC
1. Paso 1: Cargar el controlador JDBC
En Maven, agregar dependencia:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.29</version>
</dependency>
Registrar el controlador:
| Base de datos | Controlador |
|---|---|
| MySQL | Class.forName("com.mysql.jdbc.Driver") |
| Oracle | Class.forName("oracle.jdbc.driver.OracleDriver") |
| SQL Server | Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver") |
Nota: En versiones recientes de JDBC, el registro automático es posible, por lo tanto, Class.forName() puede omitirse.
2. Paso 2: Establecer conexión
Connection conn = DriverManager.getConnection(url, user, pwd);
URL JDBC sigue formato:
jdbc:<subprotocol>:<subname>
Ejemplo MySQL:
jdbc:mysql://localhost:3306/mydb
3. Formatos de URLs JDBC
| Base de datos | Controlador | URL |
|---|---|---|
| MySQL 5.7 | com.mysql.jdbc.Driver | jdbc:mysql://<hostname>[:<port>]/<dbname> |
| MySQL 8 | com.mysql.cj.jdbc.Driver | jdbc:mysql://<hostname>[:<port>]/<dbname>?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai |
| SQL Server 2005 | com.microsoft.sqlserver.jdbc.SQLServerDriver | jdbc:sqlserver://[ip]:[port];DatabaseName=[Database];user=[user];password=[pw] |
| Oracle Thin | oracle.jdbc.driver.OracleDriver | jdbc:oracle:thin:@[ip]:[port]:[sid] |
Parámetros específicos para MySQL
| Parámetro | Significado | Valor típico |
|---|---|---|
user |
Usuario de base de datos | - |
password |
Contraseña del usuario | - |
useSSL |
Usar conexión segura | false |
useUnicode |
Soporte Unicode | true |
characterEncoding |
Codificación de caracteres | utf8 |
serverTimezone |
Zona horaria del servidor | Asia/Shanghai |
autoReconnect |
Reconexión automática | - |
zeroDateTimeBehavior |
Manejo de fechas cero | convertToNull |
Ejemplos de URL:
jdbc:mysql://localhost:3306/hrms?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
jdbc:mysql://localhost:3306/hrms?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true
4. Paso 3: Crear objeto Statemant
Statement stmt = conn.createStatement();
PreparedStatement pstmt = conn.prepareStatement(sql);
5. Paso 4: Ejecutar sentencia SQL
ResultSet rs = stmt.executeQuery(sql);
ResultSet rs = pstmt.executeQuery();
6. Paso 5: Procesar resultados
while(rs.next()) {
String col1 = rs.getString(1);
String col2 = rs.getString(2);
int col3 = rs.getInt(3);
}
7. Paso 6: Cerrar recursos
finally {
try {
if(rs != null) rs.close();
if(stmt != null) stmt.close();
if(conn != null) conn.close();
} catch(SQLException e) {
System.out.println(e.toString());
}
}
8. Ejemplo completo
List deptList = new ArrayList();
Connection conn = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
String strUrl = "jdbc:mysql://localhost:3306/hrms?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai";
conn = DriverManager.getConnection(strUrl, "root", "root");
Statement stm = conn.createStatement();
String strSql = "select * from Dept";
ResultSet rs = stm.executeQuery(strSql);
while(rs.next()) {
Dep clsDep = new Dep();
clsDep.setDepId(rs.getString(1));
clsDep.setDepName(rs.getString(2));
clsDep.setDepDesc(rs.getString(3));
deptList.add(clsDep);
}
} finally {
conn.close();
}
Diferencias entre Statement y PreparedStatement
Creación
Statement statement = conn.createStatement();
PreparedStatement preStatement = conn.prepareStatement(sql);
Ejecución
ResultSet rSet = statement.executeQuery(sql);
ResultSet pSet = preStatement.executeQuery();
Comparativa
- Rendimiento: PreparedStatement precompila la sentencia y permite reutilizarla con diferentes parámetros, mientras que Statement compila cada vez.
- Seguridad: PreparedStatement evita inyecciones SQL al separar código y datos.