Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Modelo Vista Controlador en Java y MySQL. Nivel Básico - Kadum
Modelo Vista Controlador en Java y MySQL. Nivel Básico - Kadum
Nivel
Básico
18 noviembre, 2014 ◆ 16 comentarios
Conoces los fundamentos de la programación orientada a objetos y has trabajado con bases de
datos. También has implementado interfaces para interactuar con los usuarios de tus
aplicaciones. Pero hasta ahora lo has hecho sin separar metodológicamente cada uno de estos
componentes. Si quieres ir un paso más allá y mejorar en arquitectura software, has llegado al
lugar adecuado.
En este ejemplo se tratarán las directrices básicas para afrontar metodología MVC (Modelo –
Vista – Controlador), un modelo maduro que ha demostrado su validez a lo largo de los años en
todo tipo de aplicaciones y sobre multitud de lenguajes y plataformas de desarrollo.
En concreto, en esta guía rápida se empleará como base de datos MySQL y como lenguaje de
programación, Java.
Supuesto Práctico
Se tendrá una base de datos con una tabla donde se almacenará la información de los clientes
de nuestro negocio. Desde una interfaz gráfica, un usuario podrá listar, añadir, modificar o
eliminar los diversos clientes.
Tanto la vista como el controlador estarán implementados en Java mediante Eclipse. Sin
embargo, debido a su simplicidad, el modelo se implementará en MySQL. Se hará uso
de procesos almacenados (stored procedures) en la base de datos.
Debido a que el proyecto Java accederá a una base de datos MySQL, se debe usar un fichero
.jar que se encargará de registrar y emplear el driver adecuado para tal conexión. El fichero se
puede descargar a través del siguiente enlace (en inglés).
Los temas a tratar, son los siguiente:
Una vez abierto Eclipse, se debe acceder a File > New > Java Proyect
En el cuadro de diálogo que aparece, se indica el Project name kadumMVC y se
selecciona JavaSE-1.7 como execution enviroment JRE.
Crear proyecto KadumMVC
Una vez creado el proyecto, se procederá a la construcción de las diversas clases que
compondrán nuestro proyecto. En los siguientes apartados, se describirá cómo llevar a cabo
esta tarea. Las clases que se construirán serán:
Codificación de la clase Bd
La clase Bd se encargará de realizar la conexión a nuestro servidor. Se tendrán dos métodos, el
constructor y un método que devolverá un objeto de la clase Connection. Dicho objeto se
empleará en la clase Controller.
Dentro del proyecto creado, se accede al menú File > New > Class
En el cuadro de diálogo que aparece, tras escribir el nombre de la clase Bd, se pulsa sobre el
botón Finish.
Clase Bd
1 package kadumMVC;
2
3 import java.sql.Connection;
4 import java.sql.DriverManager;
5 import java.sql.SQLException;
6
7 public class Bd {
8 private String maquina = "localhost
9 private String usuario = "root";
10 private String clave = "";
11 private int puerto = 3306;
12 private String servidor = "";
13 private static Connection conexion = nu
14
15 //CONSTRUCTOR
16 //Recibe el nombre de la base de datos
17 Bd(String baseDatos){
18 this.servidor="jdbc:mysql://"+this.m
19 this.puerto+"/"+base
20
21 //Registrar el driver
22 try {
23 Class.forName("com.mysql.jdbc.D
24 } catch (ClassNotFoundException e) {
25 System.err.println("ERROR AL REG
26 System.exit(0); //parar la ejecu
27 }
28
29 //Establecer la conexión con el serv
30 try {
31 conexion = DriverManager.getConn
32 this.usuario, this.c
33 } catch (SQLException e) {
34 System.err.println("ERROR AL CON
35 System.exit(0); //parar la ejecu
36 }
37 System.out.println("Conectado a "+ba
38 }
39
40 //Devuelve el objeto Connection que se u
41 public static Connection getConexion() {
42 return conexion;
43 }
44
45 }
Se observa que se realizará la conexión a localhost a través del puerto 3306, mediante el
usuario root, el cual no tiene contraseña. En el momento de la creación de un objeto de la clase
Bd, se le indicará el nombre de la base de datos a la que se desea conectar.
Ventana Inicial
Componentes
Componentes
Todos los componentes irán colocados sobre un objeto JPanel.
Las tres etiquetas se definirán como objetos de la clase JLabel.
Los tres cuadros de texto se definirán como objetos de la clase JTextField.
Los tres botones se definirán como objetos de la clase JButton.
Para la construcción de la tabla, se emplearán varios elementos:
Un objeto JScrollPane.
En el interior del objeto JScrollPane, se colocará un objeto de la clase JTable, el cual
representa la tabla propiamente dicha.
La tabla se construirá a partir de un elemento JDefaultTableModel, el cual unirá la cabecera de
la tabla con el cuerpo de la tabla propiamente dicho.
Para la cabecera de la tabla, se empleará un array de cadenas de caracteres – String[].
Para el cuerpo propiamente dicho, se empleará una matriz de Object – Object[][].
Los dos primeros parámetros (lado, delComponente) hacen referencia a uno de los 4 lados de
un componente en concreto.
El tercer parámetro (separado) indica la separación en píxeles que se desea tener respecto a…
Es aquí donde entran en función el cuarto y quinto parámetro.
Los dos últimos parámetros (delLado, deOtroComponente), indican respecto a qué lado de qué
componente se desea realizar la separación indicada.
El valor para los parámetros 1 y 4 podrán ser NORTH, SOUTH, EAST, WEST.
El valor para la separación podrá ser positivo o negativo. Cuando el 4 parámetro sea SOUTH o
WEST, en nuestro caso, las cantidades serán negativas, ya que se toma como referencia el
contenedor.
Para más información de la función putConstraint, visitar el enlace siguiente en inglés:
Por simplicidad, todos los componentes se separarán una cantidad de píxeles en función del
contenedor principal.
Posición – JLabels
La interfaz debe comunicarse con el futuro controlador (clase Controller) cuando el usuario
pulse sobre los botones Añadir, Borrar o Editar, además de cuando pulse sobre una fila de la
tabla.
Para los botones se empleará el método addActionListener. Para que el controlador pueda
distinguir qué botón se ha pulsado, también se empleará el método setActionCommand.
Para la tabla se usará el método addMouseListener. El controlador actuará cuando se haga
click sobre una fila.
Código
Dentro del proyecto creado, se accede al menú File > New > Class
En el cuadro de diálogo que aparece, tras escribir el nombre de la clase View, se seleccionará
la superclass.
Se debe pulsar sobre el botón Browser asociado a Superclass. En el cuadro de diálogo que
aparece, se escribe JFrame y se selecciona la sugerencia aportada por Eclipse.
Por último, se pulsa sobre el botón Finish.
Clave View
1 package kadumMVC;
2
3 import javax.swing.JFrame;
4 import javax.swing.JPanel;
5 import javax.swing.SpringLayout;
6 import javax.swing.JLabel;
7 import javax.swing.JTextField;
8 import javax.swing.JButton;
9 import javax.swing.JScrollPane;
10 import javax.swing.table.DefaultTableModel;
11 import javax.swing.JTable;
12
13 public class View extends JFrame {
14
15 /**************** ATRIBUTOS ***********
16 //CONTENEDOR PRINCIPAL
17 private JPanel contenedor;
18
19 //DEFINICIÓN DE LAS ETIQUETAS
20 private JLabel lblNombre;
21 private JLabel lblApellido;
22 private JLabel lblNIF;
23
24 //DEFINICIÓN DE LOS CUADROS DE TEXTO
25 protected JTextField txtNombre;
26 protected JTextField txtApellido;
27 protected JTextField txtNIF;
28
29 //DEFINICIÓN DE LOS BOTONES
30 protected JButton btnAdd;
31 protected JButton btnDel;
32 protected JButton btnUpd;
33
34 //DEFINICIÓN DE LOS OBJETOS PARA LA TAB
35 private JScrollPane scroll; //Panel de
36 protected Object[][] datos; //Cuerpo de
37 protected String[] cabecera; //Cabec
38 protected DefaultTableModel dtm;//Unión
39 protected JTable tabla; //Tabla propiam
40
41 /**************** MÉTODOS *************
42 //CONSTRUCTOR
43 View(){
44 //Métodos de la JFrame
45 setBounds(100, 100, 450, 300);//Def
46 setTitle("GESTIÓN DE CLIENTES - KAD
47 setDefaultCloseOperation(EXIT_ON_CL
48
49 //CREAR EL CONTENEDOR PRINCIPAL Y A
50 contenedor = new JPanel();
51 getContentPane().add(contenedor);
52
53 //INDICAR QUE SE QUIERE USAR SPRING
54 SpringLayout sp = new SpringLayout(
55 contenedor.setLayout(sp);
56
57 //Vamos al lío
58 /**************** BOF ETIQUETAS vv
59 //ETIQUETA NOMBRE
60 lblNombre = new JLabel("Nombre:");
61 contenedor.add(lblNombre); //A
62 sp.putConstraint(SpringLayout.NORTH
63 SpringLayout.NORTH,
64 sp.putConstraint(SpringLayout.WEST,
65 SpringLayout.WEST,
66 //ETIQUETA APELLIDOS
67 lblApellido = new JLabel("Apellidos
68 contenedor.add(lblApellido);
69 sp.putConstraint(SpringLayout.NORTH
70 SpringLayout.NORTH,
71 sp.putConstraint(SpringLayout.WEST,
72 SpringLayout.WEST,
73 //ETIQUETA NIF
74 lblNIF = new JLabel("NIF:");
75 contenedor.add(lblNIF);
76 sp.putConstraint(SpringLayout.NORTH
77 SpringLayout.NORTH,
78 sp.putConstraint(SpringLayout.WEST,
79 SpringLayout.WEST,
80 /**************** EOF ETIQUETAS ^^
81
82 /**************** BOF CUADROS DE T
83 //CUADRO DE TEXTO PARA EL NOMBRE
84 txtNombre = new JTextField();
85 contenedor.add(txtNombre);
86 sp.putConstraint(SpringLayout.NORTH
87 SpringLayout.NORTH,
88 sp.putConstraint(SpringLayout.WEST,
89 SpringLayout.WEST,
90 sp.putConstraint(SpringLayout.EAST,
91 SpringLayout.WEST,
92 //CUADRO DE TEXTO PARA EL NIF
93 txtApellido = new JTextField();
94 contenedor.add(txtApellido); //a
95 sp.putConstraint(SpringLayout.NORTH
96 SpringLayout.NORTH,
97 sp.putConstraint(SpringLayout.WEST,
98 SpringLayout.WEST,
99 sp.putConstraint(SpringLayout.EAST,
100 SpringLayout.WEST,
101 //CUADRO DE TEXTO PARA LOS APELLIDO
102 txtNIF = new JTextField();
103 contenedor.add(txtNIF);
104 sp.putConstraint(SpringLayout.NORTH
105 sp.putConstraint(SpringLayout.WEST,
106 sp.putConstraint(SpringLayout.EAST,
107 /**************** EOF CUADROS DE T
108
109 /**************** BOF TABLA vvvvvv
110 scroll = new JScrollPane();
111 cabecera = new String[] {"ID","N
112 dtm = new DefaultTableModel
113 tabla = new JTable(dtm);
114 scroll.setViewportView(tabla);
115 //y ahora se coloca el scrollpane.
116 contenedor.add(scroll); //añadir al
117 sp.putConstraint(SpringLayout.NORTH
118 SpringLayout.NORTH,
119 sp.putConstraint(SpringLayout.WEST,
120 SpringLayout.WEST,
121 sp.putConstraint(SpringLayout.EAST,
122 SpringLayout.EAST,
123 sp.putConstraint(SpringLayout.SOUTH
124 SpringLayout.SOUTH,
125 /**************** EOF TABLA ^^^^^^^
126
127 /**************** BOF BOTONES vvvvv
128 //BOTÓN AÑADIR
129 btnAdd = new JButton("Añad
130 contenedor.add(btnAdd);
131 sp.putConstraint(SpringLayout.SOUTH
132 SpringLayout.SOUTH,
133 sp.putConstraint(SpringLayout.WEST,
134 SpringLayout.WEST,
135 //BOTÓN BORRAR
136 btnDel = new JButton("Borr
137 contenedor.add(btnDel);
138 sp.putConstraint(SpringLayout.SOUTH
139 SpringLayout.SOUTH,
140 sp.putConstraint(SpringLayout.WEST,
141 SpringLayout.WEST,
142 //BOTÓN MODIFICAR
143 btnUpd = new JButton("Edit
144 contenedor.add(btnUpd);
145 sp.putConstraint(SpringLayout.SOUTH
146 SpringLayout.SOUTH,
147 sp.putConstraint(SpringLayout.WEST,
148 SpringLayout.WEST,
149 /**************** EOF BOTONES ^^^^^
150
151 //Se hace visible la ventana
152 setVisible(true);
153
154 }
155
156 public void conectaControlador( Contro
157
158 btnAdd.addActionListener(c);
159 btnAdd.setActionCommand("INSERTAR")
160
161 btnDel.addActionListener(c);
162 btnDel.setActionCommand("BORRAR");
163
164 btnUpd.addActionListener(c);
165 btnUpd.setActionCommand("MODIFICAR"
166
167 tabla.addMouseListener(c);
168 //sólo se permite pulsar una fila a
169 tabla.setSelectionMode(ListSelectio
170 }
171 }
Se observa que en el constructor, los objetos que se construyen siguen cierto patrón. A modo
de detalle, nos centramos en la construcción del cuadro de texto para el nombre:
1 contenedor.add(txtNombre);
1 sp.putConstraint(SpringLayout.NORTH, txtNombr
2 SpringLayout.NORTH, conte
1 sp.putConstraint(SpringLayout.WEST, txtNombre
2 SpringLayout.WEST, conten
1 sp.putConstraint(SpringLayout.EAST, txtNombre
2 SpringLayout.WEST, conten
En el método conectaControlador, se indica que al pulsar los botones se desea que se realice
una acción, que vendrá definida en la clase Controller.
Para que Controller sepa qué botón se ha pulsado, se emplea el método setActionCommand.
Cuando el usuario interactúe con la Vista, desencadenará la ejecución de ciertos eventos que
serán recogidos por el Controlador y lanzados al Modelo. Cuando el modelo devuelva la
información, se actualizará la interfaz. Por ese motivo, la clase controlador tendrá un objeto de
la clase View.
Puesto que debe codificar eventos de ratón y de acción, la clase implementará dos interfaces
de Java, así se simulará la herencia múltiple en Java. Las interfaces que se implementarán
serán: ActionListener, MouseListener
Nota: No se debe confundir el concepto de interfaz de Java (se podría considerar como una
clase abstracta) con la idea de interfaz gráfica de usuario (cuya creación se ha llevado a
cabo en el apartado anterior).
actionPerformed
Este método se ejecutará cuando el usuario pulse sobre alguno de los tres botones de la
Ventana, tal y como se especificó en el método conectaControlador de la clase View.
En función del comando que se ejecute:
INSERTAR
BORRAR
MODIFICAR
mouseClicked
Este método se ejecutará cuando el usuario pulse sobre una fila de la tabla.
Código
Dentro del proyecto creado, se accede al menú File > New > Class
En el cuadro de diálogo que aparece, tras escribir el nombre de la clase Controller, se
seleccionarán las interfaces a implementar.
Se debe pulsar sobre el botón Add asociado a Interfaces. En el cuadro de diálogo que aparece,
se buscarán y añadirán ActionListener y MouseListener.
Por último, se pulsa sobre el botón Finish.
Clase Controller
1 package kadumMVC;
2
3 import java.awt.event.ActionEvent;
4 import java.awt.event.ActionListener;
5 import java.awt.event.MouseEvent;
6 import java.awt.event.MouseListener;
7 import java.sql.CallableStatement;
8 import java.sql.ResultSet;
9 import java.sql.SQLException;
10 import java.util.Vector;
11
12 public class Controller implements ActionLi
13 MouseLi
14 private View view;
15
16 //CONSTRUCTOR
17 Controller( View view ){
18 this.view = view;
19 cargarTabla();
20 }
21
22 @Override
23 public void actionPerformed(ActionEvent
24 //Objeto para ejecutar los procedim
25 // en la base de datos
26 CallableStatement cs;
27
28 //COMANDO EJECTUADO
29 String comando = arg0.getActionCom
30
31 //Deberá coincidir con alguno de lo
32 // indicados en setActionCommand i
33 // clase View
34 switch (comando) {
35 case "INSERTAR":
36 try{
37 //Preparar la llamada
38 cs = Bd.getConexion()
39 "{CALL insertar
40 //Indicar qué informaci
41 // procedimiento
42 cs.setString(1,
43 this.view.txtNombre
44 cs.setString(2,
45 this.view.txtApelli
46 cs.setString(3,
47 this.view.txtNIF.ge
48 //Ejecutar el procedimi
49 cs.execute();
50 }catch (SQLException e) {
51 System.err.println("Err
52 }
53
54 break;
55
56 case "BORRAR":
57 //Recoger qué fila se ha pu
58 int filaPulsada = this.view
59 //Si se ha pulsado una fila
60 if(filaPulsada>=0){
61 //Se recoge el id de la
62 int identificador = (
63 try{
64 //Preparar la llama
65 cs = Bd.getConexio
66 "{CALL borrarCl
67 //Indicar qué infor
68 cs.setInt(1, identi
69 //Ejecutar el proce
70 cs.execute();
71 //System.out.printl
72 }catch (SQLException e)
73 System.err.println(
74 }
75 }
76
77 break;
78
79 case "MODIFICAR":
80 //Recoger qué fila se ha pu
81 filaPulsada = this.view.tab
82 //Si se ha pulsado una fila
83 if(filaPulsada>=0){
84 //Se recoge el id de la
85 int identificador = (
86 try{
87 //Preparar la llama
88 cs = Bd.getConexio
89 "{CALL modifica
90 //Indicar qué infor
91 cs.setInt(1, identi
92 cs.setString(2,
93 this.view.txtNo
94 cs.setString(3,
95 this.view.txtAp
96 cs.setString(4,
97 this.view.txtNI
98 //Ejecutar el proce
99 cs.execute();
100 //System.out.printl
101 }catch (SQLException e)
102 System.err.println(
103 }
104 }
105 break;
106
107 default:
108 System.err.println("Comando
109 break;
110 }
111 //limpiar el formulario
112 limpia();
113
114 //refrescar la tabla
115 cargarTabla();
116 }
117
118 //Método para limpiar los campos de la
119 private void limpia(){
120 this.view.txtNombre.setText("");
121 this.view.txtApellido.setText("");
122 this.view.txtNIF.setText("");
123 }
124
125 //Método que recarga los datos de la ta
126 // en la tabla de la clase View
127 protected void cargarTabla(){
128 //Objeto para ejecutar los procedim
129 CallableStatement cs;
130 //Objeto para recoger los datos dev
131 ResultSet rs;
132 //Objeto para recorrer el resultado
133 // añadirlo a la tabla definida en
134 Vector<Object> fila;
135
136 //Limpiar los datos de la tabla
137 for(int i=this.view.dtm.getRowCount
138 this.view.dtm.removeRow(i-1);
139 }
140
141 //Cargar datos en la tabla
142 try {
143 //Preparar la llamada
144 cs = Bd.getConexion().prepareC
145 "{CALL getClien
146 //Ejecutarla y recoger el resul
147 rs = cs.executeQuery();
148 //Recorrer el resultado
149 while(rs.next()){
150 //Añadir registro a registr
151 fila = new Vector<Object
152 fila.add(rs.getInt("id"));
153 fila.add(rs.getString("nomb
154 fila.add(rs.getString("nif"
155 //Añadir el vector a la tab
156 this.view.dtm.addRow(fila);
157 }
158
159 } catch (SQLException e) {
160 System.err.println("Error al CA
161 }
162 }
163
164 @Override
165 public void mouseClicked(MouseEvent arg
166 //Objeto para ejecutar los procedim
167 CallableStatement cs;
168 //Objeto para recoger los datos dev
169 ResultSet rs;
170
171 //Recoger qué fila se ha pulsadao e
172 int filaPulsada = this.view.tabla.g
173 //Si se ha pulsado una fila
174 if(filaPulsada>=0){
175 //Se recoge el id de la fila ma
176 int identificador= (int)this.vi
177 filaPulsada, 0)
178 try{
179 //Preparar la llamada
180 cs = Bd.getConexion().prep
181 "{CALL getClien
182 //Indicar qué información s
183 cs.setInt(1, identificador)
184 //Ejecutar el procedimiento
185 rs = cs.executeQuery();
186 //Cargar los datos devuelto
187 if(rs.next()){
188 this.view.txtNombre.set
189 this.view.txtApellido.s
190 this.view.txtNIF.setTex
191 }
192 //System.out.println(this.v
193 }catch (SQLException e) {
194 System.err.println("Error a
195 }
196 }
197 }
198
199 @Override
200 public void mouseEntered(MouseEvent arg
201 @Override
202 public void mouseExited(MouseEvent arg0
203 @Override
204 public void mousePressed(MouseEvent arg
205 @Override
206 public void mouseReleased(MouseEvent ar
207 }
En eclipse:
Dentro del proyecto creado, se accede al menú File > New > Class
En el cuadro de diálogo que aparece, tras escribir el nombre de la clase Principal, se marca el
checkbox correspondiente a public static void main
Por último, se pulsa sobre el botón Finish.
Clase Principal
1 package kadumMVC;
2
3 public class Principal {
4 public static void main(String[] args) {
5 //Invocar al constructor de la clase
6 new Bd("kadummvc");
7 //Crear un objeto de la clase View
8 View vista = new View();
9 //Crear un objeto de la clase Contro
10 Controller controlador = new Contro
11 //Vincular la vista y el controlado
12 vista.conectaControlador(controlado
13
14 }
15 }
Como nota, observar que se realiza la vinculación entre la clase Controller y View en dos
sentidos.
Se crea la base de datos kadummvc. Como se observa, es el mismo nombre que recibe como
parámetro de entrada la invocación al constructor Bd en la clase Principal.
Se crea la tabla cliente. Con los campos id, nombre, apellido y NIF
Una vez compilados los códigos en nuestra base de datos, sólo queda cruzar los dedos (:-) y
probar el proyecto.
Relación de ficheros
Base de Datos
Se debe acceder en Eclipse a la clase Principal que contiene la función main y ejecutarla,
pulsando la tecla F11.
Se mostrará un mensaje en la consola indicando que se ha conectado a la base de datos
kadummvc, tal y como se especificó en la creación del objeto bd dentro de la clase Principal.
Y aparecerá la ventana en las coordenadas 100, 100 con un tamaño de 450×300 tal y como se
especificó en el constructor de la clase View.
Ejecución
Añadir clientes
Se rellenan los campos de texto.
Rellenar campos
Se pulsa Añadir.
Se añadirá la información a la base de datos, se limpiarán los campos de texto y se reflejará en
la tabla el cliente insertado.
Insertado
Modificar clientes
Para modificar un cliente, se pulsa sobre la fila del registro a modificar. De esa forma, se cargan
los datos para ese cliente.
Se reescribe la información correctamente y se pulsa sobre Editar.
Seleccionar y editar
Borrado
Creación de un ejecutable
Una vez comprobada que la aplicación funciona según lo previsto, se lleva a cabo la
construcción del fichero ejecutable en Eclipse.
Ejecutable runnable
Tras pulsar Next, se mostrará un cuadro de diálogo donde se configura qué clase es la que
contiene el método main que interesa ejecutar. Dónde se desea almacenar el ejecutable y la
opción de incluir las bibliotecas necesarias en el fichero ejecutable.
Crear ejecutable (.jar)