Ejemplo: CRUD Profesores

Continuamos diseñando el formulario que se usa para introducir, visualizar, modificar y eliminar datos de los profesores que se hayan incorporado al sistema.

Hay una versión nueva de este curso. Haz clic aquí para revisar JDBC, la versión actualizada de este curso.

En nuestro recorrido por la creación de sistemas CRUD con Java y JDBC, nos adentramos en la gestión de profesores, un proceso que resulta más sencillo que el de alumnos debido a la menor cantidad de campos involucrados, limitándose a nombre y apellidos. Para mantener el orden en nuestro proyecto, comenzamos organizando el código en paquetes específicos, lo que facilita la encapsulación y el control de acceso a las clases, aunque nos encontramos con la necesidad de hacer públicos ciertos paneles para evitar problemas con el editor de NetBeans.

Al diseñar la interfaz, optamos por un JFrame llamado ListProfesoresFrame, que utiliza un BorderLayout para distribuir los componentes. En la parte superior, colocamos una barra de herramientas (toolbar) con botones para agregar, editar, borrar, guardar y cancelar, separados adecuadamente para mejorar la usabilidad. La tabla que mostrará los datos de los profesores se sitúa en el centro, dentro de un panel que también alojará un panel lateral para detalles o formularios.

Para manejar los datos de la tabla, creamos un modelo personalizado llamado ProfesoresTableModel que extiende de AbstractTableModel. Este modelo se conecta con un ProfesorDAO que gestiona la comunicación con la base de datos. Implementamos los métodos esenciales como getRowCount, getColumnCount y getValueAt, donde definimos que la tabla tendrá tres columnas: identificador, apellidos y nombre. Además, sobrescribimos getColumnName para que la tabla muestre los encabezados adecuados. Este enfoque nos permite mantener una separación clara de responsabilidades y un código más limpio y mantenible.

En cuanto a la apariencia de los botones, personalizamos sus iconos y desactivamos elementos visuales como bordes y rellenos para lograr un estilo más moderno y limpio, similar al que se ve en sistemas Mac. También deshabilitamos la capacidad de mover la barra de herramientas para evitar comportamientos no deseados. Inicialmente, los botones de acción están desactivados y se habilitan solo cuando corresponde, según la interacción del usuario.

Para mostrar el estado de la aplicación, utilizamos una etiqueta (Label) en la parte inferior que indica, por ejemplo, cuántos profesores están visibles en la tabla. Ajustamos su fuente y agregamos un borde vacío para mejorar la presentación y evitar que el texto se vea apretado.

La conexión con la base de datos se realiza mediante un MySQLDaoManager, configurado con los parámetros adecuados para acceder a nuestra base de datos de ejemplo. Esto nos permite cargar y mostrar la lista de profesores en la tabla, aunque inicialmente los botones de acción no están activos.

La interactividad se implementa creando un panel de detalles con campos para nombre y apellidos, que puede ser editable o no según el contexto. Definimos métodos para cargar datos (loadData) y guardar datos (saveData) en este panel, manejando casos donde el profesor sea nulo para evitar errores. También incluimos métodos para establecer y obtener el profesor actual, y para activar o desactivar la edición de los campos.

Al integrar este panel en el frame principal, configuramos los eventos de los botones para que respondan adecuadamente. Por ejemplo, al pulsar Nuevo, se limpia el formulario y se habilita la edición para crear un nuevo profesor. Al seleccionar un profesor en la tabla y pulsar Editar, se cargan sus datos en el panel para modificar. Para obtener el profesor seleccionado, extraemos el identificador de la fila seleccionada y consultamos el DAO correspondiente.

El botón Borrar muestra un diálogo de confirmación antes de eliminar el profesor seleccionado de la base de datos. Tras la eliminación, actualizamos la tabla y limpiamos la selección, además de desactivar los botones de edición y borrado para evitar acciones inválidas.

Manejamos la selección en la tabla con un ListSelectionListener que habilita o deshabilita los botones según si hay una fila seleccionada. Esto garantiza que las acciones solo estén disponibles cuando tengan sentido.

El botón Cancelar desactiva la edición y recarga los datos originales del profesor, permitiendo al usuario revertir cambios no deseados. Finalmente, el botón Guardar recopila los datos del formulario y decide si debe insertar un nuevo registro o actualizar uno existente, basándose en si el identificador del profesor es nulo. Después de guardar, actualizamos la tabla para reflejar los cambios y desactivamos la edición.

Probamos el sistema creando un profesor de prueba, modificándolo, cancelando cambios y borrándolo, confirmando que todas las funcionalidades básicas del CRUD funcionan correctamente. Este ejemplo nos prepara para abordar casos más complejos, como la gestión de asignaturas, donde tendremos que combinar datos de varias tablas y manejar relaciones más elaboradas.

public class ProfesoresTableModel extends AbstractTableModel {
    private List<Profesor> profesores = new ArrayList<>();
    private ProfesorDAO profesorDAO;

    public ProfesoresTableModel(ProfesorDAO profesorDAO) {
        this.profesorDAO = profesorDAO;
        updateModel();
    }

    public void updateModel() {
        try {
            profesores = profesorDAO.obtenerTodos();
        } catch (DAOException e) {
            profesores = new ArrayList<>();
            // Manejo de excepción
        }
        fireTableDataChanged();
    }

    @Override
    public int getRowCount() {
        return profesores.size();
    }

    @Override
    public int getColumnCount() {
        return 3; // ID, Apellidos, Nombre
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        Profesor prof = profesores.get(rowIndex);
        switch (columnIndex) {
            case 0: return prof.getId();
            case 1: return prof.getApellidos();
            case 2: return prof.getNombre();
            default: return null;
        }
    }

    @Override
    public String getColumnName(int column) {
        switch (column) {
            case 0: return "ID";
            case 1: return "Apellidos";
            case 2: return "Nombre";
            default: return "";
        }
    }
}
public class DetalleProfesorPanel extends JPanel {
    private JTextField nombreField;
    private JTextField apellidosField;
    private Profesor profesor;
    private boolean editable;

    public DetalleProfesorPanel() {
        setLayout(new GridLayout(2, 2, 5, 5));
        add(new JLabel("Nombre:"));
        nombreField = new JTextField();
        add(nombreField);
        add(new JLabel("Apellidos:"));
        apellidosField = new JTextField();
        add(apellidosField);
    }

    public void setProfesor(Profesor profesor) {
        this.profesor = profesor != null ? profesor : new Profesor();
        loadData();
    }

    public Profesor getProfesor() {
        saveData();
        return profesor;
    }

    public void setEditable(boolean editable) {
        this.editable = editable;
        nombreField.setEditable(editable);
        apellidosField.setEditable(editable);
    }

    private void loadData() {
        if (profesor != null) {
            nombreField.setText(profesor.getNombre());
            apellidosField.setText(profesor.getApellidos());
        } else {
            nombreField.setText("");
            apellidosField.setText("");
        }
    }

    private void saveData() {
        if (profesor == null) {
            profesor = new Profesor();
        }
        profesor.setNombre(nombreField.getText());
        profesor.setApellidos(apellidosField.getText());
    }
}

Este enfoque modular y organizado nos permite gestionar de forma sencilla y clara la información de profesores, facilitando la extensión y mantenimiento del sistema.

Lista de reproducción
  1. 1
    Presentación de JDBC
    4 minutos
  2. 2
    Instalando MySQL
    7 minutos
  3. 3
    Creando tablas
    9 minutos
  4. 4
    Agregando el driver JAR
    7 minutos
  5. 5
    Estableciendo la conexión
    8 minutos
  6. 6
    Statement y ResultSet
    9 minutos
  7. 7
    Bobby Tables y PreparedStatement
    8 minutos
  8. 8
    Transacciones y MySQL
    6 minutos
  9. 9
    Transacciones, commits y rollbacks (parte 1)
    7 minutos
  10. 10
    Transacciones, commits y rollbacks (parte 2)
    6 minutos
  11. 11
    Ejemplo: Crear modelos
    9 minutos
  12. 12
    Ejemplo: Crear los DAO (parte 1)
    10 minutos
  13. 13
    Ejemplo: Crear los DAO (parte 2)
    12 minutos
  14. 14
    Ejemplo: Crear los DAO (parte 3)
    13 minutos
  15. 15
    Ejemplo: DAO Manager
    12 minutos
  16. 16
    Ejemplo: CRUD Alumnos (parte 1)
    15 minutos
  17. 17
    Ejemplo: CRUD Alumnos (parte 2)
    14 minutos
  18. 18
    Ejemplo: CRUD Alumnos (parte 3)
    13 minutos
  19. 19
    Ejemplo: CRUD Profesores
    25 minutos
  20. 20
    Ejemplo: CRUD Asignaturas
    alrededor de 1 hora
  21. 21
    Ejemplo: Login (final adelantado)
    17 minutos
  22. 22
    Conectar a PostgreSQL en Java con JDBC
    8 minutos
  23. 23
    Conectar a PostgreSQL en Kotlin con JDBC
    7 minutos
  24. 24
    Conectar a PostgreSQL en Java con JDBC (con NetBeans)
    10 minutos