BBDD&POO

Bases de Datos y
Programación Orientada a Objetos.

Curso: 2019/20. Parte POO
Máster en Modelización Matemática, Estadística y Computación

You can see this page translated into english by Google. Vous pouvez voir cette page traduite en français par Google.
(optimizado para Chrome)

Calendario

Octubre
LMMJV
[1]7
12..14 & 17..19
(0.22 & 0.21)
8
15..17..19
(0.21)
9
12..14
(0.22)
1011
[2]14
15..-17
(0.21)
15161718
[3]2122232425
[4]28293031 
Noviembre
LMMJV
[4]    1
[5]4
17..19
(0.21)
5
15..17
(0.21)
6
15..17..19
(0.21)
7
17..19
(0.21)
8
[6]1112131415
[7]181920
15..17
(0.21)
2122
[8]2526272829
Diciembre
LMMJV
[9]23456
[10]9
15..17
(0.21)
1011
15..17
(0.21)
12
17..19
(0.20)
13
[11]1617181920
 N  no lectivo,  N  fiesta,  N  estudio,  N  exámenes, NN BBDD, NN POO, nuestra clase.

Programa

TemaContenido
0INTRODUCCIÓN
1ELEMENTOS BÁSICOS DEL LENGUAJE
- Introducción.
- Tipos de datos, identificadores y literales.
- Operadores.
- Sentencias.
2ELEMENTOS RELACIONADOS CON LA ORIENTACIÓN A OBJETO
- Objetos y clases.
- Estructura de la definición de una clase.
  - Herencia.
     - Encapsulamiento (ámbitos de accesibilidad).
    - El bloque static y los atributos static y final.
     - Instanciación, inicialización y eliminación de objetos.
     - Clases y métodos abstractos.
     - Interfaces.
     - Polimorfismo.
     - Enumeraciones.
   - Clases dentro de clases y métodos. Clases anónimas.
   - Arrays.
3MECANISMO DE TRATAMIENTO DE EXCEPCIONES Y ERRORES
- Introducción.
   - Control de excepciones.
   - Generación excepciones.
   - Definición de nuevas excepciones.
- Aserciones
4BIBLIOTECA DE CLASES (clases de interés)
- Los paquetes java.lang y java.util. Genéricos y colecciones.
- Clases para entradas y salidas
5CAPAS DE APLICACIÓN Y BASES DE DATOS
- El navegador como capa de cliente (HTML, javascript) y la capa de presentación (JSPs).
- Acceso a bases de datos.

Evaluación

Aquí el enunciado del ejercicio, y aquí el javadoc de una solución.

Entrega de ejercicios en primera convocatoria: 13/1/2020; en segunda convocatoria: 5/7/2020.

Método de entrega:

Nota: antes de entregar el ejercicio hay que -por lo menos- "adecentar" el código fuente. Lo correcto sería incluso escribir la documentación embebida, pero sin duda hay que dejar el código "listo para revista": eliminar elementos abandonados, lineas de código de prueba, etc...

Desarrollo

NOVIEMBRE

Miércoles 6 de noviembre de 2019 (4h. 15:00..19:00)

TEMA 0 - Introducción

Estas introducciones pretenden dar una aproximación muy general a la Orientación a Objetos, y poner en contexto y justificar el uso de Java como lenguaje para concretar. Son en cierto modo prescindibles ya que todo ello se concreta más adelante.

Sí que aparecen algunos datos/ideas/conceptos relacionados y de interés que no se volverán a tocar, pero también pueden obviarse si nos centramos en el objetivo de entender la Orientación a Objetos. Principalmente me estoy refiriendo con esto a las Máquinas Virtuales (la JVM -Java Virtual Machine- en nuestro caso y como precursora), y al patrón MVC de "estructuración" de aplicaciones

Las últimas páginas se dedican a las herramientas que usaremos, y su justificación y acceso para descargarlas se encuentra en el texto que se muestra a continuación.

Necesitaréis el entorno de desarrollo de Java (JDK - Java Development Kit). Ha salido hace un mes la versión JDK13 (recientemente se ha establecido en 6 meses el periodo de publicación de versiones -una técnica de desarrollo acual-). De todos modos, aunque nos hagamos con esta versión, trabajaremos "a nivel" de la versión 7, porque todas las actualizaciones desde entonces caen fuera del ámbito de este curso (en realidad, la versión 8 sería la mejor opción ahora mismo, pero sus capacidades funcionales nos pueden confundir en el IDE del que hablamos más abajo). Descargad e instalad de aquí.

Además usaremos como entorno de ayuda al desarrollo (IDE) el de Netbeans (es el que mejor se adapta a nuestras necesidades siendo 100% gratuito). Descargad de aquí la última versión (11.2).

TEMA 1 - Elementos básicos del lenguaje

En este tema aprendemos todo lo necesario para programar en Java sin Orientación a Objetos (ignorando por el momento todo aquello que sí lo es y nos vemos obligados a incluir sin dominar). Para quien domine C encontrará más similitudes que diferencias (siempre a mejor). En general tampoco es muy diferente a programar en cualquier otro lenguaje imperativo. Es cuestión de "hacerse" con una sintaxis concreta.

Como puntos a destacar: la absoluta portabilidad de los tipos primitivos; algunos operadores no demasiado comunes: el ternario (cond ? exp1 : exp2), los incrementos y decrementos (++x, --x, x++, x--), los combinados (+=, -=, %=, etc.)

Como decíamos, hay ciertos elementos que se mencionan aquí aunque pertenecen al "mundo de los objetos" (operadores new e instanceof, o la sentencia throw) que se estudiarán más adelante

//Nos quedamos viendo la lista de operadores...

Jueves 7 de noviembre de 2019 (2h. 17:00..19:00)

//Continuamos donde lo dejamos...

El siguiente ejercicio lo dejamos planteado para resolverlo el próximo día en clase

Obtención del número Pi mediante aproximación por serie.

Se trata de calcular el número π con precisión de cuatro decimales mediante la serie:

La especificación de cuatro decimales hace referencia al criterio de parada en la suma de términos de la serie, no a la presentación de la solución, que se hará normalmente mediante System.out.println(.) y que nos mostrará un número de decimales que no podemos controlar por ahora.

Una solución: TBD

El siguiente ejercicio lo dejamos planteado "sin más", y veremos soluciones al finalizar el curso porque nos mostrará algunas capacidades "avanzadas" que nos permiten obtener más soluciones que las que están por ahora en nuestra mano.

Obtención de números Perfectos

Escriba una RUTINA que determine si un número dado es perfecto o no.

static boolean isPerfect(long n) {
            //TODO hacer lo necesario para que "isPerfect" retorne "true" o "false" si n es perfecto o no.
            }

Un número perfecto es un entero positivo igual a la suma de sus divisores propios. Los divisores propios de un entero positivo son todos sus divisores a excepción de sí mismo. (Ejemplo de número perfecto: el 6, porque sus divisores propios son 1, 2 y 3 y 6=1+2+3.)

Utilizando dicha rutina debera obtener una lista de números perfectos entre el 1 y el 100.000

Resultado de la ejecución:
6 = 1+2+3
28 = 1+2+4+7+14
496 = 1+2+4+8+16+31+62+124+248
8128 = 1+2+4+8+16+32+64+127+254+508+1016+2032+4064

Listado de Números Perfectos [pdf]

Una solución: TBD

TEMA 2 - Elementos relacionados con la Orientación a Objetos

En este tema encontramos los conceptos importantes de la Orientación a Objetos. Todos son importantes, pero hay que destacar la Herencia, y más aún el Polimorismo.

Miércoles 20 de noviembre de 2019 (2h. 15:00..17:00)

//Echamos un vistazo al ejercicio del cálculo de Pi, y continuamos donde lo dejamos con el tema 2...
... y llegamos hasta ver el polimorfismo

DICIEMBRE

Lunes 9 de diciembre de 2019 (2h. 15:00..17:00)

//Continuamos donde lo dejamos con el tema 2

TEMA 3 - Mecanismo de control de Excepciones y Errores

En este tema vemos una parte de Java que, siendo parte de la estructura básica del lenguaje, comienza a hacer uso de las capacidades que nos da la orientación a objetos. La gestión de errores obedece a un modelo de separación de caminos de éxito y resolución de problemas, que está soportada por el lenguaje mediante una sentencia específica así como por clases que heredan la capacidad de ser "arrojables"

TEMA 4 - Biblioteca de Clases

Hemos visto todo lo que se refiere al lenguaje (bueno, excepto el soporte puntual que da a un par de características con los términos "transient" y "volatil", las dos que nos quedan por marcar en el cuadro de palabras reservadas). A partir de aquí todo son bibliotecas. Como ya se ha mencionado, el elenguaje es absolutamente incapaz de hacer nada sin bibliotecas, y se han usado desde el primer instante (System.out.println("Hola mundo");).

Hemos de estudiar las clases imprescindibles, las de más frecuente uso, y las específicas para nuestros intereses particulares.

  • Un vistazo general a las bibliotecas
  • Material de biblioteca de uso general (java.lang y java.util)
    • Empezamos con Object, ha de tenerse en cuenta... siempre forma parte de nuestra herencia

... llegamos hasta ver el Object a falta de equals-hashcode-clone

Miercoles 11 de diciembre de 2019 (2h. 15:00..17:00)

//Continuamos donde lo dejamos con Object

  • Material de biblioteca de uso general (java.lang y java.util)
    • Empezamos con Object, ha de tenerse en cuenta... siempre forma parte de nuestra herencia
    • System, es la máquina sobre la que se ejecuta el programa...
    • Otras clases en java.lang, son básicas e interesantes. -Imagen resumen-
    • Clases en java.util, no son "imprescindibles", pero a poco que hagamos las necesitaremos.
    • Las colecciones (aplicable el for "iterativo" -es un patrón-)
      (en las colecciones se usan intensivamente los "Genéricos" aquí un "tutorial"
    • Algunas otras clase de interés en java.util (muy por encima):
      • Formatter (en java.util facilita métodos en String y en Streams de salida entre otras clases)
      • Scanner (en java.util pero muy usada con streams de entrada)
      • Pattern y Matcher(en java.util.regex -expresiones regulares- facilita métodos en String y otras clases)
  • Material de biblioteca de uso específico (sólo java.IO en nuestro caso) -Imagenes resumen: 1, 2, 3-
    • Un vistazo general en pizarra:
      • los Streams soportados por las clases de cuatro sub-árboles del árbol de herencia.
      • El patrón "Wrapper".(Patrones en Wikipedia)
    • Otras clases File, RandomAccessFile
    • El paquete java.nio.file aporta más material de IO para trabajo con ficheros

... llegamos a ver ina introducción mínima a IO explicando el patrón Wrapper

Jueves 12 de diciembre de 2019 (2h. 17:00..19:00)

//Continuamos con una visión muy rápida de IO para pasar a hacer un ejercicio completo.

  • Antes, (también muy rápidamente) sobre capas y acceso a base de datos (Es necesario el driver JDBC para MySQL)
  • Procesaremos unos ficheros de texto con alineamientos fonéticos de voz y actas de las sesiones del Parlamento Vasco de los días: 1, 11, 14, 15 de diciembre de 2017. No es preciso "bajarlos", accederemos a ellos directamente desde el programa.
    Para montar la base de datos (tan sólo una tabla) usaremos el siguiente script:
    DROP DATABASE IF EXISTS actaspv;
    CREATE DATABASE actaspv;
    USE actaspv;
    CREATE TABLE estadisticas (
      `id` VARCHAR(8) NOT NULL,
      `numPalabras` INT NOT NULL,
      `validas` INT NOT NULL,
      `media` DOUBLE NOT NULL,
      `desviacionTipica` DOUBLE NOT NULL,
      PRIMARY KEY (`id`),
      UNIQUE INDEX `id_UNIQUE` (`id` ASC));
Una vez terminadas las clases...
  • El tiempo ha sido muy excaso... algo que quedó pendiente fue echar un vistazo a diferentes soluciones al problema de los números Perfectos. He desbloqueado la solución para que podais verla y ejecutar el proyecto. Creo que os puede resultar interesante
  • En un par de días os pondré, en la sección de Evaluación de esta página, el enunciado de un ejercicio a realizar para la evaluación del curso
  • Hemos desarrollado en clase el ejercicio final para procesar información de los ficheros remotos y enviar los resultados a la base de datos, pero nos ha faltado tiempo para corregir un error final. Sólo era necesario 1 minuto (pero eso no era previsible). El error obtenido decía
    Exception in thread "main" java.sql.SQLException: Column count doesn't match value count at row 1
    así que el número de datos (columnas) no coincide en la query sql con la tabla de la base de datos, por lo que hay que ver qué estamos enviando, es decir mostrar la query por pantalla:
    Teníamos esto
    public static void main(String[] args) throws IOException, SQLException {
           PVFile f = new PVFile("http://gtts.ehu.es/German/Docencia/assets/20171201.txt");
           con.createStatement().executeUpdate(
                   String.format(
                   "insert into estadisticas (id, numPalabras, validas, media,desviacionTipica) values (%s, %d, %d, %.3f, %.3f)",
                   "20171201", f.getNumeroDePalabras(), f.getNumeroDePalabrasValidas(), f.media(), f.desviacion())
           );
     }
                    
    y lo que hacemos es construir la query con antelación, para mostrarla en la consola antes de enviarla a la base de datos
    public static void main(String[] args) throws IOException, SQLException {
           PVFile f = new PVFile("http://gtts.ehu.es/German/Docencia/assets/20171201.txt");
           String query = String.format(
                   "insert into estadisticas (id, numPalabras, validas, media,desviacionTipica) values (%s, %d, %d, %.3f, %.3f)",
                   "20171201", f.getNumeroDePalabras(), f.getNumeroDePalabrasValidas(), f.media(), f.desviacion()
           );
           System.out.println(query);
           con.createStatement().executeUpdate(query);
     }
                    
    Lo que observamos es esto:
    insert into estadisticas (id, numPalabras, validas, media,desviacionTipica) values (20171201, 35892, 28287, 0,085, 0,052)
    ...osea que el método "format" de String (el objeto de clase Formatter que utiliza internamente) está configurado de tal modo que escribe el separador de decimales como una coma (está configurado localmente, se comporta como es nuestra costumbre) y eso supone un problema con la sintaxis de SQL.
    Podríamos adoptar una solución ad-hoc con lo que ya sabriamos hacer, como reemplazar comas por puntos antes de insertar los decimales en la query, pero la solución correcta será indicarle al formateador que considere las "costumbres locales" de un lugar donde los decimales se escriban con puntos (p.ej. U.S.). Para eso esta la clase "Locale", que contiene constantes como "Locale.US" que es la que nos interesa para obtener el resultado buscado.
    public static void main(String[] args) throws IOException, SQLException {
           PVFile f = new PVFile("http://gtts.ehu.es/German/Docencia/assets/20171201.txt");
           con.createStatement().executeUpdate(
                   String.format(Locale.UK,
                   "insert into estadisticas (id, numPalabras, validas, media,desviacionTipica) values (%s, %d, %d, %.3f, %.3f)",
                   "20171201", f.getNumeroDePalabras(), f.getNumeroDePalabrasValidas(), f.media(), f.desviacion())
           );
     }
                    
    Si queremos hacer que en todo momento el comportamiento "local" sea el propio de UK (p.ej.) y evitar indicarlo cada vez que apliquemos un formato, podemos establecerlo inicialmente por defecto (ojo que afecta a más cosas, como por ejemplo el formateo de las fechas).
    public static void main(String[] args) throws IOException, SQLException {
           Locale.setDefault(Locale.UK);
           PVFile f = new PVFile("http://gtts.ehu.es/German/Docencia/assets/20171201.txt");
           con.createStatement().executeUpdate(
                   String.format(
                   "insert into estadisticas (id, numPalabras, validas, media,desviacionTipica) values (%s, %d, %d, %.3f, %.3f)",
                   "20171201", f.getNumeroDePalabras(), f.getNumeroDePalabrasValidas(), f.media(), f.desviacion())
           );
     }
                    
    Una vez que ya tenemos todo funcionando, podemos hacer que nuestro programa procese los cuatro ficheros mediante un ciclo "for" del siguiente modo:
    public static void main(String[] args) throws IOException, SQLException {
        Locale.setDefault(Locale.UK);
        String[] filenames = {"20171201", "20171211", "20171214", "20171215"};
        for (String filename : filenames) {
            PVFile f = new PVFile("http://gtts.ehu.es/German/Docencia/assets/"+filename+".txt");
            con.createStatement().executeUpdate(
                    String.format(
                           "insert into estadisticas (id, numPalabras, validas, media,desviacionTipica) values (%s, %d, %d, %.3f, %.3f)",
                            filename, f.getNumeroDePalabras(), f.getNumeroDePalabrasValidas(), f.media(), f.desviacion())
                    );
        }
    }
    
    O un poco más directamente:
    public static void main(String[] args) throws IOException, SQLException {
        Locale.setDefault(Locale.UK);
        for (String filename : new String[]{"20171201", "20171211", "20171214", "20171215"}) {
            PVFile f = new PVFile("http://gtts.ehu.es/German/Docencia/assets/"+filename+".txt");
            con.createStatement().executeUpdate(
                    String.format(
                            "insert into estadisticas (id, numPalabras, validas, media,desviacionTipica) values (%s, %d, %d, %.3f, %.3f)",
                            filename, f.getNumeroDePalabras(), f.getNumeroDePalabrasValidas(), f.media(), f.desviacion())
                    );
        }
    }
    Aquí está el proyecto en formato "zip"

Extras

"Not So Frequently Asked Questions"
En ocasiones alguna pregunta nada habitual puede ser de interés general....