├── .gitignore ├── README.md ├── Recursos └── cheat_sheet_java8.png ├── Soluciones ├── 01-Optional │ ├── .idea │ │ ├── .gitignore │ │ ├── description.html │ │ ├── encodings.xml │ │ ├── misc.xml │ │ ├── modules.xml │ │ └── project-template.xml │ ├── Optional.iml │ └── src │ │ └── es │ │ └── joseluisgs │ │ └── dam │ │ └── Main.java ├── 02-Formateadores │ ├── .idea │ │ ├── .gitignore │ │ ├── description.html │ │ ├── encodings.xml │ │ ├── misc.xml │ │ ├── modules.xml │ │ └── project-template.xml │ ├── KakaJava.iml │ └── src │ │ └── es │ │ └── joseluisgs │ │ └── dam │ │ └── Main.java ├── 03-BD-Relacional │ ├── .gitignore │ ├── .idea │ │ ├── .gitignore │ │ ├── compiler.xml │ │ ├── encodings.xml │ │ ├── jarRepositories.xml │ │ ├── misc.xml │ │ ├── uiDesigner.xml │ │ └── vcs.xml │ ├── docker │ │ ├── docker-compose.yml │ │ └── mariadb │ │ │ ├── Dockerfile │ │ │ └── sql │ │ │ └── init-db.sql │ ├── pom.xml │ ├── sql │ │ └── mapas.sql │ └── src │ │ └── main │ │ └── java │ │ └── es │ │ └── joseluisgs │ │ └── dam │ │ ├── App.java │ │ ├── database │ │ └── DataBaseManager.java │ │ └── model │ │ └── User.java ├── 04-MVC-Paises-BBDD-DI │ ├── .gitignore │ ├── SecuenciaPaises.iml │ ├── data │ │ └── backup.json │ ├── docker │ │ ├── docker-compose.yml │ │ └── mariadb │ │ │ ├── Dockerfile │ │ │ └── sql │ │ │ └── init-db.sql │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── es │ │ │ │ └── joseluisgs │ │ │ │ └── dam │ │ │ │ ├── Main.java │ │ │ │ ├── comparators │ │ │ │ ├── PaisCodigoComparator.java │ │ │ │ └── PaisNombreComparator.java │ │ │ │ ├── controllers │ │ │ │ ├── AcuerdoController.java │ │ │ │ ├── BackupManager.java │ │ │ │ ├── DataBaseManager.java │ │ │ │ └── PaisController.java │ │ │ │ ├── exceptions │ │ │ │ ├── AcuerdoException.java │ │ │ │ └── PaisException.java │ │ │ │ ├── models │ │ │ │ ├── Acuerdo.java │ │ │ │ ├── Backup.java │ │ │ │ ├── LineaAcuerdo.java │ │ │ │ └── Pais.java │ │ │ │ ├── repositories │ │ │ │ ├── CRUDRepository.java │ │ │ │ ├── acuerdos │ │ │ │ │ ├── AcuerdoRepository.java │ │ │ │ │ └── IAcuerdoRepository.java │ │ │ │ └── paises │ │ │ │ │ ├── IPaisRepository.java │ │ │ │ │ └── PaisRepository.java │ │ │ │ ├── services │ │ │ │ └── Storage │ │ │ │ │ ├── IStorage.java │ │ │ │ │ ├── IStorageBackup.java │ │ │ │ │ └── StorageBackupJsonFile.java │ │ │ │ ├── utils │ │ │ │ ├── ApplicationProperties.java │ │ │ │ ├── Console.java │ │ │ │ └── Formatter.java │ │ │ │ └── views │ │ │ │ └── PaisView.java │ │ └── resources │ │ │ ├── application.properties │ │ │ └── sql │ │ │ └── init-db.sql │ │ └── test │ │ ├── java │ │ └── es │ │ │ └── joseluisgs │ │ │ └── dam │ │ │ ├── MainTest.java │ │ │ ├── controllers │ │ │ ├── AcuerdoControllerMockTest.java │ │ │ ├── AcuerdoControllerTest.java │ │ │ ├── PaisControllerMockTest.java │ │ │ └── PaisControllerTest.java │ │ │ ├── repositories │ │ │ ├── acuerdos │ │ │ │ └── AcuerdoRepositoryTest.java │ │ │ └── paises │ │ │ │ └── PaisRepositoryTest.java │ │ │ └── utilities │ │ │ ├── DataBase.java │ │ │ └── DataDB.java │ │ └── resources │ │ ├── application.properties │ │ └── sql │ │ └── init-db.sql ├── 05-JavaLambdaFuncional │ ├── .idea │ │ ├── .gitignore │ │ ├── description.html │ │ ├── encodings.xml │ │ ├── misc.xml │ │ ├── modules.xml │ │ ├── project-template.xml │ │ └── uiDesigner.xml │ ├── JavaLambdaFuncional.iml │ └── src │ │ └── es │ │ └── joseluisgs │ │ └── dam │ │ ├── CalcImperativeA.java │ │ ├── CalcImperativeB.java │ │ ├── CalcImperativeC.java │ │ ├── ICalcFunctional.java │ │ ├── ICalcImperativeA.java │ │ ├── ICalcImperativeB.java │ │ ├── ICalcImperativeC.java │ │ └── Main.java ├── 06-JavaStreamAPI │ ├── .idea │ │ ├── .gitignore │ │ ├── description.html │ │ ├── encodings.xml │ │ ├── misc.xml │ │ ├── modules.xml │ │ └── project-template.xml │ ├── JavaStreamAPI.iml │ └── src │ │ └── es │ │ └── joseluisgs │ │ └── dam │ │ ├── Main.java │ │ └── Persona.java ├── 07-StreamEjemplos │ ├── .gitignore │ ├── .idea │ │ ├── .gitignore │ │ ├── description.html │ │ ├── encodings.xml │ │ ├── misc.xml │ │ ├── modules.xml │ │ ├── project-template.xml │ │ └── vcs.xml │ ├── 02-Stream.iml │ ├── data │ │ └── products.csv │ └── src │ │ └── es │ │ └── joseluisgs │ │ └── dam │ │ ├── ConsultasAlumnos.java │ │ ├── ConsultasCanciones.java │ │ ├── ConsultasProductos.java │ │ ├── Main.java │ │ ├── model │ │ ├── Alumno.java │ │ ├── Cancion.java │ │ └── Product.java │ │ └── utils │ │ └── Util.java ├── 08-MVC-Paises-BBDD-Optional-Functional │ ├── .gitignore │ ├── SecuenciaPaises.iml │ ├── data │ │ └── backup.json │ ├── docker │ │ ├── docker-compose.yml │ │ └── mariadb │ │ │ ├── Dockerfile │ │ │ └── sql │ │ │ └── init-db.sql │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── es │ │ │ │ └── joseluisgs │ │ │ │ └── dam │ │ │ │ ├── Main.java │ │ │ │ ├── controllers │ │ │ │ ├── AcuerdoController.java │ │ │ │ ├── BackupManager.java │ │ │ │ ├── DataBaseManager.java │ │ │ │ └── PaisController.java │ │ │ │ ├── exceptions │ │ │ │ ├── AcuerdoException.java │ │ │ │ └── PaisException.java │ │ │ │ ├── models │ │ │ │ ├── Acuerdo.java │ │ │ │ ├── Backup.java │ │ │ │ ├── LineaAcuerdo.java │ │ │ │ └── Pais.java │ │ │ │ ├── repositories │ │ │ │ ├── CRUDRepository.java │ │ │ │ ├── acuerdos │ │ │ │ │ ├── AcuerdoRepository.java │ │ │ │ │ └── IAcuerdoRepository.java │ │ │ │ └── paises │ │ │ │ │ ├── IPaisRepository.java │ │ │ │ │ └── PaisRepository.java │ │ │ │ ├── services │ │ │ │ └── Storage │ │ │ │ │ ├── IStorage.java │ │ │ │ │ ├── IStorageBackup.java │ │ │ │ │ └── StorageBackupJsonFile.java │ │ │ │ ├── utils │ │ │ │ ├── ApplicationProperties.java │ │ │ │ ├── Console.java │ │ │ │ └── Formatter.java │ │ │ │ └── views │ │ │ │ └── PaisView.java │ │ └── resources │ │ │ ├── application.properties │ │ │ └── sql │ │ │ └── init-db.sql │ │ └── test │ │ ├── java │ │ └── es │ │ │ └── joseluisgs │ │ │ └── dam │ │ │ ├── MainTest.java │ │ │ ├── controllers │ │ │ ├── AcuerdoControllerMockTest.java │ │ │ ├── AcuerdoControllerTest.java │ │ │ ├── PaisControllerMockTest.java │ │ │ └── PaisControllerTest.java │ │ │ ├── repositories │ │ │ ├── acuerdos │ │ │ │ └── AcuerdoRepositoryTest.java │ │ │ └── paises │ │ │ │ └── PaisRepositoryTest.java │ │ │ └── utilities │ │ │ ├── DataBase.java │ │ │ └── DataDB.java │ │ └── resources │ │ ├── application.properties │ │ └── sql │ │ └── init-db.sql ├── 09-AccidentesStream │ ├── .gitignore │ ├── .idea │ │ ├── .gitignore │ │ ├── compiler.xml │ │ ├── description.html │ │ ├── encodings.xml │ │ ├── jarRepositories.xml │ │ ├── libraries │ │ │ └── Maven__org_projectlombok_lombok_1_18_22.xml │ │ ├── misc.xml │ │ ├── modules.xml │ │ └── project-template.xml │ ├── AccidentesStream.iml │ ├── data │ │ └── accidentes.csv │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── es │ │ └── joseluisgs │ │ └── dam │ │ ├── Accidente.java │ │ ├── AccidentesController.java │ │ └── Main.java ├── 10-MVC-Paises-BBDD-Dagger-Lombok │ ├── .gitignore │ ├── SecuenciaPaises.iml │ ├── data │ │ └── backup.json │ ├── docker │ │ ├── docker-compose.yml │ │ └── mariadb │ │ │ ├── Dockerfile │ │ │ └── sql │ │ │ └── init-db.sql │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── es │ │ │ │ └── joseluisgs │ │ │ │ └── dam │ │ │ │ ├── DI │ │ │ │ ├── controllers │ │ │ │ │ └── controllers │ │ │ │ │ │ ├── AcuerdoControllerDI.java │ │ │ │ │ │ ├── BackupManagerDI.java │ │ │ │ │ │ └── PaisControllerDI.java │ │ │ │ └── modules │ │ │ │ │ ├── AcuerdoRepositoryModule.java │ │ │ │ │ ├── DataBaseManagerModule.java │ │ │ │ │ ├── PaisRepositoryModule.java │ │ │ │ │ └── StorageBackupModule.java │ │ │ │ ├── Main.java │ │ │ │ ├── controllers │ │ │ │ ├── AcuerdoController.java │ │ │ │ ├── BackupManager.java │ │ │ │ ├── DataBaseManager.java │ │ │ │ └── PaisController.java │ │ │ │ ├── exceptions │ │ │ │ ├── AcuerdoException.java │ │ │ │ └── PaisException.java │ │ │ │ ├── models │ │ │ │ ├── Acuerdo.java │ │ │ │ ├── Backup.java │ │ │ │ ├── LineaAcuerdo.java │ │ │ │ └── Pais.java │ │ │ │ ├── repositories │ │ │ │ ├── CRUDRepository.java │ │ │ │ ├── acuerdos │ │ │ │ │ ├── AcuerdoRepository.java │ │ │ │ │ └── IAcuerdoRepository.java │ │ │ │ └── paises │ │ │ │ │ ├── IPaisRepository.java │ │ │ │ │ └── PaisRepository.java │ │ │ │ ├── services │ │ │ │ └── Storage │ │ │ │ │ ├── IStorage.java │ │ │ │ │ ├── IStorageBackup.java │ │ │ │ │ └── StorageBackupJsonFile.java │ │ │ │ ├── utils │ │ │ │ ├── ApplicationProperties.java │ │ │ │ ├── Console.java │ │ │ │ └── Formatter.java │ │ │ │ └── views │ │ │ │ └── PaisView.java │ │ └── resources │ │ │ ├── application.properties │ │ │ └── sql │ │ │ └── init-db.sql │ │ └── test │ │ ├── java │ │ └── es │ │ │ └── joseluisgs │ │ │ └── dam │ │ │ ├── MainTest.java │ │ │ ├── controllers │ │ │ ├── AcuerdoControllerMockTest.java │ │ │ ├── AcuerdoControllerTest.java │ │ │ ├── PaisControllerMockTest.java │ │ │ └── PaisControllerTest.java │ │ │ ├── repositories │ │ │ ├── acuerdos │ │ │ │ └── AcuerdoRepositoryTest.java │ │ │ └── paises │ │ │ │ └── PaisRepositoryTest.java │ │ │ └── utilities │ │ │ ├── DataBase.java │ │ │ └── DataDB.java │ │ └── resources │ │ ├── application.properties │ │ └── sql │ │ └── init-db.sql └── 11-CRUD-SQLite-GSon │ ├── .gitignore │ ├── .idea │ ├── .gitignore │ ├── dataSources.xml │ ├── deployment.xml │ ├── inspectionProfiles │ │ └── Project_Default.xml │ ├── misc.xml │ ├── uiDesigner.xml │ └── vcs.xml │ ├── data │ └── personas.json │ ├── db │ └── personas.db │ ├── pom.xml │ └── src │ └── main │ └── java │ └── es │ └── joseluisgs │ └── dam │ ├── Main.java │ ├── controllers │ └── PersonasController.java │ ├── managers │ └── DataBaseManager.java │ ├── models │ └── Persona.java │ ├── repositories │ ├── CRUDRepository.java │ ├── IPersonasRepository.java │ └── PersonasRepository.java │ ├── services │ ├── Backup.java │ ├── BackupJSON.java │ └── IBackupJSON.java │ └── utils │ └── LocalDateAdapter.java └── UD09.pdf /.gitignore: -------------------------------------------------------------------------------- 1 | *.pptx 2 | .DS_Store 3 | /Ejercicios/*.docx 4 | upload.sh 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Programación - 09 Gestión de Bases de Datos mediante código 2 | 3 | Tema 09 Gestión de Bases de Datos mediante código. 1DAM. Curso 2021/2022. 4 | 5 | ![imagen](https://www.mindinventory.com/blog/wp-content/uploads/2019/10/Offshore-app-developer.png) 6 | 7 | ## Contenidos 8 | 1. Bases de datos Relacionales 9 | 2. El Desfase Objeto-Relacional 10 | 3. Acceso a Base de Datos Relacionales 11 | 4. CRUD con JDBC 12 | 5. El problema de Null y el tipo Optional 13 | 6. Procesando información en colecciones. API Stream y programación funcional 14 | 15 | 16 | ## Recursos 17 | - Twitter: https://twitter.com/joseluisgonsan 18 | - GitHub: https://github.com/joseluisgs 19 | - Web: https://joseluisgs.github.io 20 | - Discord: https://discord.gg/uv7GcytM 21 | - Aula Virtual: https://aulavirtual33.educa.madrid.org/ies.luisvives.leganes/course/view.php?id=245 22 | 23 | 24 | 25 | ## Autor 26 | 27 | Codificado con :sparkling_heart: por [José Luis González Sánchez](https://twitter.com/joseluisgonsan) 28 | 29 | [![Twitter](https://img.shields.io/twitter/follow/joseluisgonsan?style=social)](https://twitter.com/joseluisgonsan) 30 | [![GitHub](https://img.shields.io/github/followers/joseluisgs?style=social)](https://github.com/joseluisgs) 31 | 32 | ### Contacto 33 |

34 | Cualquier cosa que necesites házmelo saber por si puedo ayudarte 💬. 35 |

36 |

37 | 38 | 40 |    41 | 42 | 44 |    45 | 46 | 48 |    49 | 50 | 52 | 53 |

54 | -------------------------------------------------------------------------------- /Recursos/cheat_sheet_java8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joseluisgs/Programacion-09-2021-2022/188c0476c2f30e7149340dda33239a3df1488e4b/Recursos/cheat_sheet_java8.png -------------------------------------------------------------------------------- /Soluciones/01-Optional/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /Soluciones/01-Optional/.idea/description.html: -------------------------------------------------------------------------------- 1 | Simple Java application that includes a class with main() method -------------------------------------------------------------------------------- /Soluciones/01-Optional/.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Soluciones/01-Optional/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Soluciones/01-Optional/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Soluciones/01-Optional/.idea/project-template.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Soluciones/01-Optional/Optional.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Soluciones/01-Optional/src/es/joseluisgs/dam/Main.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam; 2 | 3 | import java.util.Optional; 4 | 5 | public class Main { 6 | 7 | public static void main(String[] args) { 8 | System.out.println("Hello Optional!"); 9 | sinOptional(); 10 | conOptional(); 11 | } 12 | 13 | private static void sinOptional() { 14 | // imaginamos que nos llega un null o no sabemos que es 15 | String nombre = null; 16 | // y se nos olvida el if... 17 | // System.out.println("Nombre: " + nombre.length()); 18 | // ponemos el if, o try catch por todos lados 19 | if (nombre != null) { 20 | System.out.println("Nombre: " + nombre.length()); 21 | } 22 | try { 23 | System.out.println("Nombre: " + nombre.length()); 24 | } catch (NullPointerException e) { 25 | System.out.println("puffff"); 26 | // throw new RuntimeException("No hay nombre"); 27 | } 28 | } 29 | 30 | public static void conOptional() { 31 | String nombre = null; 32 | Optional nombreOpt = Optional.ofNullable(nombre); 33 | // Podemos comrpbar si está presente o no 34 | if (nombreOpt.isPresent()) { 35 | System.out.println("Nombre: " + nombreOpt.get().length()); 36 | } 37 | // o si está vacío 38 | if (!nombreOpt.isEmpty()) { 39 | System.out.println("Nombre: " + nombreOpt.get().length()); 40 | } 41 | // Lo importante es que siempre que quiera usarlo necesito el get!! y si no 42 | // Puedo jugar con valores por defecto 43 | System.out.println("Nombre: " + nombreOpt.orElse("default").length()); 44 | // O lanzar una excepción controlada... 45 | // System.out.println("Nombre: " + nombreOpt.orElseThrow(() -> new RuntimeException("No hay nombre"))); 46 | Optional opt = Optional.of("DAM"); 47 | String name = opt.get(); 48 | System.out.println("Nombre: " + name); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Soluciones/02-Formateadores/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /Soluciones/02-Formateadores/.idea/description.html: -------------------------------------------------------------------------------- 1 | Simple Java application that includes a class with main() method -------------------------------------------------------------------------------- /Soluciones/02-Formateadores/.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Soluciones/02-Formateadores/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Soluciones/02-Formateadores/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Soluciones/02-Formateadores/.idea/project-template.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Soluciones/02-Formateadores/KakaJava.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Soluciones/02-Formateadores/src/es/joseluisgs/dam/Main.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam; 2 | 3 | import java.text.NumberFormat; 4 | import java.time.LocalDate; 5 | import java.time.LocalDateTime; 6 | import java.time.format.DateTimeFormatter; 7 | import java.time.format.FormatStyle; 8 | import java.util.Date; 9 | import java.util.Locale; 10 | import java.util.StringTokenizer; 11 | 12 | public class Main { 13 | 14 | public static void main(String[] args) { 15 | // write your code here 16 | double numero = 123_456.789; 17 | LocalDateTime fecha = LocalDateTime.now(); 18 | 19 | System.out.println(numero); 20 | System.out.println(fecha); 21 | 22 | Locale.setDefault(Locale.getDefault()); 23 | System.out.println(Locale.getDefault()); 24 | 25 | // Formatear la fecha 26 | System.out.println(dateParser(fecha, Locale.getDefault())); 27 | 28 | // Formatear el numero 29 | System.out.println(doubleParser(numero, new Locale("es", "ES"))); 30 | 31 | // Formatear el dinero 32 | System.out.println(moneyParser(numero, new Locale("es", "ES"))); 33 | 34 | // Formatear el porcentaje 35 | System.out.println(doublePercentParser(numero, new Locale("es", "ES"))); 36 | 37 | String fechaString = "01/01/2020"; 38 | String horaString = "11:13:14"; 39 | 40 | DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss"); 41 | LocalDateTime fechaHora = LocalDateTime.parse(fechaString + " " + horaString, formatter); 42 | System.out.println(fechaHora); 43 | 44 | formatter = DateTimeFormatter.ofPattern("HH:mm:ss"); 45 | System.out.println(fechaHora.format(formatter)); 46 | 47 | String token = ","; 48 | String cadena = "casa , pepe ,, , luis, jose "; 49 | String[] palabras = cadena.split(token); 50 | for (String palabra : palabras) { 51 | if (!palabra.isBlank()) { 52 | System.out.println(palabra.trim()); 53 | } 54 | } 55 | 56 | StringTokenizer st = new StringTokenizer(cadena, token); 57 | while (st.hasMoreTokens()) { 58 | System.out.println(st.nextToken().trim()); 59 | } 60 | 61 | } 62 | 63 | public static String dateParser(LocalDateTime date, Locale locale) { 64 | // private String pattern = "dd/MM/yyyy"; 65 | return date.format(DateTimeFormatter 66 | .ofLocalizedDate(FormatStyle.FULL).withLocale(locale)); 67 | } 68 | 69 | public static String moneyParser(Double money, Locale locale) { 70 | return NumberFormat.getCurrencyInstance(locale).format(money); 71 | } 72 | 73 | public static String doubleParser(Double number, Locale locale) { 74 | return NumberFormat.getNumberInstance(locale).format(number); 75 | } 76 | 77 | public static String doublePercentParser(Double number, Locale locale) { 78 | return NumberFormat.getPercentInstance(locale).format(number); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /Soluciones/03-BD-Relacional/.gitignore: -------------------------------------------------------------------------------- 1 | /out 2 | /target 3 | -------------------------------------------------------------------------------- /Soluciones/03-BD-Relacional/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /Soluciones/03-BD-Relacional/.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Soluciones/03-BD-Relacional/.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Soluciones/03-BD-Relacional/.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | -------------------------------------------------------------------------------- /Soluciones/03-BD-Relacional/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Soluciones/03-BD-Relacional/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Soluciones/03-BD-Relacional/docker/docker-compose.yml: -------------------------------------------------------------------------------- 1 | # Indicamos la versión 2 | # Para iniciar docker-compose up -d 3 | version: '3.7' 4 | 5 | # Mis servicios 6 | # Iniciamos los servicios 7 | services: 8 | # MARIA DB 9 | mariadb: 10 | build: ./mariadb 11 | image: mariadb 12 | container_name: mariadb 13 | ports: 14 | - 3306:3306 15 | expose: 16 | - 3306 17 | volumes: 18 | - mariadb-volume:/var/lib/mysql 19 | networks: 20 | - mariadb-network 21 | # restart: always 22 | 23 | # ADMIN MARIADB 24 | adminer: 25 | image: adminer 26 | container_name: adminer 27 | # restart: always 28 | ports: 29 | - 8080:8080 30 | networks: 31 | - mariadb-network 32 | depends_on: 33 | - mariadb 34 | 35 | # Mi volumenes de datos compartidos 36 | volumes: 37 | mariadb-volume: 38 | 39 | # Si queremos que tengan una red propia a otros contenedores 40 | networks: 41 | mariadb-network: 42 | driver: bridge 43 | -------------------------------------------------------------------------------- /Soluciones/03-BD-Relacional/docker/mariadb/Dockerfile: -------------------------------------------------------------------------------- 1 | # MariaDB 2 | FROM yobasystems/alpine-mariadb:10 3 | # FROM mariadb:10.5 4 | 5 | # Configuramos BBDD 6 | ENV MYSQL_ROOT_PASSWORD 123 7 | ENV MYSQL_USER blog 8 | ENV MYSQL_PASSWORD blog1234 9 | ENV MYSQL_DATABASE blog 10 | 11 | # Copiamos los ficheros sql para que se ejecuten 12 | COPY ./sql /docker-entrypoint-initdb.d/ -------------------------------------------------------------------------------- /Soluciones/03-BD-Relacional/src/main/java/es/joseluisgs/dam/model/User.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.model; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | 6 | import java.time.LocalDate; 7 | 8 | @Data 9 | @Builder 10 | public class User { 11 | private Long id; 12 | private String nombre; 13 | private String email; 14 | private String password; 15 | private LocalDate fechaRegistro; 16 | 17 | 18 | public User(Long id, String nombre, String email, String password, LocalDate fechaRegistro) { 19 | this.id = id; 20 | this.nombre = nombre; 21 | this.email = email; 22 | this.fechaRegistro = fechaRegistro; 23 | this.password = password; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Soluciones/04-MVC-Paises-BBDD-DI/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.toptal.com/developers/gitignore/api/maven,java,intellij+all 3 | # Edit at https://www.toptal.com/developers/gitignore?templates=maven,java,intellij+all 4 | 5 | ### Intellij+all ### 6 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 7 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 8 | 9 | # User-specific stuff 10 | .idea/**/workspace.xml 11 | .idea/**/tasks.xml 12 | .idea/**/usage.statistics.xml 13 | .idea/**/dictionaries 14 | .idea/**/shelf 15 | 16 | # AWS User-specific 17 | .idea/**/aws.xml 18 | 19 | # Generated files 20 | .idea/**/contentModel.xml 21 | 22 | # Sensitive or high-churn files 23 | .idea/**/dataSources/ 24 | .idea/**/dataSources.ids 25 | .idea/**/dataSources.local.xml 26 | .idea/**/sqlDataSources.xml 27 | .idea/**/dynamic.xml 28 | .idea/**/uiDesigner.xml 29 | .idea/**/dbnavigator.xml 30 | 31 | # Gradle 32 | .idea/**/gradle.xml 33 | .idea/**/libraries 34 | 35 | # Gradle and Maven with auto-import 36 | # When using Gradle or Maven with auto-import, you should exclude module files, 37 | # since they will be recreated, and may cause churn. Uncomment if using 38 | # auto-import. 39 | # .idea/artifacts 40 | # .idea/compiler.xml 41 | # .idea/jarRepositories.xml 42 | # .idea/modules.xml 43 | # .idea/*.iml 44 | # .idea/modules 45 | # *.iml 46 | # *.ipr 47 | 48 | # CMake 49 | cmake-build-*/ 50 | 51 | # Mongo Explorer plugin 52 | .idea/**/mongoSettings.xml 53 | 54 | # File-based project format 55 | *.iws 56 | 57 | # IntelliJ 58 | out/ 59 | 60 | # mpeltonen/sbt-idea plugin 61 | .idea_modules/ 62 | 63 | # JIRA plugin 64 | atlassian-ide-plugin.xml 65 | 66 | # Cursive Clojure plugin 67 | .idea/replstate.xml 68 | 69 | # SonarLint plugin 70 | .idea/sonarlint/ 71 | 72 | # Crashlytics plugin (for Android Studio and IntelliJ) 73 | com_crashlytics_export_strings.xml 74 | crashlytics.properties 75 | crashlytics-build.properties 76 | fabric.properties 77 | 78 | # Editor-based Rest Client 79 | .idea/httpRequests 80 | 81 | # Android studio 3.1+ serialized cache file 82 | .idea/caches/build_file_checksums.ser 83 | 84 | ### Intellij+all Patch ### 85 | # Ignore everything but code style settings and run configurations 86 | # that are supposed to be shared within teams. 87 | 88 | .idea/* 89 | 90 | !.idea/codeStyles 91 | !.idea/runConfigurations 92 | 93 | ### Java ### 94 | # Compiled class file 95 | *.class 96 | 97 | # Log file 98 | *.log 99 | 100 | # BlueJ files 101 | *.ctxt 102 | 103 | # Mobile Tools for Java (J2ME) 104 | .mtj.tmp/ 105 | 106 | # Package Files # 107 | *.jar 108 | *.war 109 | *.nar 110 | *.ear 111 | *.zip 112 | *.tar.gz 113 | *.rar 114 | 115 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 116 | hs_err_pid* 117 | replay_pid* 118 | 119 | ### Maven ### 120 | target/ 121 | pom.xml.tag 122 | pom.xml.releaseBackup 123 | pom.xml.versionsBackup 124 | pom.xml.next 125 | release.properties 126 | dependency-reduced-pom.xml 127 | buildNumber.properties 128 | .mvn/timing.properties 129 | # https://github.com/takari/maven-wrapper#usage-without-binary-jar 130 | .mvn/wrapper/maven-wrapper.jar 131 | 132 | # Eclipse m2e generated files 133 | # Eclipse Core 134 | .project 135 | # JDT-specific (Eclipse Java Development Tools) 136 | .classpath 137 | 138 | # End of https://www.toptal.com/developers/gitignore/api/maven,java,intellij+all 139 | -------------------------------------------------------------------------------- /Soluciones/04-MVC-Paises-BBDD-DI/SecuenciaPaises.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Soluciones/04-MVC-Paises-BBDD-DI/docker/docker-compose.yml: -------------------------------------------------------------------------------- 1 | # Indicamos la versión 2 | # Para iniciar docker-compose up -d 3 | version: '3.7' 4 | 5 | # Mis servicios 6 | # Iniciamos los servicios 7 | services: 8 | # MARIA DB 9 | mariadb: 10 | build: ./mariadb 11 | image: mariadb 12 | container_name: mariadb 13 | ports: 14 | - 3306:3306 15 | expose: 16 | - 3306 17 | volumes: 18 | - mariadb-volume:/var/lib/mysql 19 | networks: 20 | - mariadb-network 21 | # restart: always 22 | 23 | # ADMIN MARIADB 24 | adminer: 25 | image: adminer 26 | container_name: adminer 27 | # restart: always 28 | ports: 29 | - 8080:8080 30 | networks: 31 | - mariadb-network 32 | depends_on: 33 | - mariadb 34 | 35 | # Mi volumenes de datos compartidos 36 | volumes: 37 | mariadb-volume: 38 | 39 | # Si queremos que tengan una red propia a otros contenedores 40 | networks: 41 | mariadb-network: 42 | driver: bridge 43 | -------------------------------------------------------------------------------- /Soluciones/04-MVC-Paises-BBDD-DI/docker/mariadb/Dockerfile: -------------------------------------------------------------------------------- 1 | # MariaDB 2 | FROM yobasystems/alpine-mariadb:10 3 | # FROM mariadb:10.5 4 | 5 | # Configuramos BBDD 6 | ENV MYSQL_ROOT_PASSWORD 123 7 | ENV MYSQL_USER dam 8 | ENV MYSQL_PASSWORD dam1234 9 | ENV MYSQL_DATABASE dam 10 | 11 | # Copiamos los ficheros sql para que se ejecuten 12 | COPY ./sql /docker-entrypoint-initdb.d/ -------------------------------------------------------------------------------- /Soluciones/04-MVC-Paises-BBDD-DI/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | groupId 8 | SecuenciaPaises 9 | 1.0-SNAPSHOT 10 | 11 | 12 | 11 13 | 11 14 | 15 | 16 | 17 | 18 | 19 | com.google.code.gson 20 | gson 21 | 2.9.0 22 | 23 | 24 | 25 | org.projectlombok 26 | lombok 27 | RELEASE 28 | compile 29 | 30 | 31 | 32 | org.mariadb.jdbc 33 | mariadb-java-client 34 | 3.0.3 35 | 36 | 37 | 38 | org.mybatis 39 | mybatis 40 | 3.5.9 41 | 42 | 43 | 44 | org.junit.jupiter 45 | junit-jupiter 46 | RELEASE 47 | test 48 | 49 | 50 | 51 | org.mockito 52 | mockito-core 53 | 4.4.0 54 | test 55 | 56 | 57 | org.mockito 58 | mockito-junit-jupiter 59 | 4.4.0 60 | test 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /Soluciones/04-MVC-Paises-BBDD-DI/src/main/java/es/joseluisgs/dam/Main.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam; 2 | 3 | import es.joseluisgs.dam.controllers.DataBaseManager; 4 | import es.joseluisgs.dam.utils.ApplicationProperties; 5 | import es.joseluisgs.dam.views.PaisView; 6 | 7 | import java.io.File; 8 | import java.io.FileNotFoundException; 9 | import java.sql.ResultSet; 10 | import java.sql.SQLException; 11 | import java.util.Optional; 12 | 13 | /** 14 | * Ejemplo de Patrón MVC para CRUD de países. 15 | * Siguiendo los diagramas de Secuencias en Clase 16 | * Modelo: Pais, gestionador por PaisRepository 17 | * Vista: La propia consola: comunicacion con el usuario 18 | * Controlador: PaisController, controla, cómo y de qué manera el modelo, repositorio y la vista interactúan 19 | * Como vista que soy, soy lo último y gestiono las excepciones con Try/Catch 20 | */ 21 | public class Main { 22 | public static void main(String[] args) { 23 | checkServer(); 24 | initData(); 25 | PaisView view = PaisView.getInstance(); 26 | view.menu(); 27 | 28 | } 29 | 30 | private static void checkServer() { 31 | System.out.println("Comprobamos la conexión al Servidor BD"); 32 | DataBaseManager controller = DataBaseManager.getInstance(); 33 | try { 34 | controller.open(); 35 | Optional rs = controller.select("SELECT 'Hello world'"); 36 | if (rs.isPresent()) { 37 | rs.get().first(); 38 | controller.close(); 39 | System.out.println("Conexión con la Base de Datos realizada con éxito"); 40 | } 41 | } catch (SQLException e) { 42 | System.err.println("Error al conectar al servidor de Base de Datos: " + e.getMessage()); 43 | System.exit(1); 44 | } 45 | } 46 | 47 | private static void initData() { 48 | ApplicationProperties properties = new ApplicationProperties(); 49 | boolean init = Boolean.parseBoolean(properties.readProperty("database.initdata")); 50 | if (init) { 51 | System.out.println("Iniciamos los datos de ejemplo de la Base de Datos"); 52 | DataBaseManager controller = DataBaseManager.getInstance(); 53 | String dataPath = "sql" + File.separator + "init-db.sql"; 54 | try { 55 | var sqlFile = Main.class.getClassLoader().getResource(dataPath).getPath(); 56 | System.out.println(dataPath); 57 | controller.open(); 58 | controller.initData(sqlFile, false); 59 | controller.close(); 60 | System.out.println("Datos inicializados con éxito"); 61 | } catch (SQLException e) { 62 | System.err.println("Error al conectar al servidor de Base de Datos: " + e.getMessage()); 63 | System.exit(1); 64 | } catch (FileNotFoundException e) { 65 | System.err.println("Error al leer el fichero de datos iniciales: " + e.getMessage()); 66 | System.exit(1); 67 | } 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Soluciones/04-MVC-Paises-BBDD-DI/src/main/java/es/joseluisgs/dam/comparators/PaisCodigoComparator.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.comparators; 2 | 3 | import es.joseluisgs.dam.models.Pais; 4 | 5 | import java.util.Comparator; 6 | 7 | /** 8 | * Comparador de países por código. 9 | */ 10 | public class PaisCodigoComparator implements Comparator { 11 | @Override 12 | public int compare(Pais p1, Pais p2) { 13 | return p1.getCodigo().compareTo(p2.getCodigo()); 14 | } 15 | 16 | @Override 17 | public Comparator reversed() { 18 | return Comparator.super.reversed(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Soluciones/04-MVC-Paises-BBDD-DI/src/main/java/es/joseluisgs/dam/comparators/PaisNombreComparator.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.comparators; 2 | 3 | import es.joseluisgs.dam.models.Pais; 4 | 5 | import java.util.Comparator; 6 | 7 | /** 8 | * Comparador de países por nombre. 9 | */ 10 | public class PaisNombreComparator implements Comparator { 11 | @Override 12 | public int compare(Pais p1, Pais p2) { 13 | return p1.getNombre().compareTo(p2.getNombre()); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Soluciones/04-MVC-Paises-BBDD-DI/src/main/java/es/joseluisgs/dam/controllers/AcuerdoController.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.controllers; 2 | 3 | import es.joseluisgs.dam.exceptions.AcuerdoException; 4 | import es.joseluisgs.dam.models.Acuerdo; 5 | import es.joseluisgs.dam.models.LineaAcuerdo; 6 | import es.joseluisgs.dam.models.Pais; 7 | import es.joseluisgs.dam.repositories.acuerdos.IAcuerdoRepository; 8 | 9 | import java.sql.SQLException; 10 | import java.time.LocalDate; 11 | import java.time.LocalDateTime; 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | 15 | public class AcuerdoController { 16 | private final IAcuerdoRepository acuerdosRepository; 17 | 18 | public AcuerdoController(IAcuerdoRepository acuerdosRepository) { 19 | this.acuerdosRepository = acuerdosRepository; 20 | } 21 | 22 | /** 23 | * Crea un acuerdo con los datos pasados por parámetro. 24 | * 25 | * @param nombre Nombre del acuerdo. 26 | * @param paises Paises que participan en el acuerdo. 27 | * @return El acuerdo creado. 28 | * @throws SQLException Si hay un error en la base de datos. 29 | */ 30 | public Acuerdo createAcuerdo(String nombre, List paises) throws SQLException { 31 | List lineas = new ArrayList<>(); 32 | for (Pais pais : paises) { 33 | lineas.add(new LineaAcuerdo(pais, LocalDate.now().getYear())); 34 | } 35 | Acuerdo acuerdo = new Acuerdo(0, nombre, LocalDateTime.now(), lineas); 36 | return acuerdosRepository.save(acuerdo); 37 | } 38 | 39 | /** 40 | * Obtiene un acuerdo por su id. 41 | * 42 | * @param id Id del acuerdo. 43 | * @return El acuerdo. 44 | * @throws AcuerdoException Si no existe el acuerdo. 45 | * @throws SQLException Si hay un error en la base de datos. 46 | */ 47 | public Acuerdo getAcuerdoById(int id) throws AcuerdoException, SQLException { 48 | return acuerdosRepository.findById(id).orElseThrow(() -> new AcuerdoException("No existe el acuerdo con id " + id)); 49 | } 50 | 51 | /** 52 | * Obtiene todos los acuerdos. 53 | * 54 | * @return Lista de acuerdos. 55 | * @throws SQLException Si hay un error en la base de datos. 56 | */ 57 | public List getAllAcuerdos() throws SQLException { 58 | return acuerdosRepository.findAll(); 59 | } 60 | 61 | /** 62 | * Elimina un acuerdo por su id. 63 | * 64 | * @param id Id del acuerdo. 65 | * @return El acuerdo eliminado. 66 | * @throws SQLException Si hay un error en la base de datos. 67 | */ 68 | public Acuerdo deleteAcuerdo(int id) throws SQLException { 69 | return acuerdosRepository.delete(id); 70 | } 71 | 72 | /** 73 | * Actualiza un acuerdo. 74 | * 75 | * @param id Id del acuerdo. 76 | * @param acuerdo Acuerdo con los nuevos datos. 77 | * @return El acuerdo actualizado. 78 | * @throws SQLException Si hay un error en la base de datos. 79 | */ 80 | public Acuerdo updateAcuerdo(int id, Acuerdo acuerdo) throws SQLException { 81 | return acuerdosRepository.update(id, acuerdo); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Soluciones/04-MVC-Paises-BBDD-DI/src/main/java/es/joseluisgs/dam/controllers/BackupManager.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.controllers; 2 | 3 | import es.joseluisgs.dam.models.Acuerdo; 4 | import es.joseluisgs.dam.models.Backup; 5 | import es.joseluisgs.dam.models.Pais; 6 | import es.joseluisgs.dam.repositories.acuerdos.IAcuerdoRepository; 7 | import es.joseluisgs.dam.repositories.paises.IPaisRepository; 8 | import es.joseluisgs.dam.services.Storage.IStorageBackup; 9 | 10 | import java.sql.SQLException; 11 | 12 | public class BackupManager { 13 | private final IPaisRepository paisRepository; 14 | private final IAcuerdoRepository acuerdoRepository; 15 | private final IStorageBackup storageBackup; 16 | 17 | public BackupManager(IPaisRepository paisRepository, IAcuerdoRepository acuerdoRepository, IStorageBackup storageBackup) { 18 | this.paisRepository = paisRepository; 19 | this.acuerdoRepository = acuerdoRepository; 20 | this.storageBackup = storageBackup; 21 | } 22 | 23 | 24 | /** 25 | * Importa los datos desde un fichero de backup 26 | */ 27 | public void importarDatos() throws SQLException { 28 | System.out.println("Importando datos de Backup: " + storageBackup.getStoragePath()); 29 | var backup = storageBackup.load(); 30 | System.out.println("Importando Paises..."); 31 | if (backup.getPaises().size() > 0) { 32 | paisRepository.clearAll(); 33 | for (Pais pais : backup.getPaises()) { 34 | paisRepository.save(pais); 35 | } 36 | System.out.println("Paises importados con éxito al repositorio: " + backup.getPaises().size() + " paises"); 37 | } else { 38 | System.out.println("Ha existido un problema al importar los datos de Paises"); 39 | } 40 | System.out.println("Importando Acuerdos..."); 41 | if (backup.getAcuerdos().size() > 0) { 42 | acuerdoRepository.clearAll(); 43 | for (Acuerdo acuerdo : backup.getAcuerdos()) { 44 | acuerdoRepository.save(acuerdo); 45 | } 46 | System.out.println("Acuerdos importados con éxito al repositorio: " + backup.getAcuerdos().size() + " acuerdos"); 47 | } else { 48 | System.out.println("Ha existido un problema al importar los datos de Acuerdos"); 49 | } 50 | } 51 | 52 | 53 | /** 54 | * Exporta los datos desde un fichero de Backup 55 | */ 56 | public void exportarDatos() throws SQLException { 57 | System.out.println("Exportando datos a fichero de Backup..."); 58 | var paises = paisRepository.findAll(); 59 | var acuerdos = acuerdoRepository.findAll(); 60 | Backup backup = Backup.builder() 61 | .paises(paises) 62 | .acuerdos(acuerdos) 63 | .build(); 64 | var res = storageBackup.save(backup); 65 | if (res) { 66 | System.out.println("Exportando " + backup.getPaises().size() + " paises"); 67 | System.out.println("Exportando " + backup.getAcuerdos().size() + " acuerdos"); 68 | System.out.println("Datos exportados con éxito en: " + storageBackup.getStoragePath()); 69 | } else { 70 | System.out.println("Ha existido un problema al exportar los datos"); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Soluciones/04-MVC-Paises-BBDD-DI/src/main/java/es/joseluisgs/dam/exceptions/AcuerdoException.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.exceptions; 2 | 3 | /** 4 | * Excepción asociada al comprotamiento de gestion de Acuerdos. 5 | */ 6 | public class AcuerdoException extends Exception { 7 | 8 | public AcuerdoException(String mensaje) { 9 | super(mensaje); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Soluciones/04-MVC-Paises-BBDD-DI/src/main/java/es/joseluisgs/dam/exceptions/PaisException.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.exceptions; 2 | 3 | /** 4 | * Excepción asociada al comprotamiento de gestion de paises. 5 | */ 6 | public class PaisException extends Exception { 7 | 8 | public PaisException(String mensaje) { 9 | super(mensaje); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Soluciones/04-MVC-Paises-BBDD-DI/src/main/java/es/joseluisgs/dam/models/Acuerdo.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.models; 2 | 3 | import es.joseluisgs.dam.utils.Formatter; 4 | import lombok.Data; 5 | 6 | import java.time.LocalDateTime; 7 | import java.util.List; 8 | 9 | @Data 10 | public class Acuerdo { 11 | private final LocalDateTime fecha; 12 | private String nombre; 13 | private double aportacion; 14 | private List lineas; 15 | private int id; 16 | 17 | 18 | public Acuerdo(int id, String nombre, LocalDateTime fecha, List lineas) { 19 | this.id = id; 20 | this.nombre = nombre; 21 | this.fecha = fecha; 22 | this.lineas = lineas; 23 | this.aportacion = calcularAportacion(); 24 | } 25 | 26 | public Acuerdo(int id, String nombre, LocalDateTime fecha, double aportacion, List lineas) { 27 | this.id = id; 28 | this.nombre = nombre; 29 | this.fecha = fecha; 30 | this.lineas = lineas; 31 | this.aportacion = aportacion; 32 | } 33 | 34 | private double calcularAportacion() { 35 | double total = 0; 36 | for (LineaAcuerdo linea : lineas) { 37 | total += linea.getSubvencion(); 38 | } 39 | return total; 40 | } 41 | 42 | public Integer getId() { 43 | return id; 44 | } 45 | 46 | @Override 47 | public String toString() { 48 | // Puedes imprimir listas como Arrays.toString(lista)) 49 | return "Acuerdo{" + "id=" + id + ", nombre=" + nombre + ", fecha=" 50 | + Formatter.dateParser(fecha) + ", lineas=" + lineas + ", aportacion=" + Formatter.moneyParser(aportacion) + '}'; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /Soluciones/04-MVC-Paises-BBDD-DI/src/main/java/es/joseluisgs/dam/models/Backup.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.models; 2 | 3 | import lombok.Builder; 4 | 5 | import java.time.LocalDateTime; 6 | import java.util.List; 7 | 8 | @Builder 9 | public class Backup { 10 | private final String createdAt = LocalDateTime.now().toString(); 11 | private List paises; 12 | private List acuerdos; 13 | 14 | public List getPaises() { 15 | return paises; 16 | } 17 | 18 | public List getAcuerdos() { 19 | return acuerdos; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Soluciones/04-MVC-Paises-BBDD-DI/src/main/java/es/joseluisgs/dam/models/LineaAcuerdo.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.models; 2 | 3 | import es.joseluisgs.dam.utils.Formatter; 4 | import lombok.Data; 5 | 6 | @Data 7 | public class LineaAcuerdo { 8 | private final Pais pais; 9 | private final int año; 10 | private final double subvencion; 11 | 12 | public LineaAcuerdo(Pais pais, int año) { 13 | this.pais = pais; 14 | this.año = año; 15 | this.subvencion = pais.getPresupuesto() * 0.25; 16 | } 17 | 18 | public LineaAcuerdo(Pais pais, int año, double subvencion) { 19 | this.pais = pais; 20 | this.año = año; 21 | this.subvencion = subvencion; 22 | } 23 | 24 | @Override 25 | public String toString() { 26 | return "LineaAcuerdo{" + "pais=" + pais.getNombre() + ", año=" + año + ", subvencion=" + Formatter.moneyParser(subvencion) + '}'; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Soluciones/04-MVC-Paises-BBDD-DI/src/main/java/es/joseluisgs/dam/repositories/CRUDRepository.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.repositories; 2 | 3 | import java.sql.SQLException; 4 | import java.util.List; 5 | import java.util.Optional; 6 | 7 | public interface CRUDRepository { 8 | /** 9 | * Devuelve una lista de todos los elementos del repositorio 10 | * 11 | * @return Lista de elementos 12 | * @throws SQLException Si hay algún error en la base de datos 13 | */ 14 | List findAll() throws SQLException; 15 | 16 | /** 17 | * Devuelve un Optional del elemento dada una id 18 | * 19 | * @param id Id del elemento 20 | * @return Optional del elemento 21 | * @throws SQLException Si hay algún error en la base de datos 22 | */ 23 | Optional findById(ID id) throws SQLException; 24 | 25 | /** 26 | * Inserta un elemento en el repositorio 27 | * 28 | * @param entity Elemento a insertar 29 | * @return Elemento insertado 30 | * @throws SQLException Si hay algún error en la base de datos 31 | */ 32 | T save(T entity) throws SQLException; 33 | 34 | /** 35 | * Actualiza un elemento en el repositorio 36 | * 37 | * @param id Id del elemento a actualizar 38 | * @param entity Elemento a actualizar 39 | * @return Elemento actualizado 40 | * @throws SQLException Si hay algún error en la base de datos 41 | */ 42 | T update(ID id, T entity) throws SQLException; 43 | 44 | /** 45 | * Elimina un elemento del repositorio 46 | * 47 | * @param id Id del elemento a eliminar 48 | * @return Elemento eliminado 49 | * @throws SQLException Si hay algún error en la base de datos 50 | */ 51 | T delete(ID id) throws SQLException; 52 | } 53 | -------------------------------------------------------------------------------- /Soluciones/04-MVC-Paises-BBDD-DI/src/main/java/es/joseluisgs/dam/repositories/acuerdos/IAcuerdoRepository.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.repositories.acuerdos; 2 | 3 | import es.joseluisgs.dam.models.Acuerdo; 4 | import es.joseluisgs.dam.repositories.CRUDRepository; 5 | 6 | import java.sql.SQLException; 7 | 8 | public interface IAcuerdoRepository extends CRUDRepository { 9 | 10 | void clearAll() throws SQLException; 11 | } 12 | -------------------------------------------------------------------------------- /Soluciones/04-MVC-Paises-BBDD-DI/src/main/java/es/joseluisgs/dam/repositories/paises/IPaisRepository.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.repositories.paises; 2 | 3 | import es.joseluisgs.dam.models.Pais; 4 | import es.joseluisgs.dam.repositories.CRUDRepository; 5 | 6 | import java.sql.SQLException; 7 | import java.util.Optional; 8 | 9 | // Toda nueva funcionalidad se extiende de la interfaz SOLID 10 | public interface IPaisRepository extends CRUDRepository { 11 | 12 | Optional findByNombre(String nombre) throws SQLException; 13 | 14 | void clearAll() throws SQLException; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Soluciones/04-MVC-Paises-BBDD-DI/src/main/java/es/joseluisgs/dam/services/Storage/IStorage.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.services.Storage; 2 | 3 | public interface IStorage { 4 | 5 | /** 6 | * Salva los elementos almacenados en item. 7 | * 8 | * @param item Elementos a almacenar. 9 | * @return true si se ha almacenado correctamente, false en caso contrario. 10 | */ 11 | boolean save(T item); 12 | 13 | /** 14 | * Le el almacenado y lo devuelve en un item T. 15 | * 16 | * @return Elementos almacenados. 17 | */ 18 | T load(); 19 | 20 | /** 21 | * Devuelve el path de la ubicación del almacenado. 22 | * 23 | * @return Path de la ubicación del almacenado. 24 | */ 25 | String getStoragePath(); 26 | } 27 | -------------------------------------------------------------------------------- /Soluciones/04-MVC-Paises-BBDD-DI/src/main/java/es/joseluisgs/dam/services/Storage/IStorageBackup.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.services.Storage; 2 | 3 | import es.joseluisgs.dam.models.Backup; 4 | 5 | public interface IStorageBackup extends IStorage { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /Soluciones/04-MVC-Paises-BBDD-DI/src/main/java/es/joseluisgs/dam/services/Storage/StorageBackupJsonFile.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.services.Storage; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.GsonBuilder; 5 | import com.google.gson.reflect.TypeToken; 6 | import es.joseluisgs.dam.models.Backup; 7 | 8 | import java.io.*; 9 | import java.nio.file.Files; 10 | import java.nio.file.Path; 11 | import java.nio.file.Paths; 12 | 13 | public class StorageBackupJsonFile implements IStorageBackup { 14 | private static StorageBackupJsonFile instance; 15 | 16 | private final Path currentRelativePath = Paths.get(""); 17 | private final String ruta = currentRelativePath.toAbsolutePath().toString(); 18 | private final String dir = ruta + File.separator + "data"; 19 | private final String backupFile = dir + File.separator + "backup.json"; 20 | 21 | 22 | private StorageBackupJsonFile() { 23 | init(); 24 | } 25 | 26 | public static StorageBackupJsonFile getInstance() { 27 | if (instance == null) { 28 | instance = new StorageBackupJsonFile(); 29 | } 30 | return instance; 31 | } 32 | 33 | private void init() { 34 | Path path = Paths.get(dir); 35 | if (!Files.exists(path)) { 36 | try { 37 | Files.createDirectories(path); 38 | } catch (IOException e) { 39 | System.out.println("Error: " + e.getMessage()); 40 | } 41 | } 42 | } 43 | 44 | @Override 45 | public boolean save(Backup backup) { 46 | Gson gson = new GsonBuilder().setPrettyPrinting().create(); 47 | boolean result = false; 48 | PrintWriter f = null; 49 | try { 50 | f = new PrintWriter(new FileWriter(backupFile)); 51 | f.println(gson.toJson(backup)); 52 | result = true; 53 | 54 | } catch (Exception e) { 55 | System.out.println("Error: " + e.getMessage()); 56 | result = false; 57 | } finally { 58 | if (f != null) { 59 | f.close(); 60 | } 61 | } 62 | return result; 63 | } 64 | 65 | @Override 66 | public Backup load() { 67 | Gson gson = new GsonBuilder().setPrettyPrinting().create(); 68 | Backup backup = null; 69 | Reader reader = null; 70 | try { 71 | reader = Files.newBufferedReader(Paths.get(backupFile)); 72 | backup = gson.fromJson(reader, new TypeToken() { 73 | }.getType()); 74 | } catch (Exception e) { 75 | System.out.println("Error: " + e.getMessage()); 76 | } finally { 77 | if (reader != null) { 78 | try { 79 | reader.close(); 80 | } catch (IOException e) { 81 | System.out.println("Error: " + e.getMessage()); 82 | } 83 | } 84 | } 85 | return backup; 86 | } 87 | 88 | @Override 89 | public String getStoragePath() { 90 | return backupFile; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /Soluciones/04-MVC-Paises-BBDD-DI/src/main/java/es/joseluisgs/dam/utils/ApplicationProperties.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.utils; 2 | 3 | import java.io.IOException; 4 | import java.util.Properties; 5 | import java.util.logging.Level; 6 | import java.util.logging.Logger; 7 | 8 | public class ApplicationProperties { 9 | private final Properties properties; 10 | 11 | public ApplicationProperties() { 12 | properties = new Properties(); 13 | try { 14 | // De esta manera leemos desde el fichero de propiedades en resources 15 | properties.load(getClass().getClassLoader().getResourceAsStream("application.properties")); 16 | 17 | } catch (IOException ex) { 18 | System.err.println("IOException Ocurrido al leer el fichero de propiedades: " + ex.getMessage()); 19 | Logger.getLogger(getClass().getName()).log(Level.ALL, "IOException Ocurrido al leer el fichero de propiedades: " + ex.getMessage()); 20 | } 21 | } 22 | 23 | public String readProperty(String keyName) { 24 | // Logger.getLogger(getClass().getName()).log(Level.INFO, "Leyendo propiedad " + keyName); 25 | return properties.getProperty(keyName, "No existe esa clave en el fichero de propiedades"); 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /Soluciones/04-MVC-Paises-BBDD-DI/src/main/java/es/joseluisgs/dam/utils/Console.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.utils; 2 | 3 | import java.util.Scanner; 4 | 5 | /** 6 | * Clase que permite leer datos desde la consola. 7 | */ 8 | public class Console { 9 | public static String getString(String message) { 10 | System.out.println(message); 11 | return new Scanner(System.in).nextLine().trim(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Soluciones/04-MVC-Paises-BBDD-DI/src/main/java/es/joseluisgs/dam/utils/Formatter.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.utils; 2 | 3 | import java.text.NumberFormat; 4 | import java.time.LocalDateTime; 5 | import java.time.format.DateTimeFormatter; 6 | import java.time.format.FormatStyle; 7 | import java.util.Locale; 8 | 9 | public class Formatter { 10 | 11 | public static String dateParser(LocalDateTime date) { 12 | final Locale locale = new Locale("es", "ES"); 13 | // private String pattern = "dd/MM/yyyy"; 14 | return date.format(DateTimeFormatter 15 | .ofLocalizedDate(FormatStyle.MEDIUM).withLocale(locale)); 16 | } 17 | 18 | public static String moneyParser(Double money) { 19 | final Locale locale = new Locale("es", "ES"); 20 | return NumberFormat.getCurrencyInstance(locale).format(money); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Soluciones/04-MVC-Paises-BBDD-DI/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joseluisgs/Programacion-09-2021-2022/188c0476c2f30e7149340dda33239a3df1488e4b/Soluciones/04-MVC-Paises-BBDD-DI/src/main/resources/application.properties -------------------------------------------------------------------------------- /Soluciones/04-MVC-Paises-BBDD-DI/src/main/resources/sql/init-db.sql: -------------------------------------------------------------------------------- 1 | -- Adminer 4.8.1 MySQL 5.5.5-10.6.4-MariaDB dump 2 | 3 | SET NAMES utf8; 4 | SET 5 | time_zone = '+00:00'; 6 | SET 7 | foreign_key_checks = 0; 8 | SET 9 | sql_mode = 'NO_AUTO_VALUE_ON_ZERO'; 10 | 11 | DROP 12 | DATABASE IF EXISTS `dam`; 13 | CREATE 14 | DATABASE `dam` /*!40100 DEFAULT CHARACTER SET utf8mb3 */; 15 | USE 16 | `dam`; 17 | 18 | DROP TABLE IF EXISTS `acuerdo`; 19 | CREATE TABLE `acuerdo` 20 | ( 21 | `id` int(11) NOT NULL AUTO_INCREMENT, 22 | `nombre` varchar(100) NOT NULL, 23 | `fecha` datetime NOT NULL, 24 | `aportacion` double NOT NULL, 25 | PRIMARY KEY (`id`) 26 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; 27 | 28 | INSERT INTO `acuerdo` (`id`, `nombre`, `fecha`, `aportacion`) 29 | VALUES (1, 'Acuerdo Diplomático', '2022-03-25 20:59:57', 12345.89), 30 | (2, 'Acuerdo de Fronteras', '2022-03-25 21:01:40', 999.99); 31 | 32 | DROP TABLE IF EXISTS `linea_acuerdo`; 33 | CREATE TABLE `linea_acuerdo` 34 | ( 35 | `id_acuerdo` int(11) NOT NULL, 36 | `id_pais` int(11) NOT NULL, 37 | `año` int(11) NOT NULL, 38 | `subvencion` double NOT NULL, 39 | KEY `id_acuerdo` (`id_acuerdo`), 40 | KEY `id_pais` (`id_pais`), 41 | CONSTRAINT `linea_acuerdo_ibfk_1` FOREIGN KEY (`id_acuerdo`) REFERENCES `acuerdo` (`id`) ON DELETE CASCADE 42 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; 43 | 44 | INSERT INTO `linea_acuerdo` (`id_acuerdo`, `id_pais`, `año`, `subvencion`) 45 | VALUES (1, 1, 2022, 1234.56), 46 | (1, 2, 2022, 345.32), 47 | (2, 4, 2022, 450.8), 48 | (2, 7, 2022, 6666.66), 49 | (2, 2, 2022, 333.33); 50 | 51 | DROP TABLE IF EXISTS `pais`; 52 | CREATE TABLE `pais` 53 | ( 54 | `id` int(11) NOT NULL AUTO_INCREMENT, 55 | `nombre` varchar(100) NOT NULL, 56 | `codigo` varchar(5) NOT NULL, 57 | `idioma` varchar(100) NOT NULL, 58 | `moneda` varchar(50) NOT NULL, 59 | `capital` varchar(100) NOT NULL, 60 | `presupuesto` double DEFAULT NULL, 61 | PRIMARY KEY (`id`) 62 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; 63 | 64 | INSERT INTO `pais` (`id`, `nombre`, `codigo`, `idioma`, `moneda`, `capital`, `presupuesto`) 65 | VALUES (1, 'España', 'ES', 'Español', 'Euro', 'Madrid', 1234567.23), 66 | (2, 'Francia', 'FR', 'Francés', 'Euro', 'París', 123456.67), 67 | (3, 'Italia', 'IT', 'Italiano', 'Euro', 'Roma', 564568.34), 68 | (4, 'Alemania', 'DE', 'Alemán', 'Euro', 'Berlín', 234567.23), 69 | (5, 'Reino Unido', 'UK', 'Inglés', 'Libra', 'Londres', 232323.34), 70 | (6, 'Japón', 'JP', 'Jsaponés', 'Yen', 'Tokio', 21212.12), 71 | (7, 'China', 'CN', 'Chino', 'Yuan', 'Pekín', 121212.34), 72 | (8, 'Australia', 'AU', 'Inglés', 'Dólar', 'Canberra', 567654.23), 73 | (9, 'Argentina', 'AR', 'Español', 'Peso', 'Buenos Aires', 123456.34), 74 | (10, 'Brasil', 'BR', 'Portugués', 'Real', 'Brasilia', 251251.62), 75 | (11, 'Estados Unidos', 'US', 'Inglés', 'Dólar', 'Washington', 1212415.98); 76 | 77 | -- 2022-03-26 11:15:34 -------------------------------------------------------------------------------- /Soluciones/04-MVC-Paises-BBDD-DI/src/test/java/es/joseluisgs/dam/MainTest.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | import static org.junit.jupiter.api.Assertions.assertTrue; 6 | 7 | class MainTest { 8 | 9 | @Test 10 | public void trueIsTrue() { 11 | assertTrue(true); 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /Soluciones/04-MVC-Paises-BBDD-DI/src/test/java/es/joseluisgs/dam/utilities/DataBase.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.utilities; 2 | 3 | import es.joseluisgs.dam.Main; 4 | import es.joseluisgs.dam.controllers.DataBaseManager; 5 | import es.joseluisgs.dam.utils.ApplicationProperties; 6 | 7 | import java.io.File; 8 | import java.io.FileNotFoundException; 9 | import java.sql.SQLException; 10 | 11 | public class DataBase { 12 | 13 | /** 14 | * Inicia la base de datos con los datos de prueba si los hay, o la estructura de la tabla... 15 | */ 16 | public static void init() { 17 | ApplicationProperties properties = new ApplicationProperties(); 18 | boolean init = Boolean.parseBoolean(properties.readProperty("database.initdata")); 19 | if (init) { 20 | DataBaseManager controller = DataBaseManager.getInstance(); 21 | String dataPath = "sql" + File.separator + "init-db.sql"; 22 | try { 23 | var sqlFile = Main.class.getClassLoader().getResource(dataPath).getPath(); 24 | controller.open(); 25 | controller.initData(sqlFile, false); 26 | controller.close(); 27 | } catch (SQLException e) { 28 | System.err.println("Error al conectar al servidor de Base de Datos: " + e.getMessage()); 29 | System.exit(1); 30 | } catch (FileNotFoundException e) { 31 | System.err.println("Error al leer el fichero de datos iniciales: " + e.getMessage()); 32 | System.exit(1); 33 | } 34 | } 35 | } 36 | 37 | /** 38 | * Borra todas las tablas, que cuesta menos que tirar toda la base de datos y levantarla de nuevo 39 | * 40 | * @throws SQLException 41 | */ 42 | public static void deleteAll() throws SQLException { 43 | DataBaseManager db = DataBaseManager.getInstance(); 44 | String query = "DELETE FROM pais"; 45 | db.open(); 46 | db.delete(query); 47 | query = "DELETE FROM acuerdo"; 48 | db.beginTransaction(); 49 | db.delete(query); 50 | query = "DELETE FROM linea_acuerdo"; 51 | db.delete(query); 52 | db.commit(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Soluciones/04-MVC-Paises-BBDD-DI/src/test/java/es/joseluisgs/dam/utilities/DataDB.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.utilities; 2 | 3 | import es.joseluisgs.dam.controllers.DataBaseManager; 4 | import es.joseluisgs.dam.models.Acuerdo; 5 | import es.joseluisgs.dam.models.LineaAcuerdo; 6 | import es.joseluisgs.dam.models.Pais; 7 | 8 | import java.sql.ResultSet; 9 | import java.sql.SQLException; 10 | import java.util.Optional; 11 | 12 | public class DataDB { 13 | // Insertamos un dato de prueba, aquí vemos un acoplamiento... 14 | // Si no quiseramos esto, podríamos usar Order de test 15 | // Lo ideal es meterlo en el script, e iniciarlo cada vez... 16 | public static void insertPaisTest(Pais paisTest) throws SQLException { 17 | String query = "INSERT INTO pais VALUES (null, ?, ?, ?, ?, ?, ?)"; 18 | DataBaseManager db = DataBaseManager.getInstance(); 19 | db.open(); 20 | Optional res = db.insert(query, paisTest.getNombre(), paisTest.getCodigo(), paisTest.getIdioma(), paisTest.getMoneda(), 21 | paisTest.getCapital(), paisTest.getPresupuesto()); 22 | if (res.get().first()) { 23 | paisTest.setId(res.get().getInt(1)); 24 | } 25 | db.close(); 26 | } 27 | 28 | public static void insertAcuerdoTest(Acuerdo acuerdoTest) throws SQLException { 29 | // OJO pongo null en el primer parámetro porque no inserto el ID, este se genera automático. Mira el DBMAnager 30 | String query = "INSERT INTO acuerdo VALUES (null, ?, ?, ?)"; 31 | DataBaseManager db = DataBaseManager.getInstance(); 32 | // Es una transacción, por lo que si falla alguna de las dos, se cancela todo 33 | db.open(); 34 | db.beginTransaction(); 35 | ResultSet res = db.insert(query, acuerdoTest.getNombre(), acuerdoTest.getFecha(), acuerdoTest.getAportacion()) 36 | .orElseThrow(() -> new SQLException("Error al insertar acuerdo")); 37 | 38 | // Para obtener su ID que ha generado la BD 39 | if (res.first()) { 40 | acuerdoTest.setId(res.getInt(1)); 41 | // Ahora salvamos toda las lineas de acuerdo... 42 | for (LineaAcuerdo linea : acuerdoTest.getLineas()) { 43 | query = "INSERT INTO linea_acuerdo VALUES (?, ?, ?, ?)"; 44 | db.insert(query, acuerdoTest.getId(), linea.getPais().getId(), linea.getAño(), linea.getSubvencion()) 45 | .orElseThrow(() -> new SQLException("Error al insertar linea de acuerdo")); 46 | } 47 | 48 | // Y finalmente cerramos la conexión y devolvemos el acuerdo 49 | db.commit(); 50 | db.close(); 51 | } 52 | db.rollback(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Soluciones/04-MVC-Paises-BBDD-DI/src/test/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joseluisgs/Programacion-09-2021-2022/188c0476c2f30e7149340dda33239a3df1488e4b/Soluciones/04-MVC-Paises-BBDD-DI/src/test/resources/application.properties -------------------------------------------------------------------------------- /Soluciones/04-MVC-Paises-BBDD-DI/src/test/resources/sql/init-db.sql: -------------------------------------------------------------------------------- 1 | -- Adminer 4.8.1 MySQL 5.5.5-10.6.4-MariaDB dump 2 | 3 | SET NAMES utf8; 4 | SET 5 | time_zone = '+00:00'; 6 | SET 7 | foreign_key_checks = 0; 8 | SET 9 | sql_mode = 'NO_AUTO_VALUE_ON_ZERO'; 10 | 11 | DROP 12 | DATABASE IF EXISTS `dam`; 13 | CREATE 14 | DATABASE `dam` /*!40100 DEFAULT CHARACTER SET utf8mb3 */; 15 | USE 16 | `dam`; 17 | 18 | DROP TABLE IF EXISTS `acuerdo`; 19 | CREATE TABLE `acuerdo` 20 | ( 21 | `id` int(11) NOT NULL AUTO_INCREMENT, 22 | `nombre` varchar(100) NOT NULL, 23 | `fecha` datetime NOT NULL, 24 | `aportacion` double NOT NULL, 25 | PRIMARY KEY (`id`) 26 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; 27 | 28 | 29 | DROP TABLE IF EXISTS `linea_acuerdo`; 30 | CREATE TABLE `linea_acuerdo` 31 | ( 32 | `id_acuerdo` int(11) NOT NULL, 33 | `id_pais` int(11) NOT NULL, 34 | `año` int(11) NOT NULL, 35 | `subvencion` double NOT NULL, 36 | KEY `id_acuerdo` (`id_acuerdo`), 37 | KEY `id_pais` (`id_pais`), 38 | CONSTRAINT `linea_acuerdo_ibfk_1` FOREIGN KEY (`id_acuerdo`) REFERENCES `acuerdo` (`id`) ON DELETE CASCADE 39 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; 40 | 41 | DROP TABLE IF EXISTS `pais`; 42 | CREATE TABLE `pais` 43 | ( 44 | `id` int(11) NOT NULL AUTO_INCREMENT, 45 | `nombre` varchar(100) NOT NULL, 46 | `codigo` varchar(5) NOT NULL, 47 | `idioma` varchar(100) NOT NULL, 48 | `moneda` varchar(50) NOT NULL, 49 | `capital` varchar(100) NOT NULL, 50 | `presupuesto` double DEFAULT NULL, 51 | PRIMARY KEY (`id`) 52 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; 53 | 54 | -- 2022-03-26 11:15:34 -------------------------------------------------------------------------------- /Soluciones/05-JavaLambdaFuncional/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /Soluciones/05-JavaLambdaFuncional/.idea/description.html: -------------------------------------------------------------------------------- 1 | Simple Java application that includes a class with main() method -------------------------------------------------------------------------------- /Soluciones/05-JavaLambdaFuncional/.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Soluciones/05-JavaLambdaFuncional/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Soluciones/05-JavaLambdaFuncional/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Soluciones/05-JavaLambdaFuncional/.idea/project-template.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Soluciones/05-JavaLambdaFuncional/JavaLambdaFuncional.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Soluciones/05-JavaLambdaFuncional/src/es/joseluisgs/dam/CalcImperativeA.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam; 2 | 3 | public class CalcImperativeA implements ICalcImperativeA { 4 | 5 | @Override 6 | public int suma(int a, int b) { 7 | return a + b; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Soluciones/05-JavaLambdaFuncional/src/es/joseluisgs/dam/CalcImperativeB.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam; 2 | 3 | public class CalcImperativeB implements ICalcImperativeB { 4 | 5 | @Override 6 | public void suma(int a, int b) { 7 | System.out.println("Suma: " + (a + b)); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Soluciones/05-JavaLambdaFuncional/src/es/joseluisgs/dam/CalcImperativeC.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam; 2 | 3 | public class CalcImperativeC implements ICalcImperativeC { 4 | @Override 5 | public void suma(int a, int b) { 6 | System.out.println("Suma:"); 7 | System.out.println("\tResultado: " + (a + b)); 8 | } 9 | 10 | @Override 11 | public void resta(int a, int b) { 12 | System.out.println("Resta:"); 13 | System.out.println("\tResultado: " + (a - b)); 14 | } 15 | 16 | @Override 17 | public void multiplicacion(int a, int b) { 18 | System.out.println("Multiplicacion:"); 19 | System.out.println("\tResultado: " + (a * b)); 20 | } 21 | 22 | @Override 23 | public void division(int a, int b) { 24 | System.out.println("Division:"); 25 | if (b != 0) { 26 | System.out.println("\tResultado: " + (a / b)); 27 | } else { 28 | System.err.println("\tError!"); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Soluciones/05-JavaLambdaFuncional/src/es/joseluisgs/dam/ICalcFunctional.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam; 2 | 3 | public interface ICalcFunctional { 4 | default int suma(int a, int b) { 5 | return a + b; 6 | } 7 | 8 | int multiplicacion(int a, int b); 9 | 10 | default int resta(int a, int b) { 11 | return a - b; 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /Soluciones/05-JavaLambdaFuncional/src/es/joseluisgs/dam/ICalcImperativeA.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam; 2 | 3 | public interface ICalcImperativeA { 4 | int suma(int a, int b); 5 | } 6 | -------------------------------------------------------------------------------- /Soluciones/05-JavaLambdaFuncional/src/es/joseluisgs/dam/ICalcImperativeB.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam; 2 | 3 | public interface ICalcImperativeB { 4 | void suma(int a, int b); 5 | } 6 | -------------------------------------------------------------------------------- /Soluciones/05-JavaLambdaFuncional/src/es/joseluisgs/dam/ICalcImperativeC.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam; 2 | 3 | public interface ICalcImperativeC { 4 | void suma(int a, int b); 5 | void resta(int a, int b); 6 | void multiplicacion(int a, int b); 7 | void division(int a, int b); 8 | } 9 | -------------------------------------------------------------------------------- /Soluciones/05-JavaLambdaFuncional/src/es/joseluisgs/dam/Main.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam; 2 | 3 | public class Main { 4 | 5 | public static void main(String[] args) { 6 | // Podemos usar funciones definidas... 7 | hola(); 8 | 9 | // podemos usar funciones anonimas o lambda, según las necesitemos 10 | Runnable r = () -> System.out.println("Hola"); 11 | r.run(); 12 | 13 | // Es anonima, no tiene nombre, solo la implementación. 14 | // De esta manera no hace falta declararla si solo la vamos a usar una vez 15 | 16 | // Pueden aceptar parámetros 17 | // Runnable r2 = (String s) -> System.out.println(s); 18 | 19 | /** 20 | * Concepto de caja negra (entrada salida sin muchas preocupaciones). 21 | * El código se vuelve más declarativo (programación declarativa) 22 | * y menos no imperativo (programación imperativa). 23 | * El código se vuelve más compacto, más simple, más fácil de leer y también más elegante. 24 | * Aportan una sintaxis básica. 25 | * Singularidad (SOLID o Responsabilidad única). 26 | * 27 | * (Lista de argumentos) -> { Cuerpo de la expresión lambda } 28 | * Si solo tiene un argumento, puede escribirse sin paréntesis 29 | * Si solo tiene una instruccion, puede escribirse sin llaves 30 | * a -> System.out.println(a) 31 | * () -> System.out.println("Hola") 32 | * () -> { System.out.println("Hola") } 33 | */ 34 | 35 | // Y si tenemos disitntas implementaciones de una misma interfaz?? 36 | CalcImperativeA calcA = new CalcImperativeA(); 37 | System.out.println("Suma: " + calcA.suma(1, 2)); 38 | CalcImperativeB calcB = new CalcImperativeB(); 39 | calcB.suma(1, 2); 40 | 41 | // Hecho con Lambda, no necesitamos la implementación, se la indicamos sobre 42 | // La marcha 43 | ICalcImperativeA calcLambdaA = (a, b) -> a + b; 44 | System.out.println("Suma: " + calcLambdaA.suma(1, 2)); 45 | ICalcImperativeB calcLambdaB = (a, b) -> { 46 | System.out.println("Suma: " + a + b); 47 | }; 48 | calcLambdaB.suma(1, 2); 49 | ICalcImperativeA calcLambdaA2 = (a, b) -> 2 * a + 5 + b; 50 | System.out.println("Suma: " + calcLambdaA2.suma(1, 2)); 51 | 52 | /** 53 | * Si utilizamos interfaces, las lambdas están desarrolladas para solamente 54 | * trabajar con un único método en su interior. 55 | * Si tenemos varios métodos, los requisitos a cumplir son: 56 | * Todos los métodos deben de tener la misma cantidad de parámetros. 57 | * Se deben declarar métodos a utilizar como default o static. 58 | * El resto de métodos quedaran inutilizados. 59 | * En definitiva: una función lambda es como una con un único método público. 60 | * El cual implementas su comportamiento sobre la marcha. 61 | */ 62 | 63 | CalcImperativeC calcC = new CalcImperativeC(); 64 | calcC.suma(1, 3); 65 | calcC.resta(1, 3); 66 | calcC.division(1, 3); 67 | calcC.multiplicacion(1, 3); 68 | 69 | ICalcFunctional calcLambdaC = (a, b) -> a * b; // Este es la multiplicación 70 | System.out.println("Total suma: " + calcLambdaC.suma(2, 3)); 71 | System.out.println("Total resta: " + calcLambdaC.resta(2, 3)); 72 | System.out.println("Total multiplicacion: " + calcLambdaC.multiplicacion(2, 3)); 73 | 74 | ICalcFunctional calcLambdaC2 = (a, b) -> 2 * a * 2 * b; 75 | System.out.println("Total multiplicacion: " + calcLambdaC2.multiplicacion(2, 3)); 76 | } 77 | 78 | 79 | private static void hola() { 80 | System.out.println("Hola"); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /Soluciones/06-JavaStreamAPI/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /Soluciones/06-JavaStreamAPI/.idea/description.html: -------------------------------------------------------------------------------- 1 | Simple Java application that includes a class with main() method -------------------------------------------------------------------------------- /Soluciones/06-JavaStreamAPI/.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Soluciones/06-JavaStreamAPI/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Soluciones/06-JavaStreamAPI/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Soluciones/06-JavaStreamAPI/.idea/project-template.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Soluciones/06-JavaStreamAPI/JavaStreamAPI.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Soluciones/06-JavaStreamAPI/src/es/joseluisgs/dam/Persona.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam; 2 | 3 | public class Persona { 4 | private String nombre; 5 | private int edad; 6 | 7 | public Persona(String nombre, int edad) { 8 | this.nombre = nombre; 9 | this.edad = edad; 10 | } 11 | 12 | public String getNombre() { 13 | return nombre; 14 | } 15 | 16 | public void setNombre(String nombre) { 17 | this.nombre = nombre; 18 | } 19 | 20 | public int getEdad() { 21 | return edad; 22 | } 23 | 24 | public void setEdad(int edad) { 25 | this.edad = edad; 26 | } 27 | 28 | @Override 29 | public String toString() { 30 | return "Persona{" + 31 | "nombre='" + nombre + '\'' + 32 | ", edad=" + edad + 33 | '}'; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Soluciones/07-StreamEjemplos/.gitignore: -------------------------------------------------------------------------------- 1 | /out -------------------------------------------------------------------------------- /Soluciones/07-StreamEjemplos/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Datasource local storage ignored files 5 | /dataSources/ 6 | /dataSources.local.xml 7 | # Editor-based HTTP Client requests 8 | /httpRequests/ 9 | -------------------------------------------------------------------------------- /Soluciones/07-StreamEjemplos/.idea/description.html: -------------------------------------------------------------------------------- 1 | Simple Java application that includes a class with main() method -------------------------------------------------------------------------------- /Soluciones/07-StreamEjemplos/.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Soluciones/07-StreamEjemplos/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Soluciones/07-StreamEjemplos/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Soluciones/07-StreamEjemplos/.idea/project-template.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Soluciones/07-StreamEjemplos/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Soluciones/07-StreamEjemplos/02-Stream.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Soluciones/07-StreamEjemplos/src/es/joseluisgs/dam/Main.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam; 2 | 3 | public class Main { 4 | public static void main(String[] args) { 5 | // ConsultasAlumnos alumnos = new ConsultasAlumnos(); 6 | ConsultasCanciones canciones = new ConsultasCanciones(); 7 | // ConsultasProductos productos = new ConsultasProductos(); 8 | } 9 | 10 | 11 | } -------------------------------------------------------------------------------- /Soluciones/07-StreamEjemplos/src/es/joseluisgs/dam/model/Alumno.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.model; 2 | 3 | public class Alumno { 4 | private int id; 5 | private String dni; 6 | private String nombre; 7 | private String apellidos; 8 | private String nombreCurso; 9 | private double nota; 10 | private int edad; 11 | 12 | public Alumno() { 13 | 14 | } 15 | 16 | public Alumno(int id, String dni, String nombre, String apellidos, String nombreCurso, double nota, int edad) { 17 | this.id = id; 18 | this.dni = dni; 19 | this.nombre = nombre; 20 | this.apellidos = apellidos; 21 | this.nombreCurso = nombreCurso; 22 | this.nota = nota; 23 | this.edad = edad; 24 | } 25 | 26 | public int getId() { 27 | return id; 28 | } 29 | 30 | public void setId(int id) { 31 | this.id = id; 32 | } 33 | 34 | public String getDni() { 35 | return dni; 36 | } 37 | 38 | public void setDni(String dni) { 39 | this.dni = dni; 40 | } 41 | 42 | public String getNombre() { 43 | return nombre; 44 | } 45 | 46 | public void setNombre(String nombre) { 47 | this.nombre = nombre; 48 | } 49 | 50 | public String getApellidos() { 51 | return apellidos; 52 | } 53 | 54 | public void setApellidos(String apellidos) { 55 | this.apellidos = apellidos; 56 | } 57 | 58 | public String getNombreCurso() { 59 | return nombreCurso; 60 | } 61 | 62 | public void setNombreCurso(String nombreCurso) { 63 | this.nombreCurso = nombreCurso; 64 | } 65 | 66 | public double getNota() { 67 | return nota; 68 | } 69 | 70 | public void setNota(double nota) { 71 | this.nota = nota; 72 | } 73 | 74 | public int getEdad() { 75 | return edad; 76 | } 77 | 78 | public void setEdad(int edad) { 79 | this.edad = edad; 80 | } 81 | 82 | @Override 83 | public String toString() { 84 | return id+" | "+dni+" | "+ nombre +" | "+apellidos+" | Curso: "+nombreCurso+" | Nota: "+nota+" | Edad: "+edad; 85 | } 86 | } -------------------------------------------------------------------------------- /Soluciones/07-StreamEjemplos/src/es/joseluisgs/dam/model/Cancion.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.model; 2 | 3 | public class Cancion { 4 | String titulo; 5 | String cantante; 6 | 7 | public Cancion(String titulo, String cantante) { 8 | this.titulo = titulo; 9 | this.cantante = cantante; 10 | } 11 | 12 | public String getTitulo() { 13 | return titulo; 14 | } 15 | 16 | public void setTitulo(String titulo) { 17 | this.titulo = titulo; 18 | } 19 | 20 | public String getCantante() { 21 | return cantante; 22 | } 23 | 24 | public void setCantante(String cantante) { 25 | this.cantante = cantante; 26 | } 27 | 28 | @Override 29 | public String toString() { 30 | return "Cancion{" + 31 | "titulo='" + titulo + '\'' + 32 | ", cantante='" + cantante + '\'' + 33 | '}'; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Soluciones/07-StreamEjemplos/src/es/joseluisgs/dam/model/Product.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.model; 2 | 3 | public class Product implements Comparable { 4 | private int id; 5 | private String name; 6 | private int supplier; 7 | private int category; 8 | private double unitPrice; 9 | private int unitsInStock; 10 | 11 | public int getId() { 12 | return id; 13 | } 14 | 15 | public void setId(int id) { 16 | this.id = id; 17 | } 18 | 19 | public String getName() { 20 | return name; 21 | } 22 | 23 | public void setName(String name) { 24 | this.name = name; 25 | } 26 | 27 | public int getSupplier() { 28 | return supplier; 29 | } 30 | 31 | public void setSupplier(int supplier) { 32 | this.supplier = supplier; 33 | } 34 | 35 | public int getCategory() { 36 | return category; 37 | } 38 | 39 | public void setCategory(int category) { 40 | this.category = category; 41 | } 42 | 43 | public double getUnitPrice() { 44 | return unitPrice; 45 | } 46 | 47 | public void setUnitPrice(double unitPrice) { 48 | this.unitPrice = unitPrice; 49 | } 50 | 51 | public int getUnitsInStock() { 52 | return unitsInStock; 53 | } 54 | 55 | public void setUnitsInStock(int unitsInStock) { 56 | this.unitsInStock = unitsInStock; 57 | } 58 | 59 | @Override 60 | public String toString() { 61 | return "Product{" + 62 | "id=" + id + 63 | ", name='" + name + '\'' + 64 | ", supplier=" + supplier + 65 | ", category=" + category + 66 | ", unitPrice=" + unitPrice + 67 | ", unitsInStock=" + unitsInStock + 68 | '}'; 69 | } 70 | 71 | 72 | @Override 73 | public int compareTo(Product p) { 74 | if (this.getUnitsInStock() < p.getUnitsInStock()) 75 | return -1; 76 | else if (this.getUnitsInStock() > p.getUnitsInStock()) 77 | return 1; 78 | else 79 | return 0; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /Soluciones/07-StreamEjemplos/src/es/joseluisgs/dam/utils/Util.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.utils; 2 | 3 | import es.joseluisgs.dam.model.Product; 4 | 5 | import java.io.File; 6 | import java.io.IOException; 7 | import java.nio.charset.StandardCharsets; 8 | import java.nio.file.Files; 9 | import java.nio.file.Path; 10 | import java.nio.file.Paths; 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | import java.util.StringTokenizer; 14 | import java.util.stream.Collectors; 15 | 16 | public class Util { 17 | 18 | public static List getProducts() throws IOException { 19 | // Cargamos el archivo ubicado en la carpeta data 20 | String DATA_FILE = "products.csv"; 21 | String WORKING_DIRECTORY = System.getProperty("user.dir"); 22 | Path path = Paths.get(WORKING_DIRECTORY + File.separator + "data" + File.separator + DATA_FILE); 23 | // Puedo leer todo el fichero del tiron. Cuidado si no es muy grande!! 24 | final List lineas = Files.readAllLines(path, StandardCharsets.UTF_8); 25 | // lines.forEach(System.out::println); 26 | // List products = new ArrayList<>(); 27 | // Me he saltado la primera línea del archivo, porque es la cabecera 28 | /*for (int i = 1; i < lineas.size(); i++) { 29 | Product product = parseProduct(lineas.get(i)); 30 | products.add(product); 31 | }*/ 32 | // Mapeando cada línea a un objeto Product 33 | // Usamos Skip para saltarnos la primera línea 34 | return lineas.stream().skip(1).map(Util::parseProduct).collect(Collectors.toList()); 35 | 36 | } 37 | 38 | public static List getProducts2() throws IOException { 39 | // Cargamos el archivo ubicado en la carpeta data 40 | String DATA_FILE = "products.csv"; 41 | String WORKING_DIRECTORY = System.getProperty("user.dir"); 42 | Path path = Paths.get(WORKING_DIRECTORY + File.separator + "data" + File.separator + DATA_FILE); 43 | // Puedo leer todo el fichero liena a linea usando API Stream y Programación Funcional 44 | // Mapeando cada línea a un objeto Product 45 | // Usamos Skip para saltarnos la primera línea 46 | return Files.lines(path, StandardCharsets.UTF_8) 47 | .skip(1).map(Util::parseProduct).collect(Collectors.toList()); 48 | 49 | } 50 | 51 | private static Product parseProduct(String linea) { 52 | String[] campos = linea.split(","); 53 | Product product = new Product(); 54 | product.setId(Integer.parseInt(campos[0])); 55 | product.setName(campos[1]); 56 | product.setSupplier(Integer.parseInt(campos[2])); 57 | product.setCategory(Integer.parseInt(campos[3])); 58 | product.setUnitPrice(Double.parseDouble(campos[5])); 59 | product.setUnitsInStock(Integer.parseInt(campos[6])); 60 | return product; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Soluciones/08-MVC-Paises-BBDD-Optional-Functional/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.toptal.com/developers/gitignore/api/maven,java,intellij+all 3 | # Edit at https://www.toptal.com/developers/gitignore?templates=maven,java,intellij+all 4 | 5 | ### Intellij+all ### 6 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 7 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 8 | 9 | # User-specific stuff 10 | .idea/**/workspace.xml 11 | .idea/**/tasks.xml 12 | .idea/**/usage.statistics.xml 13 | .idea/**/dictionaries 14 | .idea/**/shelf 15 | 16 | # AWS User-specific 17 | .idea/**/aws.xml 18 | 19 | # Generated files 20 | .idea/**/contentModel.xml 21 | 22 | # Sensitive or high-churn files 23 | .idea/**/dataSources/ 24 | .idea/**/dataSources.ids 25 | .idea/**/dataSources.local.xml 26 | .idea/**/sqlDataSources.xml 27 | .idea/**/dynamic.xml 28 | .idea/**/uiDesigner.xml 29 | .idea/**/dbnavigator.xml 30 | 31 | # Gradle 32 | .idea/**/gradle.xml 33 | .idea/**/libraries 34 | 35 | # Gradle and Maven with auto-import 36 | # When using Gradle or Maven with auto-import, you should exclude module files, 37 | # since they will be recreated, and may cause churn. Uncomment if using 38 | # auto-import. 39 | # .idea/artifacts 40 | # .idea/compiler.xml 41 | # .idea/jarRepositories.xml 42 | # .idea/modules.xml 43 | # .idea/*.iml 44 | # .idea/modules 45 | # *.iml 46 | # *.ipr 47 | 48 | # CMake 49 | cmake-build-*/ 50 | 51 | # Mongo Explorer plugin 52 | .idea/**/mongoSettings.xml 53 | 54 | # File-based project format 55 | *.iws 56 | 57 | # IntelliJ 58 | out/ 59 | 60 | # mpeltonen/sbt-idea plugin 61 | .idea_modules/ 62 | 63 | # JIRA plugin 64 | atlassian-ide-plugin.xml 65 | 66 | # Cursive Clojure plugin 67 | .idea/replstate.xml 68 | 69 | # SonarLint plugin 70 | .idea/sonarlint/ 71 | 72 | # Crashlytics plugin (for Android Studio and IntelliJ) 73 | com_crashlytics_export_strings.xml 74 | crashlytics.properties 75 | crashlytics-build.properties 76 | fabric.properties 77 | 78 | # Editor-based Rest Client 79 | .idea/httpRequests 80 | 81 | # Android studio 3.1+ serialized cache file 82 | .idea/caches/build_file_checksums.ser 83 | 84 | ### Intellij+all Patch ### 85 | # Ignore everything but code style settings and run configurations 86 | # that are supposed to be shared within teams. 87 | 88 | .idea/* 89 | 90 | !.idea/codeStyles 91 | !.idea/runConfigurations 92 | 93 | ### Java ### 94 | # Compiled class file 95 | *.class 96 | 97 | # Log file 98 | *.log 99 | 100 | # BlueJ files 101 | *.ctxt 102 | 103 | # Mobile Tools for Java (J2ME) 104 | .mtj.tmp/ 105 | 106 | # Package Files # 107 | *.jar 108 | *.war 109 | *.nar 110 | *.ear 111 | *.zip 112 | *.tar.gz 113 | *.rar 114 | 115 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 116 | hs_err_pid* 117 | replay_pid* 118 | 119 | ### Maven ### 120 | target/ 121 | pom.xml.tag 122 | pom.xml.releaseBackup 123 | pom.xml.versionsBackup 124 | pom.xml.next 125 | release.properties 126 | dependency-reduced-pom.xml 127 | buildNumber.properties 128 | .mvn/timing.properties 129 | # https://github.com/takari/maven-wrapper#usage-without-binary-jar 130 | .mvn/wrapper/maven-wrapper.jar 131 | 132 | # Eclipse m2e generated files 133 | # Eclipse Core 134 | .project 135 | # JDT-specific (Eclipse Java Development Tools) 136 | .classpath 137 | 138 | # End of https://www.toptal.com/developers/gitignore/api/maven,java,intellij+all 139 | -------------------------------------------------------------------------------- /Soluciones/08-MVC-Paises-BBDD-Optional-Functional/SecuenciaPaises.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Soluciones/08-MVC-Paises-BBDD-Optional-Functional/docker/docker-compose.yml: -------------------------------------------------------------------------------- 1 | # Indicamos la versión 2 | # Para iniciar docker-compose up -d 3 | version: '3.7' 4 | 5 | # Mis servicios 6 | # Iniciamos los servicios 7 | services: 8 | # MARIA DB 9 | mariadb: 10 | build: ./mariadb 11 | image: mariadb 12 | container_name: mariadb 13 | ports: 14 | - 3306:3306 15 | expose: 16 | - 3306 17 | volumes: 18 | - mariadb-volume:/var/lib/mysql 19 | networks: 20 | - mariadb-network 21 | # restart: always 22 | 23 | # ADMIN MARIADB 24 | adminer: 25 | image: adminer 26 | container_name: adminer 27 | # restart: always 28 | ports: 29 | - 8080:8080 30 | networks: 31 | - mariadb-network 32 | depends_on: 33 | - mariadb 34 | 35 | # Mi volumenes de datos compartidos 36 | volumes: 37 | mariadb-volume: 38 | 39 | # Si queremos que tengan una red propia a otros contenedores 40 | networks: 41 | mariadb-network: 42 | driver: bridge 43 | -------------------------------------------------------------------------------- /Soluciones/08-MVC-Paises-BBDD-Optional-Functional/docker/mariadb/Dockerfile: -------------------------------------------------------------------------------- 1 | # MariaDB 2 | FROM yobasystems/alpine-mariadb:10 3 | # FROM mariadb:10.5 4 | 5 | # Configuramos BBDD 6 | ENV MYSQL_ROOT_PASSWORD 123 7 | ENV MYSQL_USER dam 8 | ENV MYSQL_PASSWORD dam1234 9 | ENV MYSQL_DATABASE dam 10 | 11 | # Copiamos los ficheros sql para que se ejecuten 12 | COPY ./sql /docker-entrypoint-initdb.d/ -------------------------------------------------------------------------------- /Soluciones/08-MVC-Paises-BBDD-Optional-Functional/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | groupId 8 | SecuenciaPaises 9 | 1.0-SNAPSHOT 10 | 11 | 12 | 11 13 | 11 14 | 15 | 16 | 17 | 18 | 19 | com.google.code.gson 20 | gson 21 | 2.9.0 22 | 23 | 24 | 25 | org.projectlombok 26 | lombok 27 | RELEASE 28 | compile 29 | 30 | 31 | 32 | org.mariadb.jdbc 33 | mariadb-java-client 34 | 3.0.3 35 | 36 | 37 | 38 | org.mybatis 39 | mybatis 40 | 3.5.9 41 | 42 | 43 | 44 | org.junit.jupiter 45 | junit-jupiter 46 | RELEASE 47 | test 48 | 49 | 50 | 51 | org.mockito 52 | mockito-core 53 | 4.4.0 54 | test 55 | 56 | 57 | org.mockito 58 | mockito-junit-jupiter 59 | 4.4.0 60 | test 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /Soluciones/08-MVC-Paises-BBDD-Optional-Functional/src/main/java/es/joseluisgs/dam/Main.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam; 2 | 3 | import es.joseluisgs.dam.controllers.DataBaseManager; 4 | import es.joseluisgs.dam.utils.ApplicationProperties; 5 | import es.joseluisgs.dam.views.PaisView; 6 | 7 | import java.io.File; 8 | import java.io.FileNotFoundException; 9 | import java.sql.ResultSet; 10 | import java.sql.SQLException; 11 | import java.util.Optional; 12 | 13 | /** 14 | * Ejemplo de Patrón MVC para CRUD de países. 15 | * Siguiendo los diagramas de Secuencias en Clase 16 | * Modelo: Pais, gestionador por PaisRepository 17 | * Vista: La propia consola: comunicacion con el usuario 18 | * Controlador: PaisController, controla, cómo y de qué manera el modelo, repositorio y la vista interactúan 19 | * Como vista que soy, soy lo último y gestiono las excepciones con Try/Catch 20 | */ 21 | public class Main { 22 | public static void main(String[] args) { 23 | checkServer(); 24 | initData(); 25 | PaisView view = PaisView.getInstance(); 26 | view.menu(); 27 | 28 | } 29 | 30 | private static void checkServer() { 31 | System.out.println("Comprobamos la conexión al Servidor BD"); 32 | DataBaseManager controller = DataBaseManager.getInstance(); 33 | try { 34 | controller.open(); 35 | Optional rs = controller.select("SELECT 'Hello world'"); 36 | if (rs.isPresent()) { 37 | rs.get().first(); 38 | controller.close(); 39 | System.out.println("Conexión con la Base de Datos realizada con éxito"); 40 | } 41 | } catch (SQLException e) { 42 | System.err.println("Error al conectar al servidor de Base de Datos: " + e.getMessage()); 43 | System.exit(1); 44 | } 45 | } 46 | 47 | private static void initData() { 48 | ApplicationProperties properties = new ApplicationProperties(); 49 | boolean init = Boolean.parseBoolean(properties.readProperty("database.initdata")); 50 | if (init) { 51 | System.out.println("Iniciamos los datos de ejemplo de la Base de Datos"); 52 | DataBaseManager controller = DataBaseManager.getInstance(); 53 | String dataPath = "sql" + File.separator + "init-db.sql"; 54 | try { 55 | var sqlFile = Main.class.getClassLoader().getResource(dataPath).getPath(); 56 | System.out.println(dataPath); 57 | controller.open(); 58 | controller.initData(sqlFile, false); 59 | controller.close(); 60 | System.out.println("Datos inicializados con éxito"); 61 | } catch (SQLException e) { 62 | System.err.println("Error al conectar al servidor de Base de Datos: " + e.getMessage()); 63 | System.exit(1); 64 | } catch (FileNotFoundException e) { 65 | System.err.println("Error al leer el fichero de datos iniciales: " + e.getMessage()); 66 | System.exit(1); 67 | } 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Soluciones/08-MVC-Paises-BBDD-Optional-Functional/src/main/java/es/joseluisgs/dam/controllers/AcuerdoController.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.controllers; 2 | 3 | import es.joseluisgs.dam.exceptions.AcuerdoException; 4 | import es.joseluisgs.dam.models.Acuerdo; 5 | import es.joseluisgs.dam.models.LineaAcuerdo; 6 | import es.joseluisgs.dam.models.Pais; 7 | import es.joseluisgs.dam.repositories.acuerdos.IAcuerdoRepository; 8 | 9 | import java.sql.SQLException; 10 | import java.time.LocalDate; 11 | import java.time.LocalDateTime; 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | 15 | public class AcuerdoController { 16 | private final IAcuerdoRepository acuerdosRepository; 17 | 18 | public AcuerdoController(IAcuerdoRepository acuerdosRepository) { 19 | this.acuerdosRepository = acuerdosRepository; 20 | } 21 | 22 | /** 23 | * Crea un acuerdo con los datos pasados por parámetro. 24 | * 25 | * @param nombre Nombre del acuerdo. 26 | * @param paises Paises que participan en el acuerdo. 27 | * @return El acuerdo creado. 28 | * @throws SQLException Si hay un error en la base de datos. 29 | */ 30 | public Acuerdo createAcuerdo(String nombre, List paises) throws SQLException { 31 | List lineas = new ArrayList<>(); 32 | for (Pais pais : paises) { 33 | lineas.add(new LineaAcuerdo(pais, LocalDate.now().getYear())); 34 | } 35 | Acuerdo acuerdo = new Acuerdo(0, nombre, LocalDateTime.now(), lineas); 36 | return acuerdosRepository.save(acuerdo).get(); 37 | } 38 | 39 | /** 40 | * Obtiene un acuerdo por su id. 41 | * 42 | * @param id Id del acuerdo. 43 | * @return El acuerdo. 44 | * @throws AcuerdoException Si no existe el acuerdo. 45 | * @throws SQLException Si hay un error en la base de datos. 46 | */ 47 | public Acuerdo getAcuerdoById(int id) throws AcuerdoException, SQLException { 48 | return acuerdosRepository.findById(id).orElseThrow(() -> new AcuerdoException("No existe el acuerdo con id " + id)); 49 | } 50 | 51 | /** 52 | * Obtiene todos los acuerdos. 53 | * 54 | * @return Lista de acuerdos. 55 | * @throws SQLException Si hay un error en la base de datos. 56 | */ 57 | public List getAllAcuerdos() throws SQLException { 58 | return acuerdosRepository.findAll(); 59 | } 60 | 61 | /** 62 | * Elimina un acuerdo por su id. 63 | * 64 | * @param id Id del acuerdo. 65 | * @return El acuerdo eliminado. 66 | * @throws SQLException Si hay un error en la base de datos. 67 | */ 68 | public Acuerdo deleteAcuerdo(int id) throws SQLException { 69 | return acuerdosRepository.delete(id).get(); 70 | } 71 | 72 | /** 73 | * Actualiza un acuerdo. 74 | * 75 | * @param id Id del acuerdo. 76 | * @param acuerdo Acuerdo con los nuevos datos. 77 | * @return El acuerdo actualizado. 78 | * @throws SQLException Si hay un error en la base de datos. 79 | */ 80 | public Acuerdo updateAcuerdo(int id, Acuerdo acuerdo) throws SQLException { 81 | return acuerdosRepository.update(id, acuerdo).get(); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Soluciones/08-MVC-Paises-BBDD-Optional-Functional/src/main/java/es/joseluisgs/dam/controllers/BackupManager.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.controllers; 2 | 3 | import es.joseluisgs.dam.models.Acuerdo; 4 | import es.joseluisgs.dam.models.Backup; 5 | import es.joseluisgs.dam.models.Pais; 6 | import es.joseluisgs.dam.repositories.acuerdos.IAcuerdoRepository; 7 | import es.joseluisgs.dam.repositories.paises.IPaisRepository; 8 | import es.joseluisgs.dam.services.Storage.IStorageBackup; 9 | 10 | import java.sql.SQLException; 11 | 12 | public class BackupManager { 13 | private final IPaisRepository paisRepository; 14 | private final IAcuerdoRepository acuerdoRepository; 15 | private final IStorageBackup storageBackup; 16 | 17 | public BackupManager(IPaisRepository paisRepository, IAcuerdoRepository acuerdoRepository, IStorageBackup storageBackup) { 18 | this.paisRepository = paisRepository; 19 | this.acuerdoRepository = acuerdoRepository; 20 | this.storageBackup = storageBackup; 21 | } 22 | 23 | 24 | /** 25 | * Importa los datos desde un fichero de backup 26 | */ 27 | public void importarDatos() throws SQLException { 28 | System.out.println("Importando datos de Backup: " + storageBackup.getStoragePath()); 29 | var backup = storageBackup.load(); 30 | System.out.println("Importando Paises..."); 31 | if (backup.getPaises().size() > 0) { 32 | paisRepository.clearAll(); 33 | for (Pais pais : backup.getPaises()) { 34 | paisRepository.save(pais); 35 | } 36 | System.out.println("Paises importados con éxito al repositorio: " + backup.getPaises().size() + " paises"); 37 | } else { 38 | System.out.println("Ha existido un problema al importar los datos de Paises"); 39 | } 40 | System.out.println("Importando Acuerdos..."); 41 | if (backup.getAcuerdos().size() > 0) { 42 | acuerdoRepository.clearAll(); 43 | for (Acuerdo acuerdo : backup.getAcuerdos()) { 44 | acuerdoRepository.save(acuerdo); 45 | } 46 | System.out.println("Acuerdos importados con éxito al repositorio: " + backup.getAcuerdos().size() + " acuerdos"); 47 | } else { 48 | System.out.println("Ha existido un problema al importar los datos de Acuerdos"); 49 | } 50 | } 51 | 52 | 53 | /** 54 | * Exporta los datos desde un fichero de Backup 55 | */ 56 | public void exportarDatos() throws SQLException { 57 | System.out.println("Exportando datos a fichero de Backup..."); 58 | var paises = paisRepository.findAll(); 59 | var acuerdos = acuerdoRepository.findAll(); 60 | Backup backup = Backup.builder() 61 | .paises(paises) 62 | .acuerdos(acuerdos) 63 | .build(); 64 | var res = storageBackup.save(backup); 65 | if (res) { 66 | System.out.println("Exportando " + backup.getPaises().size() + " paises"); 67 | System.out.println("Exportando " + backup.getAcuerdos().size() + " acuerdos"); 68 | System.out.println("Datos exportados con éxito en: " + storageBackup.getStoragePath()); 69 | } else { 70 | System.out.println("Ha existido un problema al exportar los datos"); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Soluciones/08-MVC-Paises-BBDD-Optional-Functional/src/main/java/es/joseluisgs/dam/exceptions/AcuerdoException.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.exceptions; 2 | 3 | /** 4 | * Excepción asociada al comprotamiento de gestion de Acuerdos. 5 | */ 6 | public class AcuerdoException extends Exception { 7 | 8 | public AcuerdoException(String mensaje) { 9 | super(mensaje); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Soluciones/08-MVC-Paises-BBDD-Optional-Functional/src/main/java/es/joseluisgs/dam/exceptions/PaisException.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.exceptions; 2 | 3 | /** 4 | * Excepción asociada al comprotamiento de gestion de paises. 5 | */ 6 | public class PaisException extends Exception { 7 | 8 | public PaisException(String mensaje) { 9 | super(mensaje); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Soluciones/08-MVC-Paises-BBDD-Optional-Functional/src/main/java/es/joseluisgs/dam/models/Acuerdo.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.models; 2 | 3 | import es.joseluisgs.dam.utils.Formatter; 4 | import lombok.Data; 5 | 6 | import java.time.LocalDateTime; 7 | import java.util.List; 8 | 9 | @Data 10 | public class Acuerdo { 11 | private final LocalDateTime fecha; 12 | private String nombre; 13 | private double aportacion; 14 | private List lineas; 15 | private int id; 16 | 17 | 18 | public Acuerdo(int id, String nombre, LocalDateTime fecha, List lineas) { 19 | this.id = id; 20 | this.nombre = nombre; 21 | this.fecha = fecha; 22 | this.lineas = lineas; 23 | this.aportacion = calcularAportacion(); 24 | } 25 | 26 | public Acuerdo(int id, String nombre, LocalDateTime fecha, double aportacion, List lineas) { 27 | this.id = id; 28 | this.nombre = nombre; 29 | this.fecha = fecha; 30 | this.lineas = lineas; 31 | this.aportacion = aportacion; 32 | } 33 | 34 | private double calcularAportacion() { 35 | double total = 0; 36 | for (LineaAcuerdo linea : lineas) { 37 | total += linea.getSubvencion(); 38 | } 39 | return total; 40 | } 41 | 42 | public Integer getId() { 43 | return id; 44 | } 45 | 46 | @Override 47 | public String toString() { 48 | // Puedes imprimir listas como Arrays.toString(lista)) 49 | return "Acuerdo{" + "id=" + id + ", nombre=" + nombre + ", fecha=" 50 | + Formatter.dateParser(fecha) + ", lineas=" + lineas + ", aportacion=" + Formatter.moneyParser(aportacion) + '}'; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /Soluciones/08-MVC-Paises-BBDD-Optional-Functional/src/main/java/es/joseluisgs/dam/models/Backup.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.models; 2 | 3 | import lombok.Builder; 4 | 5 | import java.time.LocalDateTime; 6 | import java.util.List; 7 | 8 | @Builder 9 | public class Backup { 10 | private final String createdAt = LocalDateTime.now().toString(); 11 | private List paises; 12 | private List acuerdos; 13 | 14 | public List getPaises() { 15 | return paises; 16 | } 17 | 18 | public List getAcuerdos() { 19 | return acuerdos; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Soluciones/08-MVC-Paises-BBDD-Optional-Functional/src/main/java/es/joseluisgs/dam/models/LineaAcuerdo.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.models; 2 | 3 | import es.joseluisgs.dam.utils.Formatter; 4 | import lombok.Data; 5 | 6 | @Data 7 | public class LineaAcuerdo { 8 | private final Pais pais; 9 | private final int año; 10 | private final double subvencion; 11 | 12 | public LineaAcuerdo(Pais pais, int año) { 13 | this.pais = pais; 14 | this.año = año; 15 | this.subvencion = pais.getPresupuesto() * 0.25; 16 | } 17 | 18 | public LineaAcuerdo(Pais pais, int año, double subvencion) { 19 | this.pais = pais; 20 | this.año = año; 21 | this.subvencion = subvencion; 22 | } 23 | 24 | @Override 25 | public String toString() { 26 | return "LineaAcuerdo{" + "pais=" + pais.getNombre() + ", año=" + año + ", subvencion=" + Formatter.moneyParser(subvencion) + '}'; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Soluciones/08-MVC-Paises-BBDD-Optional-Functional/src/main/java/es/joseluisgs/dam/repositories/CRUDRepository.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.repositories; 2 | 3 | import java.sql.SQLException; 4 | import java.util.List; 5 | import java.util.Optional; 6 | 7 | public interface CRUDRepository { 8 | /** 9 | * Devuelve una lista de todos los elementos del repositorio 10 | * 11 | * @return Lista de elementos 12 | * @throws SQLException Si hay algún error en la base de datos 13 | */ 14 | List findAll() throws SQLException; 15 | 16 | /** 17 | * Devuelve un Optional del elemento dada una id 18 | * 19 | * @param id Id del elemento 20 | * @return Optional del elemento 21 | * @throws SQLException Si hay algún error en la base de datos 22 | */ 23 | Optional findById(ID id) throws SQLException; 24 | 25 | /** 26 | * Inserta un elemento en el repositorio 27 | * 28 | * @param entity Elemento a insertar 29 | * @return Elemento insertado 30 | * @throws SQLException Si hay algún error en la base de datos 31 | */ 32 | Optional save(T entity) throws SQLException; 33 | 34 | /** 35 | * Actualiza un elemento en el repositorio 36 | * 37 | * @param id Id del elemento a actualizar 38 | * @param entity Elemento a actualizar 39 | * @return Elemento actualizado 40 | * @throws SQLException Si hay algún error en la base de datos 41 | */ 42 | Optional update(ID id, T entity) throws SQLException; 43 | 44 | /** 45 | * Elimina un elemento del repositorio 46 | * 47 | * @param id Id del elemento a eliminar 48 | * @return Elemento eliminado 49 | * @throws SQLException Si hay algún error en la base de datos 50 | */ 51 | Optional delete(ID id) throws SQLException; 52 | } 53 | -------------------------------------------------------------------------------- /Soluciones/08-MVC-Paises-BBDD-Optional-Functional/src/main/java/es/joseluisgs/dam/repositories/acuerdos/IAcuerdoRepository.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.repositories.acuerdos; 2 | 3 | import es.joseluisgs.dam.models.Acuerdo; 4 | import es.joseluisgs.dam.repositories.CRUDRepository; 5 | 6 | import java.sql.SQLException; 7 | 8 | public interface IAcuerdoRepository extends CRUDRepository { 9 | 10 | void clearAll() throws SQLException; 11 | } 12 | -------------------------------------------------------------------------------- /Soluciones/08-MVC-Paises-BBDD-Optional-Functional/src/main/java/es/joseluisgs/dam/repositories/paises/IPaisRepository.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.repositories.paises; 2 | 3 | import es.joseluisgs.dam.models.Pais; 4 | import es.joseluisgs.dam.repositories.CRUDRepository; 5 | 6 | import java.sql.SQLException; 7 | import java.util.Optional; 8 | 9 | // Toda nueva funcionalidad se extiende de la interfaz SOLID 10 | public interface IPaisRepository extends CRUDRepository { 11 | 12 | Optional findByNombre(String nombre) throws SQLException; 13 | 14 | void clearAll() throws SQLException; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Soluciones/08-MVC-Paises-BBDD-Optional-Functional/src/main/java/es/joseluisgs/dam/services/Storage/IStorage.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.services.Storage; 2 | 3 | public interface IStorage { 4 | 5 | /** 6 | * Salva los elementos almacenados en item. 7 | * 8 | * @param item Elementos a almacenar. 9 | * @return true si se ha almacenado correctamente, false en caso contrario. 10 | */ 11 | boolean save(T item); 12 | 13 | /** 14 | * Le el almacenado y lo devuelve en un item T. 15 | * 16 | * @return Elementos almacenados. 17 | */ 18 | T load(); 19 | 20 | /** 21 | * Devuelve el path de la ubicación del almacenado. 22 | * 23 | * @return Path de la ubicación del almacenado. 24 | */ 25 | String getStoragePath(); 26 | } 27 | -------------------------------------------------------------------------------- /Soluciones/08-MVC-Paises-BBDD-Optional-Functional/src/main/java/es/joseluisgs/dam/services/Storage/IStorageBackup.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.services.Storage; 2 | 3 | import es.joseluisgs.dam.models.Backup; 4 | 5 | public interface IStorageBackup extends IStorage { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /Soluciones/08-MVC-Paises-BBDD-Optional-Functional/src/main/java/es/joseluisgs/dam/services/Storage/StorageBackupJsonFile.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.services.Storage; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.GsonBuilder; 5 | import com.google.gson.reflect.TypeToken; 6 | import es.joseluisgs.dam.models.Backup; 7 | 8 | import java.io.*; 9 | import java.nio.file.Files; 10 | import java.nio.file.Path; 11 | import java.nio.file.Paths; 12 | 13 | public class StorageBackupJsonFile implements IStorageBackup { 14 | private static StorageBackupJsonFile instance; 15 | 16 | private final Path currentRelativePath = Paths.get(""); 17 | private final String ruta = currentRelativePath.toAbsolutePath().toString(); 18 | private final String dir = ruta + File.separator + "data"; 19 | private final String backupFile = dir + File.separator + "backup.json"; 20 | 21 | 22 | private StorageBackupJsonFile() { 23 | init(); 24 | } 25 | 26 | public static StorageBackupJsonFile getInstance() { 27 | if (instance == null) { 28 | instance = new StorageBackupJsonFile(); 29 | } 30 | return instance; 31 | } 32 | 33 | private void init() { 34 | Path path = Paths.get(dir); 35 | if (!Files.exists(path)) { 36 | try { 37 | Files.createDirectories(path); 38 | } catch (IOException e) { 39 | System.out.println("Error: " + e.getMessage()); 40 | } 41 | } 42 | } 43 | 44 | @Override 45 | public boolean save(Backup backup) { 46 | Gson gson = new GsonBuilder().setPrettyPrinting().create(); 47 | boolean result = false; 48 | PrintWriter f = null; 49 | try { 50 | f = new PrintWriter(new FileWriter(backupFile)); 51 | f.println(gson.toJson(backup)); 52 | result = true; 53 | 54 | } catch (Exception e) { 55 | System.out.println("Error: " + e.getMessage()); 56 | result = false; 57 | } finally { 58 | if (f != null) { 59 | f.close(); 60 | } 61 | } 62 | return result; 63 | } 64 | 65 | @Override 66 | public Backup load() { 67 | Gson gson = new GsonBuilder().setPrettyPrinting().create(); 68 | Backup backup = null; 69 | Reader reader = null; 70 | try { 71 | reader = Files.newBufferedReader(Paths.get(backupFile)); 72 | backup = gson.fromJson(reader, new TypeToken() { 73 | }.getType()); 74 | } catch (Exception e) { 75 | System.out.println("Error: " + e.getMessage()); 76 | } finally { 77 | if (reader != null) { 78 | try { 79 | reader.close(); 80 | } catch (IOException e) { 81 | System.out.println("Error: " + e.getMessage()); 82 | } 83 | } 84 | } 85 | return backup; 86 | } 87 | 88 | @Override 89 | public String getStoragePath() { 90 | return backupFile; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /Soluciones/08-MVC-Paises-BBDD-Optional-Functional/src/main/java/es/joseluisgs/dam/utils/ApplicationProperties.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.utils; 2 | 3 | import java.io.IOException; 4 | import java.util.Properties; 5 | import java.util.logging.Level; 6 | import java.util.logging.Logger; 7 | 8 | public class ApplicationProperties { 9 | private final Properties properties; 10 | 11 | public ApplicationProperties() { 12 | properties = new Properties(); 13 | try { 14 | // De esta manera leemos desde el fichero de propiedades en resources 15 | properties.load(getClass().getClassLoader().getResourceAsStream("application.properties")); 16 | 17 | } catch (IOException ex) { 18 | System.err.println("IOException Ocurrido al leer el fichero de propiedades: " + ex.getMessage()); 19 | Logger.getLogger(getClass().getName()).log(Level.ALL, "IOException Ocurrido al leer el fichero de propiedades: " + ex.getMessage()); 20 | } 21 | } 22 | 23 | public String readProperty(String keyName) { 24 | // Logger.getLogger(getClass().getName()).log(Level.INFO, "Leyendo propiedad " + keyName); 25 | return properties.getProperty(keyName, "No existe esa clave en el fichero de propiedades"); 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /Soluciones/08-MVC-Paises-BBDD-Optional-Functional/src/main/java/es/joseluisgs/dam/utils/Console.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.utils; 2 | 3 | import java.util.Scanner; 4 | 5 | /** 6 | * Clase que permite leer datos desde la consola. 7 | */ 8 | public class Console { 9 | public static String getString(String message) { 10 | System.out.println(message); 11 | return new Scanner(System.in).nextLine().trim(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Soluciones/08-MVC-Paises-BBDD-Optional-Functional/src/main/java/es/joseluisgs/dam/utils/Formatter.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.utils; 2 | 3 | import java.text.NumberFormat; 4 | import java.time.LocalDateTime; 5 | import java.time.format.DateTimeFormatter; 6 | import java.time.format.FormatStyle; 7 | import java.util.Locale; 8 | 9 | public class Formatter { 10 | 11 | public static String dateParser(LocalDateTime date) { 12 | final Locale locale = new Locale("es", "ES"); 13 | // private String pattern = "dd/MM/yyyy"; 14 | return date.format(DateTimeFormatter 15 | .ofLocalizedDate(FormatStyle.MEDIUM).withLocale(locale)); 16 | } 17 | 18 | public static String moneyParser(Double money) { 19 | final Locale locale = new Locale("es", "ES"); 20 | return NumberFormat.getCurrencyInstance(locale).format(money); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Soluciones/08-MVC-Paises-BBDD-Optional-Functional/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joseluisgs/Programacion-09-2021-2022/188c0476c2f30e7149340dda33239a3df1488e4b/Soluciones/08-MVC-Paises-BBDD-Optional-Functional/src/main/resources/application.properties -------------------------------------------------------------------------------- /Soluciones/08-MVC-Paises-BBDD-Optional-Functional/src/main/resources/sql/init-db.sql: -------------------------------------------------------------------------------- 1 | -- Adminer 4.8.1 MySQL 5.5.5-10.6.4-MariaDB dump 2 | 3 | SET NAMES utf8; 4 | SET 5 | time_zone = '+00:00'; 6 | SET 7 | foreign_key_checks = 0; 8 | SET 9 | sql_mode = 'NO_AUTO_VALUE_ON_ZERO'; 10 | 11 | DROP 12 | DATABASE IF EXISTS `dam`; 13 | CREATE 14 | DATABASE `dam` /*!40100 DEFAULT CHARACTER SET utf8mb3 */; 15 | USE 16 | `dam`; 17 | 18 | DROP TABLE IF EXISTS `acuerdo`; 19 | CREATE TABLE `acuerdo` 20 | ( 21 | `id` int(11) NOT NULL AUTO_INCREMENT, 22 | `nombre` varchar(100) NOT NULL, 23 | `fecha` datetime NOT NULL, 24 | `aportacion` double NOT NULL, 25 | PRIMARY KEY (`id`) 26 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; 27 | 28 | INSERT INTO `acuerdo` (`id`, `nombre`, `fecha`, `aportacion`) 29 | VALUES (1, 'Acuerdo Diplomático', '2022-03-25 20:59:57', 12345.89), 30 | (2, 'Acuerdo de Fronteras', '2022-03-25 21:01:40', 999.99); 31 | 32 | DROP TABLE IF EXISTS `linea_acuerdo`; 33 | CREATE TABLE `linea_acuerdo` 34 | ( 35 | `id_acuerdo` int(11) NOT NULL, 36 | `id_pais` int(11) NOT NULL, 37 | `año` int(11) NOT NULL, 38 | `subvencion` double NOT NULL, 39 | KEY `id_acuerdo` (`id_acuerdo`), 40 | KEY `id_pais` (`id_pais`), 41 | CONSTRAINT `linea_acuerdo_ibfk_1` FOREIGN KEY (`id_acuerdo`) REFERENCES `acuerdo` (`id`) ON DELETE CASCADE 42 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; 43 | 44 | INSERT INTO `linea_acuerdo` (`id_acuerdo`, `id_pais`, `año`, `subvencion`) 45 | VALUES (1, 1, 2022, 1234.56), 46 | (1, 2, 2022, 345.32), 47 | (2, 4, 2022, 450.8), 48 | (2, 7, 2022, 6666.66), 49 | (2, 2, 2022, 333.33); 50 | 51 | DROP TABLE IF EXISTS `pais`; 52 | CREATE TABLE `pais` 53 | ( 54 | `id` int(11) NOT NULL AUTO_INCREMENT, 55 | `nombre` varchar(100) NOT NULL, 56 | `codigo` varchar(5) NOT NULL, 57 | `idioma` varchar(100) NOT NULL, 58 | `moneda` varchar(50) NOT NULL, 59 | `capital` varchar(100) NOT NULL, 60 | `presupuesto` double DEFAULT NULL, 61 | PRIMARY KEY (`id`) 62 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; 63 | 64 | INSERT INTO `pais` (`id`, `nombre`, `codigo`, `idioma`, `moneda`, `capital`, `presupuesto`) 65 | VALUES (1, 'España', 'ES', 'Español', 'Euro', 'Madrid', 1234567.23), 66 | (2, 'Francia', 'FR', 'Francés', 'Euro', 'París', 123456.67), 67 | (3, 'Italia', 'IT', 'Italiano', 'Euro', 'Roma', 564568.34), 68 | (4, 'Alemania', 'DE', 'Alemán', 'Euro', 'Berlín', 234567.23), 69 | (5, 'Reino Unido', 'UK', 'Inglés', 'Libra', 'Londres', 232323.34), 70 | (6, 'Japón', 'JP', 'Jsaponés', 'Yen', 'Tokio', 21212.12), 71 | (7, 'China', 'CN', 'Chino', 'Yuan', 'Pekín', 121212.34), 72 | (8, 'Australia', 'AU', 'Inglés', 'Dólar', 'Canberra', 567654.23), 73 | (9, 'Argentina', 'AR', 'Español', 'Peso', 'Buenos Aires', 123456.34), 74 | (10, 'Brasil', 'BR', 'Portugués', 'Real', 'Brasilia', 251251.62), 75 | (11, 'Estados Unidos', 'US', 'Inglés', 'Dólar', 'Washington', 1212415.98); 76 | 77 | -- 2022-03-26 11:15:34 -------------------------------------------------------------------------------- /Soluciones/08-MVC-Paises-BBDD-Optional-Functional/src/test/java/es/joseluisgs/dam/MainTest.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | import static org.junit.jupiter.api.Assertions.assertTrue; 6 | 7 | class MainTest { 8 | 9 | @Test 10 | public void trueIsTrue() { 11 | assertTrue(true); 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /Soluciones/08-MVC-Paises-BBDD-Optional-Functional/src/test/java/es/joseluisgs/dam/utilities/DataBase.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.utilities; 2 | 3 | import es.joseluisgs.dam.Main; 4 | import es.joseluisgs.dam.controllers.DataBaseManager; 5 | import es.joseluisgs.dam.utils.ApplicationProperties; 6 | 7 | import java.io.File; 8 | import java.io.FileNotFoundException; 9 | import java.sql.SQLException; 10 | 11 | public class DataBase { 12 | 13 | /** 14 | * Inicia la base de datos con los datos de prueba si los hay, o la estructura de la tabla... 15 | */ 16 | public static void init() { 17 | ApplicationProperties properties = new ApplicationProperties(); 18 | boolean init = Boolean.parseBoolean(properties.readProperty("database.initdata")); 19 | if (init) { 20 | DataBaseManager controller = DataBaseManager.getInstance(); 21 | String dataPath = "sql" + File.separator + "init-db.sql"; 22 | try { 23 | var sqlFile = Main.class.getClassLoader().getResource(dataPath).getPath(); 24 | controller.open(); 25 | controller.initData(sqlFile, false); 26 | controller.close(); 27 | } catch (SQLException e) { 28 | System.err.println("Error al conectar al servidor de Base de Datos: " + e.getMessage()); 29 | System.exit(1); 30 | } catch (FileNotFoundException e) { 31 | System.err.println("Error al leer el fichero de datos iniciales: " + e.getMessage()); 32 | System.exit(1); 33 | } 34 | } 35 | } 36 | 37 | /** 38 | * Borra todas las tablas, que cuesta menos que tirar toda la base de datos y levantarla de nuevo 39 | * 40 | * @throws SQLException 41 | */ 42 | public static void deleteAll() throws SQLException { 43 | DataBaseManager db = DataBaseManager.getInstance(); 44 | String query = "DELETE FROM pais"; 45 | db.open(); 46 | db.delete(query); 47 | query = "DELETE FROM acuerdo"; 48 | db.beginTransaction(); 49 | db.delete(query); 50 | query = "DELETE FROM linea_acuerdo"; 51 | db.delete(query); 52 | db.commit(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Soluciones/08-MVC-Paises-BBDD-Optional-Functional/src/test/java/es/joseluisgs/dam/utilities/DataDB.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.utilities; 2 | 3 | import es.joseluisgs.dam.controllers.DataBaseManager; 4 | import es.joseluisgs.dam.models.Acuerdo; 5 | import es.joseluisgs.dam.models.LineaAcuerdo; 6 | import es.joseluisgs.dam.models.Pais; 7 | 8 | import java.sql.ResultSet; 9 | import java.sql.SQLException; 10 | import java.util.Optional; 11 | 12 | public class DataDB { 13 | // Insertamos un dato de prueba, aquí vemos un acoplamiento... 14 | // Si no quiseramos esto, podríamos usar Order de test 15 | // Lo ideal es meterlo en el script, e iniciarlo cada vez... 16 | public static void insertPaisTest(Pais paisTest) throws SQLException { 17 | String query = "INSERT INTO pais VALUES (null, ?, ?, ?, ?, ?, ?)"; 18 | DataBaseManager db = DataBaseManager.getInstance(); 19 | db.open(); 20 | Optional res = db.insert(query, paisTest.getNombre(), paisTest.getCodigo(), paisTest.getIdioma(), paisTest.getMoneda(), 21 | paisTest.getCapital(), paisTest.getPresupuesto()); 22 | if (res.get().first()) { 23 | paisTest.setId(res.get().getInt(1)); 24 | } 25 | db.close(); 26 | } 27 | 28 | public static void insertAcuerdoTest(Acuerdo acuerdoTest) throws SQLException { 29 | // OJO pongo null en el primer parámetro porque no inserto el ID, este se genera automático. Mira el DBMAnager 30 | String query = "INSERT INTO acuerdo VALUES (null, ?, ?, ?)"; 31 | DataBaseManager db = DataBaseManager.getInstance(); 32 | // Es una transacción, por lo que si falla alguna de las dos, se cancela todo 33 | db.open(); 34 | db.beginTransaction(); 35 | ResultSet res = db.insert(query, acuerdoTest.getNombre(), acuerdoTest.getFecha(), acuerdoTest.getAportacion()) 36 | .orElseThrow(() -> new SQLException("Error al insertar acuerdo")); 37 | 38 | // Para obtener su ID que ha generado la BD 39 | if (res.first()) { 40 | acuerdoTest.setId(res.getInt(1)); 41 | // Ahora salvamos toda las lineas de acuerdo... 42 | for (LineaAcuerdo linea : acuerdoTest.getLineas()) { 43 | query = "INSERT INTO linea_acuerdo VALUES (?, ?, ?, ?)"; 44 | db.insert(query, acuerdoTest.getId(), linea.getPais().getId(), linea.getAño(), linea.getSubvencion()) 45 | .orElseThrow(() -> new SQLException("Error al insertar linea de acuerdo")); 46 | } 47 | 48 | // Y finalmente cerramos la conexión y devolvemos el acuerdo 49 | db.commit(); 50 | db.close(); 51 | } 52 | db.rollback(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Soluciones/08-MVC-Paises-BBDD-Optional-Functional/src/test/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joseluisgs/Programacion-09-2021-2022/188c0476c2f30e7149340dda33239a3df1488e4b/Soluciones/08-MVC-Paises-BBDD-Optional-Functional/src/test/resources/application.properties -------------------------------------------------------------------------------- /Soluciones/08-MVC-Paises-BBDD-Optional-Functional/src/test/resources/sql/init-db.sql: -------------------------------------------------------------------------------- 1 | -- Adminer 4.8.1 MySQL 5.5.5-10.6.4-MariaDB dump 2 | 3 | SET NAMES utf8; 4 | SET 5 | time_zone = '+00:00'; 6 | SET 7 | foreign_key_checks = 0; 8 | SET 9 | sql_mode = 'NO_AUTO_VALUE_ON_ZERO'; 10 | 11 | DROP 12 | DATABASE IF EXISTS `dam`; 13 | CREATE 14 | DATABASE `dam` /*!40100 DEFAULT CHARACTER SET utf8mb3 */; 15 | USE 16 | `dam`; 17 | 18 | DROP TABLE IF EXISTS `acuerdo`; 19 | CREATE TABLE `acuerdo` 20 | ( 21 | `id` int(11) NOT NULL AUTO_INCREMENT, 22 | `nombre` varchar(100) NOT NULL, 23 | `fecha` datetime NOT NULL, 24 | `aportacion` double NOT NULL, 25 | PRIMARY KEY (`id`) 26 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; 27 | 28 | 29 | DROP TABLE IF EXISTS `linea_acuerdo`; 30 | CREATE TABLE `linea_acuerdo` 31 | ( 32 | `id_acuerdo` int(11) NOT NULL, 33 | `id_pais` int(11) NOT NULL, 34 | `año` int(11) NOT NULL, 35 | `subvencion` double NOT NULL, 36 | KEY `id_acuerdo` (`id_acuerdo`), 37 | KEY `id_pais` (`id_pais`), 38 | CONSTRAINT `linea_acuerdo_ibfk_1` FOREIGN KEY (`id_acuerdo`) REFERENCES `acuerdo` (`id`) ON DELETE CASCADE 39 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; 40 | 41 | DROP TABLE IF EXISTS `pais`; 42 | CREATE TABLE `pais` 43 | ( 44 | `id` int(11) NOT NULL AUTO_INCREMENT, 45 | `nombre` varchar(100) NOT NULL, 46 | `codigo` varchar(5) NOT NULL, 47 | `idioma` varchar(100) NOT NULL, 48 | `moneda` varchar(50) NOT NULL, 49 | `capital` varchar(100) NOT NULL, 50 | `presupuesto` double DEFAULT NULL, 51 | PRIMARY KEY (`id`) 52 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; 53 | 54 | -- 2022-03-26 11:15:34 -------------------------------------------------------------------------------- /Soluciones/09-AccidentesStream/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | -------------------------------------------------------------------------------- /Soluciones/09-AccidentesStream/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /Soluciones/09-AccidentesStream/.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Soluciones/09-AccidentesStream/.idea/description.html: -------------------------------------------------------------------------------- 1 | Simple Java application that includes a class with main() method -------------------------------------------------------------------------------- /Soluciones/09-AccidentesStream/.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Soluciones/09-AccidentesStream/.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | -------------------------------------------------------------------------------- /Soluciones/09-AccidentesStream/.idea/libraries/Maven__org_projectlombok_lombok_1_18_22.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Soluciones/09-AccidentesStream/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 11 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Soluciones/09-AccidentesStream/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Soluciones/09-AccidentesStream/.idea/project-template.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Soluciones/09-AccidentesStream/AccidentesStream.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Soluciones/09-AccidentesStream/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | groupId 8 | AccidentesStream 9 | 1.0-SNAPSHOT 10 | 11 | 12 | org.projectlombok 13 | lombok 14 | RELEASE 15 | compile 16 | 17 | 18 | 19 | 20 | 11 21 | 11 22 | 23 | 24 | -------------------------------------------------------------------------------- /Soluciones/09-AccidentesStream/src/main/java/es/joseluisgs/dam/Accidente.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam; 2 | 3 | import lombok.Data; 4 | 5 | import java.time.LocalDate; 6 | import java.time.LocalTime; 7 | 8 | @Data 9 | public class Accidente { 10 | private final String numExpediente; 11 | private final LocalDate fecha; 12 | private final LocalTime hora; 13 | private final String localizacion; 14 | private final String distrito; 15 | private final String tipoAccidente; 16 | private final String meteorologia; 17 | private final String tipoVehiculo; 18 | private final String tipoPersona; 19 | private final String sexo; 20 | private final boolean positivoAlcohol; 21 | private final boolean positivoDrogas; 22 | } 23 | -------------------------------------------------------------------------------- /Soluciones/09-AccidentesStream/src/main/java/es/joseluisgs/dam/Main.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam; 2 | 3 | public class Main { 4 | 5 | public static void main(String[] args) { 6 | System.out.println("Accidentes Madrid"); 7 | System.out.println("=================="); 8 | AccidentesController controller = new AccidentesController(); 9 | controller.run(); 10 | 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.toptal.com/developers/gitignore/api/maven,java,intellij+all 3 | # Edit at https://www.toptal.com/developers/gitignore?templates=maven,java,intellij+all 4 | 5 | ### Intellij+all ### 6 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 7 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 8 | 9 | # User-specific stuff 10 | .idea/**/workspace.xml 11 | .idea/**/tasks.xml 12 | .idea/**/usage.statistics.xml 13 | .idea/**/dictionaries 14 | .idea/**/shelf 15 | 16 | # AWS User-specific 17 | .idea/**/aws.xml 18 | 19 | # Generated files 20 | .idea/**/contentModel.xml 21 | 22 | # Sensitive or high-churn files 23 | .idea/**/dataSources/ 24 | .idea/**/dataSources.ids 25 | .idea/**/dataSources.local.xml 26 | .idea/**/sqlDataSources.xml 27 | .idea/**/dynamic.xml 28 | .idea/**/uiDesigner.xml 29 | .idea/**/dbnavigator.xml 30 | 31 | # Gradle 32 | .idea/**/gradle.xml 33 | .idea/**/libraries 34 | 35 | # Gradle and Maven with auto-import 36 | # When using Gradle or Maven with auto-import, you should exclude module files, 37 | # since they will be recreated, and may cause churn. Uncomment if using 38 | # auto-import. 39 | # .idea/artifacts 40 | # .idea/compiler.xml 41 | # .idea/jarRepositories.xml 42 | # .idea/modules.xml 43 | # .idea/*.iml 44 | # .idea/modules 45 | # *.iml 46 | # *.ipr 47 | 48 | # CMake 49 | cmake-build-*/ 50 | 51 | # Mongo Explorer plugin 52 | .idea/**/mongoSettings.xml 53 | 54 | # File-based project format 55 | *.iws 56 | 57 | # IntelliJ 58 | out/ 59 | 60 | # mpeltonen/sbt-idea plugin 61 | .idea_modules/ 62 | 63 | # JIRA plugin 64 | atlassian-ide-plugin.xml 65 | 66 | # Cursive Clojure plugin 67 | .idea/replstate.xml 68 | 69 | # SonarLint plugin 70 | .idea/sonarlint/ 71 | 72 | # Crashlytics plugin (for Android Studio and IntelliJ) 73 | com_crashlytics_export_strings.xml 74 | crashlytics.properties 75 | crashlytics-build.properties 76 | fabric.properties 77 | 78 | # Editor-based Rest Client 79 | .idea/httpRequests 80 | 81 | # Android studio 3.1+ serialized cache file 82 | .idea/caches/build_file_checksums.ser 83 | 84 | ### Intellij+all Patch ### 85 | # Ignore everything but code style settings and run configurations 86 | # that are supposed to be shared within teams. 87 | 88 | .idea/* 89 | 90 | !.idea/codeStyles 91 | !.idea/runConfigurations 92 | 93 | ### Java ### 94 | # Compiled class file 95 | *.class 96 | 97 | # Log file 98 | *.log 99 | 100 | # BlueJ files 101 | *.ctxt 102 | 103 | # Mobile Tools for Java (J2ME) 104 | .mtj.tmp/ 105 | 106 | # Package Files # 107 | *.jar 108 | *.war 109 | *.nar 110 | *.ear 111 | *.zip 112 | *.tar.gz 113 | *.rar 114 | 115 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 116 | hs_err_pid* 117 | replay_pid* 118 | 119 | ### Maven ### 120 | target/ 121 | pom.xml.tag 122 | pom.xml.releaseBackup 123 | pom.xml.versionsBackup 124 | pom.xml.next 125 | release.properties 126 | dependency-reduced-pom.xml 127 | buildNumber.properties 128 | .mvn/timing.properties 129 | # https://github.com/takari/maven-wrapper#usage-without-binary-jar 130 | .mvn/wrapper/maven-wrapper.jar 131 | 132 | # Eclipse m2e generated files 133 | # Eclipse Core 134 | .project 135 | # JDT-specific (Eclipse Java Development Tools) 136 | .classpath 137 | 138 | # End of https://www.toptal.com/developers/gitignore/api/maven,java,intellij+all 139 | -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/SecuenciaPaises.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/docker/docker-compose.yml: -------------------------------------------------------------------------------- 1 | # Indicamos la versión 2 | # Para iniciar docker-compose up -d 3 | version: '3.7' 4 | 5 | # Mis servicios 6 | # Iniciamos los servicios 7 | services: 8 | # MARIA DB 9 | mariadb: 10 | build: ./mariadb 11 | image: mariadb 12 | container_name: mariadb 13 | ports: 14 | - 3306:3306 15 | expose: 16 | - 3306 17 | volumes: 18 | - mariadb-volume:/var/lib/mysql 19 | networks: 20 | - mariadb-network 21 | # restart: always 22 | 23 | # ADMIN MARIADB 24 | adminer: 25 | image: adminer 26 | container_name: adminer 27 | # restart: always 28 | ports: 29 | - 8080:8080 30 | networks: 31 | - mariadb-network 32 | depends_on: 33 | - mariadb 34 | 35 | # Mi volumenes de datos compartidos 36 | volumes: 37 | mariadb-volume: 38 | 39 | # Si queremos que tengan una red propia a otros contenedores 40 | networks: 41 | mariadb-network: 42 | driver: bridge 43 | -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/docker/mariadb/Dockerfile: -------------------------------------------------------------------------------- 1 | # MariaDB 2 | FROM yobasystems/alpine-mariadb:10 3 | # FROM mariadb:10.5 4 | 5 | # Configuramos BBDD 6 | ENV MYSQL_ROOT_PASSWORD 123 7 | ENV MYSQL_USER dam 8 | ENV MYSQL_PASSWORD dam1234 9 | ENV MYSQL_DATABASE dam 10 | 11 | # Copiamos los ficheros sql para que se ejecuten 12 | COPY ./sql /docker-entrypoint-initdb.d/ -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | groupId 8 | SecuenciaPaises 9 | 1.0-SNAPSHOT 10 | 11 | 12 | 11 13 | 11 14 | 3.10.1 15 | 16 | 17 | 18 | 19 | 20 | com.google.code.gson 21 | gson 22 | 2.9.0 23 | 24 | 25 | 26 | org.projectlombok 27 | lombok 28 | 1.18.22 29 | compile 30 | 31 | 32 | 33 | org.mariadb.jdbc 34 | mariadb-java-client 35 | 3.0.3 36 | 37 | 38 | 39 | org.mybatis 40 | mybatis 41 | 3.5.9 42 | 43 | 44 | 45 | org.junit.jupiter 46 | junit-jupiter 47 | 5.8.2 48 | test 49 | 50 | 51 | 52 | org.mockito 53 | mockito-core 54 | 4.4.0 55 | test 56 | 57 | 58 | org.mockito 59 | mockito-junit-jupiter 60 | 4.4.0 61 | test 62 | 63 | 64 | 65 | com.google.dagger 66 | dagger 67 | 2.41 68 | 69 | 70 | 71 | 72 | 73 | 75 | 76 | org.apache.maven.plugins 77 | maven-compiler-plugin 78 | ${maven-compiler-plugin.version} 79 | 80 | 81 | 82 | com.google.dagger 83 | dagger-compiler 84 | 2.41 85 | 86 | 87 | org.projectlombok 88 | lombok 89 | 1.18.22 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/src/main/java/es/joseluisgs/dam/DI/controllers/controllers/AcuerdoControllerDI.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.DI.controllers.controllers; 2 | 3 | import dagger.Component; 4 | import es.joseluisgs.dam.DI.modules.AcuerdoRepositoryModule; 5 | import es.joseluisgs.dam.DI.modules.DataBaseManagerModule; 6 | import es.joseluisgs.dam.controllers.AcuerdoController; 7 | 8 | import javax.inject.Singleton; 9 | 10 | @Singleton 11 | @Component(modules = { 12 | AcuerdoRepositoryModule.class, 13 | DataBaseManagerModule.class 14 | }) 15 | 16 | public interface AcuerdoControllerDI { 17 | AcuerdoController build(); 18 | } 19 | -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/src/main/java/es/joseluisgs/dam/DI/controllers/controllers/BackupManagerDI.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.DI.controllers.controllers; 2 | 3 | import dagger.Component; 4 | import es.joseluisgs.dam.DI.modules.AcuerdoRepositoryModule; 5 | import es.joseluisgs.dam.DI.modules.DataBaseManagerModule; 6 | import es.joseluisgs.dam.DI.modules.PaisRepositoryModule; 7 | import es.joseluisgs.dam.DI.modules.StorageBackupModule; 8 | import es.joseluisgs.dam.controllers.BackupManager; 9 | 10 | import javax.inject.Singleton; 11 | 12 | @Singleton 13 | @Component(modules = { 14 | PaisRepositoryModule.class, 15 | AcuerdoRepositoryModule.class, 16 | StorageBackupModule.class, 17 | DataBaseManagerModule.class 18 | }) 19 | 20 | public interface BackupManagerDI { 21 | BackupManager build(); 22 | } 23 | -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/src/main/java/es/joseluisgs/dam/DI/controllers/controllers/PaisControllerDI.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.DI.controllers.controllers; 2 | 3 | import dagger.Component; 4 | import es.joseluisgs.dam.DI.modules.DataBaseManagerModule; 5 | import es.joseluisgs.dam.DI.modules.PaisRepositoryModule; 6 | import es.joseluisgs.dam.controllers.PaisController; 7 | 8 | import javax.inject.Singleton; 9 | 10 | @Singleton 11 | @Component(modules = { 12 | PaisRepositoryModule.class, 13 | DataBaseManagerModule.class 14 | }) 15 | 16 | public interface PaisControllerDI { 17 | PaisController build(); 18 | } 19 | -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/src/main/java/es/joseluisgs/dam/DI/modules/AcuerdoRepositoryModule.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.DI.modules; 2 | 3 | import dagger.Binds; 4 | import dagger.Module; 5 | import es.joseluisgs.dam.repositories.acuerdos.AcuerdoRepository; 6 | import es.joseluisgs.dam.repositories.acuerdos.IAcuerdoRepository; 7 | 8 | import javax.inject.Singleton; 9 | 10 | @Module 11 | public interface AcuerdoRepositoryModule { 12 | @Singleton 13 | @Binds 14 | IAcuerdoRepository bindAcuerdoRepository(AcuerdoRepository impl); 15 | } 16 | -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/src/main/java/es/joseluisgs/dam/DI/modules/DataBaseManagerModule.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.DI.modules; 2 | 3 | import dagger.Module; 4 | import dagger.Provides; 5 | import es.joseluisgs.dam.controllers.DataBaseManager; 6 | 7 | import javax.inject.Singleton; 8 | 9 | @Module 10 | public class DataBaseManagerModule { 11 | 12 | @Provides 13 | @Singleton 14 | DataBaseManager provideDataBaseManager() { 15 | return DataBaseManager.getInstance(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/src/main/java/es/joseluisgs/dam/DI/modules/PaisRepositoryModule.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.DI.modules; 2 | 3 | import dagger.Binds; 4 | import dagger.Module; 5 | import es.joseluisgs.dam.repositories.paises.IPaisRepository; 6 | import es.joseluisgs.dam.repositories.paises.PaisRepository; 7 | 8 | import javax.inject.Singleton; 9 | 10 | @Module 11 | public interface PaisRepositoryModule { 12 | @Singleton 13 | @Binds 14 | IPaisRepository bindPaisRepository(PaisRepository impl); 15 | } 16 | -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/src/main/java/es/joseluisgs/dam/DI/modules/StorageBackupModule.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.DI.modules; 2 | 3 | import dagger.Binds; 4 | import dagger.Module; 5 | import es.joseluisgs.dam.services.Storage.IStorageBackup; 6 | import es.joseluisgs.dam.services.Storage.StorageBackupJsonFile; 7 | 8 | import javax.inject.Named; 9 | import javax.inject.Singleton; 10 | 11 | @Module 12 | public 13 | interface StorageBackupModule { 14 | @Binds 15 | @Singleton 16 | @Named("json") 17 | IStorageBackup provideApiStorageBackupService(StorageBackupJsonFile impl); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/src/main/java/es/joseluisgs/dam/Main.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam; 2 | 3 | import es.joseluisgs.dam.controllers.DataBaseManager; 4 | import es.joseluisgs.dam.utils.ApplicationProperties; 5 | import es.joseluisgs.dam.views.PaisView; 6 | 7 | import java.io.File; 8 | import java.io.FileNotFoundException; 9 | import java.sql.ResultSet; 10 | import java.sql.SQLException; 11 | import java.util.Optional; 12 | 13 | /** 14 | * Ejemplo de Patrón MVC para CRUD de países. 15 | * Siguiendo los diagramas de Secuencias en Clase 16 | * Modelo: Pais, gestionador por PaisRepository 17 | * Vista: La propia consola: comunicacion con el usuario 18 | * Controlador: PaisController, controla, cómo y de qué manera el modelo, repositorio y la vista interactúan 19 | * Como vista que soy, soy lo último y gestiono las excepciones con Try/Catch 20 | */ 21 | public class Main { 22 | public static void main(String[] args) { 23 | checkServer(); 24 | initData(); 25 | PaisView view = PaisView.getInstance(); 26 | view.menu(); 27 | 28 | } 29 | 30 | private static void checkServer() { 31 | System.out.println("Comprobamos la conexión al Servidor BD"); 32 | DataBaseManager controller = DataBaseManager.getInstance(); 33 | try { 34 | controller.open(); 35 | Optional rs = controller.select("SELECT 'Hello world'"); 36 | if (rs.isPresent()) { 37 | rs.get().first(); 38 | controller.close(); 39 | System.out.println("Conexión con la Base de Datos realizada con éxito"); 40 | } 41 | } catch (SQLException e) { 42 | System.err.println("Error al conectar al servidor de Base de Datos: " + e.getMessage()); 43 | System.exit(1); 44 | } 45 | } 46 | 47 | private static void initData() { 48 | ApplicationProperties properties = new ApplicationProperties(); 49 | boolean init = Boolean.parseBoolean(properties.readProperty("database.initdata")); 50 | if (init) { 51 | System.out.println("Iniciamos los datos de ejemplo de la Base de Datos"); 52 | DataBaseManager controller = DataBaseManager.getInstance(); 53 | String dataPath = "sql" + File.separator + "init-db.sql"; 54 | try { 55 | var sqlFile = Main.class.getClassLoader().getResource(dataPath).getPath(); 56 | System.out.println(dataPath); 57 | controller.open(); 58 | controller.initData(sqlFile, false); 59 | controller.close(); 60 | System.out.println("Datos inicializados con éxito"); 61 | } catch (SQLException e) { 62 | System.err.println("Error al conectar al servidor de Base de Datos: " + e.getMessage()); 63 | System.exit(1); 64 | } catch (FileNotFoundException e) { 65 | System.err.println("Error al leer el fichero de datos iniciales: " + e.getMessage()); 66 | System.exit(1); 67 | } 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/src/main/java/es/joseluisgs/dam/controllers/AcuerdoController.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.controllers; 2 | 3 | import es.joseluisgs.dam.exceptions.AcuerdoException; 4 | import es.joseluisgs.dam.models.Acuerdo; 5 | import es.joseluisgs.dam.models.LineaAcuerdo; 6 | import es.joseluisgs.dam.models.Pais; 7 | import es.joseluisgs.dam.repositories.acuerdos.IAcuerdoRepository; 8 | 9 | import javax.inject.Inject; 10 | import java.sql.SQLException; 11 | import java.time.LocalDate; 12 | import java.time.LocalDateTime; 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | 16 | public class AcuerdoController { 17 | private final IAcuerdoRepository acuerdosRepository; 18 | 19 | @Inject 20 | public AcuerdoController(IAcuerdoRepository acuerdosRepository) { 21 | this.acuerdosRepository = acuerdosRepository; 22 | } 23 | 24 | /** 25 | * Crea un acuerdo con los datos pasados por parámetro. 26 | * 27 | * @param nombre Nombre del acuerdo. 28 | * @param paises Paises que participan en el acuerdo. 29 | * @return El acuerdo creado. 30 | * @throws SQLException Si hay un error en la base de datos. 31 | */ 32 | public Acuerdo createAcuerdo(String nombre, List paises) throws SQLException { 33 | List lineas = new ArrayList<>(); 34 | for (Pais pais : paises) { 35 | lineas.add(new LineaAcuerdo(pais, LocalDate.now().getYear())); 36 | } 37 | Acuerdo acuerdo = new Acuerdo(0, nombre, LocalDateTime.now(), lineas); 38 | return acuerdosRepository.save(acuerdo).get(); 39 | } 40 | 41 | /** 42 | * Obtiene un acuerdo por su id. 43 | * 44 | * @param id Id del acuerdo. 45 | * @return El acuerdo. 46 | * @throws AcuerdoException Si no existe el acuerdo. 47 | * @throws SQLException Si hay un error en la base de datos. 48 | */ 49 | public Acuerdo getAcuerdoById(int id) throws AcuerdoException, SQLException { 50 | return acuerdosRepository.findById(id).orElseThrow(() -> new AcuerdoException("No existe el acuerdo con id " + id)); 51 | } 52 | 53 | /** 54 | * Obtiene todos los acuerdos. 55 | * 56 | * @return Lista de acuerdos. 57 | * @throws SQLException Si hay un error en la base de datos. 58 | */ 59 | public List getAllAcuerdos() throws SQLException { 60 | return acuerdosRepository.findAll(); 61 | } 62 | 63 | /** 64 | * Elimina un acuerdo por su id. 65 | * 66 | * @param id Id del acuerdo. 67 | * @return El acuerdo eliminado. 68 | * @throws SQLException Si hay un error en la base de datos. 69 | */ 70 | public Acuerdo deleteAcuerdo(int id) throws SQLException { 71 | return acuerdosRepository.delete(id).get(); 72 | } 73 | 74 | /** 75 | * Actualiza un acuerdo. 76 | * 77 | * @param id Id del acuerdo. 78 | * @param acuerdo Acuerdo con los nuevos datos. 79 | * @return El acuerdo actualizado. 80 | * @throws SQLException Si hay un error en la base de datos. 81 | */ 82 | public Acuerdo updateAcuerdo(int id, Acuerdo acuerdo) throws SQLException { 83 | return acuerdosRepository.update(id, acuerdo).get(); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/src/main/java/es/joseluisgs/dam/controllers/BackupManager.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.controllers; 2 | 3 | import dagger.Lazy; 4 | import es.joseluisgs.dam.models.Acuerdo; 5 | import es.joseluisgs.dam.models.Backup; 6 | import es.joseluisgs.dam.models.Pais; 7 | import es.joseluisgs.dam.repositories.acuerdos.IAcuerdoRepository; 8 | import es.joseluisgs.dam.repositories.paises.IPaisRepository; 9 | import es.joseluisgs.dam.services.Storage.IStorageBackup; 10 | 11 | import javax.inject.Inject; 12 | import javax.inject.Named; 13 | import java.sql.SQLException; 14 | 15 | public class BackupManager { 16 | private final Lazy paisRepository; 17 | private final Lazy acuerdoRepository; 18 | private final Lazy storageBackup; 19 | 20 | @Inject 21 | public BackupManager( 22 | Lazy paisRepository, 23 | Lazy acuerdoRepository, 24 | @Named("json") Lazy storageBackup 25 | ) { 26 | this.paisRepository = paisRepository; 27 | this.acuerdoRepository = acuerdoRepository; 28 | this.storageBackup = storageBackup; 29 | } 30 | 31 | 32 | /** 33 | * Importa los datos desde un fichero de backup 34 | */ 35 | public void importarDatos() throws SQLException { 36 | System.out.println("Importando datos de Backup: " + storageBackup.get().getStoragePath()); 37 | var backup = storageBackup.get().load(); 38 | System.out.println("Importando Paises..."); 39 | if (backup.getPaises().size() > 0) { 40 | paisRepository.get().clearAll(); 41 | for (Pais pais : backup.getPaises()) { 42 | paisRepository.get().save(pais); 43 | } 44 | System.out.println("Paises importados con éxito al repositorio: " + backup.getPaises().size() + " paises"); 45 | } else { 46 | System.out.println("Ha existido un problema al importar los datos de Paises"); 47 | } 48 | System.out.println("Importando Acuerdos..."); 49 | if (backup.getAcuerdos().size() > 0) { 50 | acuerdoRepository.get().clearAll(); 51 | for (Acuerdo acuerdo : backup.getAcuerdos()) { 52 | acuerdoRepository.get().save(acuerdo); 53 | } 54 | System.out.println("Acuerdos importados con éxito al repositorio: " + backup.getAcuerdos().size() + " acuerdos"); 55 | } else { 56 | System.out.println("Ha existido un problema al importar los datos de Acuerdos"); 57 | } 58 | } 59 | 60 | 61 | /** 62 | * Exporta los datos desde un fichero de Backup 63 | */ 64 | public void exportarDatos() throws SQLException { 65 | System.out.println("Exportando datos a fichero de Backup..."); 66 | var paises = paisRepository.get().findAll(); 67 | var acuerdos = acuerdoRepository.get().findAll(); 68 | Backup backup = Backup.builder() 69 | .paises(paises) 70 | .acuerdos(acuerdos) 71 | .build(); 72 | var res = storageBackup.get().save(backup); 73 | if (res) { 74 | System.out.println("Exportando " + backup.getPaises().size() + " paises"); 75 | System.out.println("Exportando " + backup.getAcuerdos().size() + " acuerdos"); 76 | System.out.println("Datos exportados con éxito en: " + storageBackup.get().getStoragePath()); 77 | } else { 78 | System.out.println("Ha existido un problema al exportar los datos"); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/src/main/java/es/joseluisgs/dam/exceptions/AcuerdoException.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.exceptions; 2 | 3 | /** 4 | * Excepción asociada al comprotamiento de gestion de Acuerdos. 5 | */ 6 | public class AcuerdoException extends Exception { 7 | 8 | public AcuerdoException(String mensaje) { 9 | super(mensaje); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/src/main/java/es/joseluisgs/dam/exceptions/PaisException.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.exceptions; 2 | 3 | /** 4 | * Excepción asociada al comprotamiento de gestion de paises. 5 | */ 6 | public class PaisException extends Exception { 7 | 8 | public PaisException(String mensaje) { 9 | super(mensaje); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/src/main/java/es/joseluisgs/dam/models/Acuerdo.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.models; 2 | 3 | import es.joseluisgs.dam.utils.Formatter; 4 | import lombok.Data; 5 | 6 | import java.time.LocalDateTime; 7 | import java.util.List; 8 | 9 | @Data 10 | public class Acuerdo { 11 | private final LocalDateTime fecha; 12 | private String nombre; 13 | private double aportacion; 14 | private List lineas; 15 | private int id; 16 | 17 | 18 | public Acuerdo(int id, String nombre, LocalDateTime fecha, List lineas) { 19 | this.id = id; 20 | this.nombre = nombre; 21 | this.fecha = fecha; 22 | this.lineas = lineas; 23 | this.aportacion = calcularAportacion(); 24 | } 25 | 26 | private double calcularAportacion() { 27 | return lineas.stream().mapToDouble(LineaAcuerdo::getSubvencion).sum(); 28 | } 29 | 30 | public Integer getId() { 31 | return id; 32 | } 33 | 34 | @Override 35 | public String toString() { 36 | // Puedes imprimir listas como Arrays.toString(lista)) 37 | return "Acuerdo{" + "id=" + id + ", nombre=" + nombre + ", fecha=" 38 | + Formatter.dateParser(fecha) + ", lineas=" + lineas + ", aportacion=" + Formatter.moneyParser(aportacion) + '}'; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/src/main/java/es/joseluisgs/dam/models/Backup.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.models; 2 | 3 | import lombok.Builder; 4 | 5 | import java.time.LocalDateTime; 6 | import java.util.List; 7 | 8 | @Builder 9 | public class Backup { 10 | private final String createdAt = LocalDateTime.now().toString(); 11 | private List paises; 12 | private List acuerdos; 13 | 14 | public List getPaises() { 15 | return paises; 16 | } 17 | 18 | public List getAcuerdos() { 19 | return acuerdos; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/src/main/java/es/joseluisgs/dam/models/LineaAcuerdo.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.models; 2 | 3 | import es.joseluisgs.dam.utils.Formatter; 4 | import lombok.Data; 5 | 6 | @Data 7 | public class LineaAcuerdo { 8 | private final Pais pais; 9 | private final int año; 10 | private final double subvencion; 11 | 12 | public LineaAcuerdo(Pais pais, int año) { 13 | this.pais = pais; 14 | this.año = año; 15 | this.subvencion = pais.getPresupuesto() * 0.25; 16 | } 17 | 18 | public LineaAcuerdo(Pais pais, int año, double subvencion) { 19 | this.pais = pais; 20 | this.año = año; 21 | this.subvencion = subvencion; 22 | } 23 | 24 | @Override 25 | public String toString() { 26 | return "LineaAcuerdo{" + "pais=" + pais.getNombre() + ", año=" + año + ", subvencion=" + Formatter.moneyParser(subvencion) + '}'; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/src/main/java/es/joseluisgs/dam/models/Pais.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.models; 2 | 3 | import es.joseluisgs.dam.utils.Formatter; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * Modelo. Clase que representa un país. POJO. 10 | * Se hace lo más limpia posible para que sirva a numerosos casos. No se implementa excepciones ni comparables 11 | * Es un POJO de "libro" 12 | */ 13 | 14 | @Data 15 | @NoArgsConstructor 16 | @Builder 17 | public class Pais { 18 | private int id = 0; 19 | private String nombre; 20 | private String codigo; 21 | private String idioma; 22 | private String moneda; 23 | private String capital; 24 | private double presupuesto; 25 | 26 | 27 | public Pais(String nombre, String codigo, String idioma, String moneda, String capital) { 28 | this.nombre = nombre; 29 | this.codigo = codigo; 30 | this.idioma = idioma; 31 | this.moneda = moneda; 32 | this.capital = capital; 33 | // Voy a dejar el presupuesto aleatorio 34 | this.presupuesto = Math.random() * 1000000; 35 | } 36 | 37 | public Pais(int id, String nombre, String codigo, String idioma, String moneda, String capital, double presupuesto) { 38 | this.id = id; 39 | this.nombre = nombre; 40 | this.codigo = codigo; 41 | this.idioma = idioma; 42 | this.moneda = moneda; 43 | this.capital = capital; 44 | this.presupuesto = presupuesto; 45 | } 46 | 47 | @Override 48 | public String toString() { 49 | return "Pais{" + "id=" + id + ", nombre=" + nombre + ", codigo=" + codigo + ", idioma=" + idioma + ", moneda=" + moneda + ", capital=" + capital + ", presupuesto=" + Formatter.moneyParser(presupuesto) + '}'; 50 | } 51 | 52 | 53 | public Pais nombre(String nombre) { 54 | this.nombre = nombre; 55 | return this; 56 | } 57 | 58 | public Pais codigo(String codigo) { 59 | this.codigo = codigo; 60 | return this; 61 | } 62 | 63 | public Pais idioma(String idioma) { 64 | this.idioma = idioma; 65 | return this; 66 | } 67 | 68 | public Pais moneda(String moneda) { 69 | this.moneda = moneda; 70 | return this; 71 | } 72 | 73 | public Pais capital(String capital) { 74 | this.capital = capital; 75 | return this; 76 | } 77 | 78 | public Pais presupuesto(double presupuesto) { 79 | this.presupuesto = presupuesto; 80 | return this; 81 | } 82 | 83 | public String toString(String separator) { 84 | return id + separator + nombre + separator + codigo + separator + idioma + separator + moneda + separator + capital + separator + presupuesto; 85 | } 86 | } 87 | 88 | -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/src/main/java/es/joseluisgs/dam/repositories/CRUDRepository.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.repositories; 2 | 3 | import java.sql.SQLException; 4 | import java.util.List; 5 | import java.util.Optional; 6 | 7 | public interface CRUDRepository { 8 | /** 9 | * Devuelve una lista de todos los elementos del repositorio 10 | * 11 | * @return Lista de elementos 12 | * @throws SQLException Si hay algún error en la base de datos 13 | */ 14 | List findAll() throws SQLException; 15 | 16 | /** 17 | * Devuelve un Optional del elemento dada una id 18 | * 19 | * @param id Id del elemento 20 | * @return Optional del elemento 21 | * @throws SQLException Si hay algún error en la base de datos 22 | */ 23 | Optional findById(ID id) throws SQLException; 24 | 25 | /** 26 | * Inserta un elemento en el repositorio 27 | * 28 | * @param entity Elemento a insertar 29 | * @return Elemento insertado 30 | * @throws SQLException Si hay algún error en la base de datos 31 | */ 32 | Optional save(T entity) throws SQLException; 33 | 34 | /** 35 | * Actualiza un elemento en el repositorio 36 | * 37 | * @param id Id del elemento a actualizar 38 | * @param entity Elemento a actualizar 39 | * @return Elemento actualizado 40 | * @throws SQLException Si hay algún error en la base de datos 41 | */ 42 | Optional update(ID id, T entity) throws SQLException; 43 | 44 | /** 45 | * Elimina un elemento del repositorio 46 | * 47 | * @param id Id del elemento a eliminar 48 | * @return Elemento eliminado 49 | * @throws SQLException Si hay algún error en la base de datos 50 | */ 51 | Optional delete(ID id) throws SQLException; 52 | } 53 | -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/src/main/java/es/joseluisgs/dam/repositories/acuerdos/IAcuerdoRepository.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.repositories.acuerdos; 2 | 3 | import es.joseluisgs.dam.models.Acuerdo; 4 | import es.joseluisgs.dam.repositories.CRUDRepository; 5 | 6 | import java.sql.SQLException; 7 | 8 | public interface IAcuerdoRepository extends CRUDRepository { 9 | 10 | void clearAll() throws SQLException; 11 | } 12 | -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/src/main/java/es/joseluisgs/dam/repositories/paises/IPaisRepository.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.repositories.paises; 2 | 3 | import es.joseluisgs.dam.models.Pais; 4 | import es.joseluisgs.dam.repositories.CRUDRepository; 5 | 6 | import java.sql.SQLException; 7 | import java.util.Optional; 8 | 9 | // Toda nueva funcionalidad se extiende de la interfaz SOLID 10 | public interface IPaisRepository extends CRUDRepository { 11 | 12 | Optional findByNombre(String nombre) throws SQLException; 13 | 14 | void clearAll() throws SQLException; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/src/main/java/es/joseluisgs/dam/services/Storage/IStorage.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.services.Storage; 2 | 3 | public interface IStorage { 4 | 5 | /** 6 | * Salva los elementos almacenados en item. 7 | * 8 | * @param item Elementos a almacenar. 9 | * @return true si se ha almacenado correctamente, false en caso contrario. 10 | */ 11 | boolean save(T item); 12 | 13 | /** 14 | * Le el almacenado y lo devuelve en un item T. 15 | * 16 | * @return Elementos almacenados. 17 | */ 18 | T load(); 19 | 20 | /** 21 | * Devuelve el path de la ubicación del almacenado. 22 | * 23 | * @return Path de la ubicación del almacenado. 24 | */ 25 | String getStoragePath(); 26 | } 27 | -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/src/main/java/es/joseluisgs/dam/services/Storage/IStorageBackup.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.services.Storage; 2 | 3 | import es.joseluisgs.dam.models.Backup; 4 | 5 | public interface IStorageBackup extends IStorage { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/src/main/java/es/joseluisgs/dam/services/Storage/StorageBackupJsonFile.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.services.Storage; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.GsonBuilder; 5 | import com.google.gson.reflect.TypeToken; 6 | import es.joseluisgs.dam.models.Backup; 7 | 8 | import javax.inject.Inject; 9 | import java.io.*; 10 | import java.nio.file.Files; 11 | import java.nio.file.Path; 12 | import java.nio.file.Paths; 13 | 14 | public class StorageBackupJsonFile implements IStorageBackup { 15 | 16 | private final Path currentRelativePath = Paths.get(""); 17 | private final String ruta = currentRelativePath.toAbsolutePath().toString(); 18 | private final String dir = ruta + File.separator + "data"; 19 | private final String backupFile = dir + File.separator + "backup.json"; 20 | 21 | @Inject 22 | public StorageBackupJsonFile() { 23 | init(); 24 | } 25 | 26 | private void init() { 27 | Path path = Paths.get(dir); 28 | if (!Files.exists(path)) { 29 | try { 30 | Files.createDirectories(path); 31 | } catch (IOException e) { 32 | System.out.println("Error: " + e.getMessage()); 33 | } 34 | } 35 | } 36 | 37 | @Override 38 | public boolean save(Backup backup) { 39 | Gson gson = new GsonBuilder().setPrettyPrinting().create(); 40 | boolean result = false; 41 | PrintWriter f = null; 42 | try { 43 | f = new PrintWriter(new FileWriter(backupFile)); 44 | f.println(gson.toJson(backup)); 45 | result = true; 46 | 47 | } catch (Exception e) { 48 | System.out.println("Error: " + e.getMessage()); 49 | result = false; 50 | } finally { 51 | if (f != null) { 52 | f.close(); 53 | } 54 | } 55 | return result; 56 | } 57 | 58 | @Override 59 | public Backup load() { 60 | Gson gson = new GsonBuilder().setPrettyPrinting().create(); 61 | Backup backup = null; 62 | Reader reader = null; 63 | try { 64 | reader = Files.newBufferedReader(Paths.get(backupFile)); 65 | backup = gson.fromJson(reader, new TypeToken() { 66 | }.getType()); 67 | } catch (Exception e) { 68 | System.out.println("Error: " + e.getMessage()); 69 | } finally { 70 | if (reader != null) { 71 | try { 72 | reader.close(); 73 | } catch (IOException e) { 74 | System.out.println("Error: " + e.getMessage()); 75 | } 76 | } 77 | } 78 | return backup; 79 | } 80 | 81 | @Override 82 | public String getStoragePath() { 83 | return backupFile; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/src/main/java/es/joseluisgs/dam/utils/ApplicationProperties.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.utils; 2 | 3 | import java.io.IOException; 4 | import java.util.Properties; 5 | import java.util.logging.Level; 6 | import java.util.logging.Logger; 7 | 8 | public class ApplicationProperties { 9 | private final Properties properties; 10 | 11 | public ApplicationProperties() { 12 | properties = new Properties(); 13 | try { 14 | // De esta manera leemos desde el fichero de propiedades en resources 15 | properties.load(getClass().getClassLoader().getResourceAsStream("application.properties")); 16 | 17 | } catch (IOException ex) { 18 | System.err.println("IOException Ocurrido al leer el fichero de propiedades: " + ex.getMessage()); 19 | Logger.getLogger(getClass().getName()).log(Level.ALL, "IOException Ocurrido al leer el fichero de propiedades: " + ex.getMessage()); 20 | } 21 | } 22 | 23 | public String readProperty(String keyName) { 24 | // Logger.getLogger(getClass().getName()).log(Level.INFO, "Leyendo propiedad " + keyName); 25 | return properties.getProperty(keyName, "No existe esa clave en el fichero de propiedades"); 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/src/main/java/es/joseluisgs/dam/utils/Console.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.utils; 2 | 3 | import java.util.Scanner; 4 | 5 | /** 6 | * Clase que permite leer datos desde la consola. 7 | */ 8 | public class Console { 9 | public static String getString(String message) { 10 | System.out.println(message); 11 | return new Scanner(System.in).nextLine().trim(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/src/main/java/es/joseluisgs/dam/utils/Formatter.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.utils; 2 | 3 | import java.text.NumberFormat; 4 | import java.time.LocalDateTime; 5 | import java.time.format.DateTimeFormatter; 6 | import java.time.format.FormatStyle; 7 | import java.util.Locale; 8 | 9 | public class Formatter { 10 | 11 | public static String dateParser(LocalDateTime date) { 12 | final Locale locale = new Locale("es", "ES"); 13 | // private String pattern = "dd/MM/yyyy"; 14 | return date.format(DateTimeFormatter 15 | .ofLocalizedDate(FormatStyle.MEDIUM).withLocale(locale)); 16 | } 17 | 18 | public static String moneyParser(Double money) { 19 | final Locale locale = new Locale("es", "ES"); 20 | return NumberFormat.getCurrencyInstance(locale).format(money); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joseluisgs/Programacion-09-2021-2022/188c0476c2f30e7149340dda33239a3df1488e4b/Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/src/main/resources/application.properties -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/src/main/resources/sql/init-db.sql: -------------------------------------------------------------------------------- 1 | -- Adminer 4.8.1 MySQL 5.5.5-10.6.4-MariaDB dump 2 | 3 | SET NAMES utf8; 4 | SET 5 | time_zone = '+00:00'; 6 | SET 7 | foreign_key_checks = 0; 8 | SET 9 | sql_mode = 'NO_AUTO_VALUE_ON_ZERO'; 10 | 11 | DROP 12 | DATABASE IF EXISTS `dam`; 13 | CREATE 14 | DATABASE `dam` /*!40100 DEFAULT CHARACTER SET utf8mb3 */; 15 | USE 16 | `dam`; 17 | 18 | DROP TABLE IF EXISTS `acuerdo`; 19 | CREATE TABLE `acuerdo` 20 | ( 21 | `id` int(11) NOT NULL AUTO_INCREMENT, 22 | `nombre` varchar(100) NOT NULL, 23 | `fecha` datetime NOT NULL, 24 | `aportacion` double NOT NULL, 25 | PRIMARY KEY (`id`) 26 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; 27 | 28 | INSERT INTO `acuerdo` (`id`, `nombre`, `fecha`, `aportacion`) 29 | VALUES (1, 'Acuerdo Diplomático', '2022-03-25 20:59:57', 12345.89), 30 | (2, 'Acuerdo de Fronteras', '2022-03-25 21:01:40', 999.99); 31 | 32 | DROP TABLE IF EXISTS `linea_acuerdo`; 33 | CREATE TABLE `linea_acuerdo` 34 | ( 35 | `id_acuerdo` int(11) NOT NULL, 36 | `id_pais` int(11) NOT NULL, 37 | `año` int(11) NOT NULL, 38 | `subvencion` double NOT NULL, 39 | KEY `id_acuerdo` (`id_acuerdo`), 40 | KEY `id_pais` (`id_pais`), 41 | CONSTRAINT `linea_acuerdo_ibfk_1` FOREIGN KEY (`id_acuerdo`) REFERENCES `acuerdo` (`id`) ON DELETE CASCADE 42 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; 43 | 44 | INSERT INTO `linea_acuerdo` (`id_acuerdo`, `id_pais`, `año`, `subvencion`) 45 | VALUES (1, 1, 2022, 1234.56), 46 | (1, 2, 2022, 345.32), 47 | (2, 4, 2022, 450.8), 48 | (2, 7, 2022, 6666.66), 49 | (2, 2, 2022, 333.33); 50 | 51 | DROP TABLE IF EXISTS `pais`; 52 | CREATE TABLE `pais` 53 | ( 54 | `id` int(11) NOT NULL AUTO_INCREMENT, 55 | `nombre` varchar(100) NOT NULL, 56 | `codigo` varchar(5) NOT NULL, 57 | `idioma` varchar(100) NOT NULL, 58 | `moneda` varchar(50) NOT NULL, 59 | `capital` varchar(100) NOT NULL, 60 | `presupuesto` double DEFAULT NULL, 61 | PRIMARY KEY (`id`) 62 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; 63 | 64 | INSERT INTO `pais` (`id`, `nombre`, `codigo`, `idioma`, `moneda`, `capital`, `presupuesto`) 65 | VALUES (1, 'España', 'ES', 'Español', 'Euro', 'Madrid', 1234567.23), 66 | (2, 'Francia', 'FR', 'Francés', 'Euro', 'París', 123456.67), 67 | (3, 'Italia', 'IT', 'Italiano', 'Euro', 'Roma', 564568.34), 68 | (4, 'Alemania', 'DE', 'Alemán', 'Euro', 'Berlín', 234567.23), 69 | (5, 'Reino Unido', 'UK', 'Inglés', 'Libra', 'Londres', 232323.34), 70 | (6, 'Japón', 'JP', 'Jsaponés', 'Yen', 'Tokio', 21212.12), 71 | (7, 'China', 'CN', 'Chino', 'Yuan', 'Pekín', 121212.34), 72 | (8, 'Australia', 'AU', 'Inglés', 'Dólar', 'Canberra', 567654.23), 73 | (9, 'Argentina', 'AR', 'Español', 'Peso', 'Buenos Aires', 123456.34), 74 | (10, 'Brasil', 'BR', 'Portugués', 'Real', 'Brasilia', 251251.62), 75 | (11, 'Estados Unidos', 'US', 'Inglés', 'Dólar', 'Washington', 1212415.98); 76 | 77 | -- 2022-03-26 11:15:34 -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/src/test/java/es/joseluisgs/dam/MainTest.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | import static org.junit.jupiter.api.Assertions.assertTrue; 6 | 7 | class MainTest { 8 | 9 | @Test 10 | public void trueIsTrue() { 11 | assertTrue(true); 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/src/test/java/es/joseluisgs/dam/utilities/DataBase.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.utilities; 2 | 3 | import es.joseluisgs.dam.Main; 4 | import es.joseluisgs.dam.controllers.DataBaseManager; 5 | import es.joseluisgs.dam.utils.ApplicationProperties; 6 | 7 | import java.io.File; 8 | import java.io.FileNotFoundException; 9 | import java.sql.SQLException; 10 | 11 | public class DataBase { 12 | 13 | /** 14 | * Inicia la base de datos con los datos de prueba si los hay, o la estructura de la tabla... 15 | */ 16 | public static void init() { 17 | ApplicationProperties properties = new ApplicationProperties(); 18 | boolean init = Boolean.parseBoolean(properties.readProperty("database.initdata")); 19 | if (init) { 20 | DataBaseManager controller = DataBaseManager.getInstance(); 21 | String dataPath = "sql" + File.separator + "init-db.sql"; 22 | try { 23 | var sqlFile = Main.class.getClassLoader().getResource(dataPath).getPath(); 24 | controller.open(); 25 | controller.initData(sqlFile, false); 26 | controller.close(); 27 | } catch (SQLException e) { 28 | System.err.println("Error al conectar al servidor de Base de Datos: " + e.getMessage()); 29 | System.exit(1); 30 | } catch (FileNotFoundException e) { 31 | System.err.println("Error al leer el fichero de datos iniciales: " + e.getMessage()); 32 | System.exit(1); 33 | } 34 | } 35 | } 36 | 37 | /** 38 | * Borra todas las tablas, que cuesta menos que tirar toda la base de datos y levantarla de nuevo 39 | * 40 | * @throws SQLException 41 | */ 42 | public static void deleteAll() throws SQLException { 43 | DataBaseManager db = DataBaseManager.getInstance(); 44 | String query = "DELETE FROM pais"; 45 | db.open(); 46 | db.delete(query); 47 | query = "DELETE FROM acuerdo"; 48 | db.beginTransaction(); 49 | db.delete(query); 50 | query = "DELETE FROM linea_acuerdo"; 51 | db.delete(query); 52 | db.commit(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/src/test/java/es/joseluisgs/dam/utilities/DataDB.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.utilities; 2 | 3 | import es.joseluisgs.dam.controllers.DataBaseManager; 4 | import es.joseluisgs.dam.models.Acuerdo; 5 | import es.joseluisgs.dam.models.LineaAcuerdo; 6 | import es.joseluisgs.dam.models.Pais; 7 | 8 | import java.sql.ResultSet; 9 | import java.sql.SQLException; 10 | import java.util.Optional; 11 | 12 | public class DataDB { 13 | // Insertamos un dato de prueba, aquí vemos un acoplamiento... 14 | // Si no quiseramos esto, podríamos usar Order de test 15 | // Lo ideal es meterlo en el script, e iniciarlo cada vez... 16 | public static void insertPaisTest(Pais paisTest) throws SQLException { 17 | String query = "INSERT INTO pais VALUES (null, ?, ?, ?, ?, ?, ?)"; 18 | DataBaseManager db = DataBaseManager.getInstance(); 19 | db.open(); 20 | Optional res = db.insert(query, paisTest.getNombre(), paisTest.getCodigo(), paisTest.getIdioma(), paisTest.getMoneda(), 21 | paisTest.getCapital(), paisTest.getPresupuesto()); 22 | if (res.get().first()) { 23 | paisTest.setId(res.get().getInt(1)); 24 | } 25 | db.close(); 26 | } 27 | 28 | public static void insertAcuerdoTest(Acuerdo acuerdoTest) throws SQLException { 29 | // OJO pongo null en el primer parámetro porque no inserto el ID, este se genera automático. Mira el DBMAnager 30 | String query = "INSERT INTO acuerdo VALUES (null, ?, ?, ?)"; 31 | DataBaseManager db = DataBaseManager.getInstance(); 32 | // Es una transacción, por lo que si falla alguna de las dos, se cancela todo 33 | db.open(); 34 | db.beginTransaction(); 35 | ResultSet res = db.insert(query, acuerdoTest.getNombre(), acuerdoTest.getFecha(), acuerdoTest.getAportacion()) 36 | .orElseThrow(() -> new SQLException("Error al insertar acuerdo")); 37 | 38 | // Para obtener su ID que ha generado la BD 39 | if (res.first()) { 40 | acuerdoTest.setId(res.getInt(1)); 41 | // Ahora salvamos toda las lineas de acuerdo... 42 | for (LineaAcuerdo linea : acuerdoTest.getLineas()) { 43 | query = "INSERT INTO linea_acuerdo VALUES (?, ?, ?, ?)"; 44 | db.insert(query, acuerdoTest.getId(), linea.getPais().getId(), linea.getAño(), linea.getSubvencion()) 45 | .orElseThrow(() -> new SQLException("Error al insertar linea de acuerdo")); 46 | } 47 | 48 | // Y finalmente cerramos la conexión y devolvemos el acuerdo 49 | db.commit(); 50 | db.close(); 51 | } 52 | db.rollback(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/src/test/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joseluisgs/Programacion-09-2021-2022/188c0476c2f30e7149340dda33239a3df1488e4b/Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/src/test/resources/application.properties -------------------------------------------------------------------------------- /Soluciones/10-MVC-Paises-BBDD-Dagger-Lombok/src/test/resources/sql/init-db.sql: -------------------------------------------------------------------------------- 1 | -- Adminer 4.8.1 MySQL 5.5.5-10.6.4-MariaDB dump 2 | 3 | SET NAMES utf8; 4 | SET 5 | time_zone = '+00:00'; 6 | SET 7 | foreign_key_checks = 0; 8 | SET 9 | sql_mode = 'NO_AUTO_VALUE_ON_ZERO'; 10 | 11 | DROP 12 | DATABASE IF EXISTS `dam`; 13 | CREATE 14 | DATABASE `dam` /*!40100 DEFAULT CHARACTER SET utf8mb3 */; 15 | USE 16 | `dam`; 17 | 18 | DROP TABLE IF EXISTS `acuerdo`; 19 | CREATE TABLE `acuerdo` 20 | ( 21 | `id` int(11) NOT NULL AUTO_INCREMENT, 22 | `nombre` varchar(100) NOT NULL, 23 | `fecha` datetime NOT NULL, 24 | `aportacion` double NOT NULL, 25 | PRIMARY KEY (`id`) 26 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; 27 | 28 | 29 | DROP TABLE IF EXISTS `linea_acuerdo`; 30 | CREATE TABLE `linea_acuerdo` 31 | ( 32 | `id_acuerdo` int(11) NOT NULL, 33 | `id_pais` int(11) NOT NULL, 34 | `año` int(11) NOT NULL, 35 | `subvencion` double NOT NULL, 36 | KEY `id_acuerdo` (`id_acuerdo`), 37 | KEY `id_pais` (`id_pais`), 38 | CONSTRAINT `linea_acuerdo_ibfk_1` FOREIGN KEY (`id_acuerdo`) REFERENCES `acuerdo` (`id`) ON DELETE CASCADE 39 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; 40 | 41 | DROP TABLE IF EXISTS `pais`; 42 | CREATE TABLE `pais` 43 | ( 44 | `id` int(11) NOT NULL AUTO_INCREMENT, 45 | `nombre` varchar(100) NOT NULL, 46 | `codigo` varchar(5) NOT NULL, 47 | `idioma` varchar(100) NOT NULL, 48 | `moneda` varchar(50) NOT NULL, 49 | `capital` varchar(100) NOT NULL, 50 | `presupuesto` double DEFAULT NULL, 51 | PRIMARY KEY (`id`) 52 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; 53 | 54 | -- 2022-03-26 11:15:34 -------------------------------------------------------------------------------- /Soluciones/11-CRUD-SQLite-GSon/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | !**/src/main/**/target/ 4 | !**/src/test/**/target/ 5 | 6 | ### IntelliJ IDEA ### 7 | .idea/modules.xml 8 | .idea/jarRepositories.xml 9 | .idea/compiler.xml 10 | .idea/libraries/ 11 | *.iws 12 | *.iml 13 | *.ipr 14 | 15 | ### Eclipse ### 16 | .apt_generated 17 | .classpath 18 | .factorypath 19 | .project 20 | .settings 21 | .springBeans 22 | .sts4-cache 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | build/ 31 | !**/src/main/**/build/ 32 | !**/src/test/**/build/ 33 | 34 | ### VS Code ### 35 | .vscode/ 36 | 37 | ### Mac OS ### 38 | .DS_Storedata/ 39 | -------------------------------------------------------------------------------- /Soluciones/11-CRUD-SQLite-GSon/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /Soluciones/11-CRUD-SQLite-GSon/.idea/dataSources.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | sqlite.xerial 6 | true 7 | org.sqlite.JDBC 8 | jdbc:sqlite:$PROJECT_DIR$/db/personas.db 9 | $ProjectFileDir$ 10 | 11 | 12 | file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.36.0.3/sqlite-jdbc-3.36.0.3.jar 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Soluciones/11-CRUD-SQLite-GSon/.idea/deployment.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /Soluciones/11-CRUD-SQLite-GSon/.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | -------------------------------------------------------------------------------- /Soluciones/11-CRUD-SQLite-GSon/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 13 | 14 | 15 | 16 | 17 | 18 | 21 | 22 | -------------------------------------------------------------------------------- /Soluciones/11-CRUD-SQLite-GSon/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Soluciones/11-CRUD-SQLite-GSon/data/personas.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 93, 4 | "uuid": "c5833b1f-808e-4fad-9971-553035418e1a", 5 | "nombre": "Pepito Update", 6 | "edad": 31, 7 | "createdAt": "2022-04-22" 8 | }, 9 | { 10 | "id": 95, 11 | "uuid": "e75e379e-64d1-4623-90f3-dc7dccadebfd", 12 | "nombre": "Anita", 13 | "edad": 25, 14 | "createdAt": "2022-04-22" 15 | } 16 | ] -------------------------------------------------------------------------------- /Soluciones/11-CRUD-SQLite-GSon/db/personas.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joseluisgs/Programacion-09-2021-2022/188c0476c2f30e7149340dda33239a3df1488e4b/Soluciones/11-CRUD-SQLite-GSon/db/personas.db -------------------------------------------------------------------------------- /Soluciones/11-CRUD-SQLite-GSon/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | es.joseluisgs.dam 8 | CRUDSQlite 9 | 1.0-SNAPSHOT 10 | 11 | 12 | 17 13 | 17 14 | 15 | 16 | 17 | 18 | org.xerial 19 | sqlite-jdbc 20 | 3.36.0.3 21 | 22 | 23 | 24 | org.projectlombok 25 | lombok 26 | 1.18.22 27 | compile 28 | 29 | 30 | 31 | org.mybatis 32 | mybatis 33 | 3.5.9 34 | 35 | 36 | 37 | org.projectlombok 38 | lombok 39 | 1.18.22 40 | compile 41 | 42 | 43 | 44 | com.google.code.gson 45 | gson 46 | 2.9.0 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /Soluciones/11-CRUD-SQLite-GSon/src/main/java/es/joseluisgs/dam/controllers/PersonasController.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.controllers; 2 | 3 | import es.joseluisgs.dam.models.Persona; 4 | import es.joseluisgs.dam.repositories.IPersonasRepository; 5 | 6 | import java.io.IOException; 7 | import java.sql.SQLException; 8 | import java.util.List; 9 | 10 | public class PersonasController { 11 | private final IPersonasRepository personasRepository; 12 | 13 | public PersonasController(IPersonasRepository personasRepository) { 14 | this.personasRepository = personasRepository; 15 | } 16 | 17 | public Persona savePersona(Persona persona) { 18 | try { 19 | return personasRepository.save(persona); 20 | } catch (SQLException e) { 21 | System.err.println("Error al guardar persona: " + e.getMessage()); 22 | } 23 | return null; 24 | } 25 | 26 | public void deleteAll() { 27 | try { 28 | personasRepository.deleteAll(); 29 | } catch (SQLException e) { 30 | System.err.println("Error al borrar todas las personas: " + e.getMessage()); 31 | } 32 | } 33 | 34 | public List findAll() { 35 | try { 36 | return personasRepository.findAll(); 37 | } catch (SQLException e) { 38 | System.err.println("Error al buscar todas las personas: " + e.getMessage()); 39 | } 40 | return null; 41 | } 42 | 43 | public Persona update(Persona persona) { 44 | try { 45 | return personasRepository.update(persona.getId(), persona); 46 | } catch (SQLException e) { 47 | System.err.println("Error al actualizar persona: " + e.getMessage()); 48 | } 49 | return null; 50 | } 51 | 52 | public Persona findById(int id) { 53 | try { 54 | return personasRepository.findById(id).orElseThrow(() -> new RuntimeException("No existe la persona con id " + id)); 55 | } catch (SQLException e) { 56 | System.err.println("Error al buscar persona: " + e.getMessage()); 57 | } 58 | return null; 59 | } 60 | 61 | public Persona delete(Persona persona) { 62 | try { 63 | return personasRepository.delete(persona.getId()); 64 | } catch (SQLException e) { 65 | System.err.println("Error al borrar persona: " + e.getMessage()); 66 | } 67 | return null; 68 | } 69 | 70 | public void backup() { 71 | try { 72 | personasRepository.backup(); 73 | } catch (IOException | SQLException e) { 74 | System.err.println("Error al hacer backup: " + e.getMessage()); 75 | } 76 | } 77 | 78 | public void restore() { 79 | try { 80 | personasRepository.restore(); 81 | } catch (IOException | SQLException e) { 82 | System.err.println("Error al hacer restore: " + e.getMessage()); 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Soluciones/11-CRUD-SQLite-GSon/src/main/java/es/joseluisgs/dam/models/Persona.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.models; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | 6 | import java.time.LocalDate; 7 | import java.util.UUID; 8 | 9 | /** 10 | * Mi consejo es que a partir de poco uses UUIDs para identificar a las personas. 11 | * y no claves autonumericas, pronto lo entenderás 12 | */ 13 | @Data 14 | @Builder 15 | public class Persona { 16 | private int id; 17 | private UUID uuid; 18 | private String nombre; 19 | private int edad; 20 | private LocalDate createdAt; 21 | } 22 | -------------------------------------------------------------------------------- /Soluciones/11-CRUD-SQLite-GSon/src/main/java/es/joseluisgs/dam/repositories/CRUDRepository.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.repositories; 2 | 3 | import java.sql.SQLException; 4 | import java.util.List; 5 | import java.util.Optional; 6 | 7 | public interface CRUDRepository { 8 | /** 9 | * Devuelve una lista de todos los elementos del repositorio 10 | * 11 | * @return Lista de elementos 12 | * @throws SQLException Si hay algún error en la base de datos 13 | */ 14 | List findAll() throws SQLException; 15 | 16 | /** 17 | * Devuelve un Optional del elemento dada una id 18 | * 19 | * @param id Id del elemento 20 | * @return Optional del elemento 21 | * @throws SQLException Si hay algún error en la base de datos 22 | */ 23 | Optional findById(ID id) throws SQLException; 24 | 25 | /** 26 | * Inserta un elemento en el repositorio 27 | * 28 | * @param entity Elemento a insertar 29 | * @return Elemento insertado 30 | * @throws SQLException Si hay algún error en la base de datos 31 | */ 32 | T save(T entity) throws SQLException; 33 | 34 | /** 35 | * Actualiza un elemento en el repositorio 36 | * 37 | * @param id Id del elemento a actualizar 38 | * @param entity Elemento a actualizar 39 | * @return Elemento actualizado 40 | * @throws SQLException Si hay algún error en la base de datos 41 | */ 42 | T update(ID id, T entity) throws SQLException; 43 | 44 | /** 45 | * Elimina un elemento del repositorio 46 | * 47 | * @param id Id del elemento a eliminar 48 | * @return Elemento eliminado 49 | * @throws SQLException Si hay algún error en la base de datos 50 | */ 51 | T delete(ID id) throws SQLException; 52 | } 53 | -------------------------------------------------------------------------------- /Soluciones/11-CRUD-SQLite-GSon/src/main/java/es/joseluisgs/dam/repositories/IPersonasRepository.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.repositories; 2 | 3 | import es.joseluisgs.dam.models.Persona; 4 | 5 | import java.io.IOException; 6 | import java.sql.SQLException; 7 | 8 | public interface IPersonasRepository extends CRUDRepository { 9 | void deleteAll() throws SQLException; 10 | 11 | void backup() throws SQLException, IOException; 12 | 13 | void restore() throws SQLException, IOException; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /Soluciones/11-CRUD-SQLite-GSon/src/main/java/es/joseluisgs/dam/services/Backup.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.services; 2 | 3 | import java.io.IOException; 4 | import java.util.List; 5 | 6 | public interface Backup { 7 | void backup(List data) throws IOException; 8 | 9 | List restore() throws IOException; 10 | } 11 | -------------------------------------------------------------------------------- /Soluciones/11-CRUD-SQLite-GSon/src/main/java/es/joseluisgs/dam/services/BackupJSON.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.services; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.GsonBuilder; 5 | import com.google.gson.reflect.TypeToken; 6 | import es.joseluisgs.dam.models.Persona; 7 | import es.joseluisgs.dam.utils.LocalDateAdapter; 8 | 9 | import java.io.File; 10 | import java.io.IOException; 11 | import java.nio.file.Files; 12 | import java.time.LocalDate; 13 | import java.util.List; 14 | 15 | public class BackupJSON implements IBackupJSON { 16 | private static BackupJSON instance; 17 | private final String APP_PATH = System.getProperty("user.dir"); 18 | private final String DATA_DIR = APP_PATH + File.separator + "data"; 19 | private final String BACKUP_FILE = DATA_DIR + File.separator + "personas.json"; 20 | 21 | private BackupJSON() { 22 | File dataDir = new File(DATA_DIR); 23 | if (!dataDir.exists()) { 24 | dataDir.mkdir(); 25 | } 26 | } 27 | 28 | 29 | public static BackupJSON getInstance() { 30 | if (instance == null) { 31 | instance = new BackupJSON(); 32 | } 33 | return instance; 34 | } 35 | 36 | 37 | @Override 38 | public void backup(List personas) throws IOException { 39 | Gson gson = new GsonBuilder() 40 | .registerTypeAdapter(LocalDate.class, new LocalDateAdapter()) 41 | .setPrettyPrinting() 42 | .create(); 43 | String json = gson.toJson(personas); 44 | Files.writeString(new File(BACKUP_FILE).toPath(), json); 45 | } 46 | 47 | 48 | @Override 49 | public List restore() throws IOException { 50 | Gson gson = new GsonBuilder() 51 | .registerTypeAdapter(LocalDate.class, new LocalDateAdapter()) 52 | .create(); 53 | String json = ""; 54 | json = Files.readString(new File(BACKUP_FILE).toPath()); 55 | return gson.fromJson(json, new TypeToken>() { 56 | }.getType()); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Soluciones/11-CRUD-SQLite-GSon/src/main/java/es/joseluisgs/dam/services/IBackupJSON.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.services; 2 | 3 | import es.joseluisgs.dam.models.Persona; 4 | 5 | public interface IBackupJSON extends Backup { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /Soluciones/11-CRUD-SQLite-GSon/src/main/java/es/joseluisgs/dam/utils/LocalDateAdapter.java: -------------------------------------------------------------------------------- 1 | package es.joseluisgs.dam.utils; 2 | 3 | import com.google.gson.TypeAdapter; 4 | import com.google.gson.stream.JsonReader; 5 | import com.google.gson.stream.JsonWriter; 6 | 7 | import java.io.IOException; 8 | import java.time.LocalDate; 9 | 10 | // Esto es porque GSON no se pensó para Java 11 hacia arriba, mejor usar Jackson o Moshi 11 | // Tiene problemas con las fechas LocalDate y LocalDateTime 12 | public class LocalDateAdapter extends TypeAdapter { 13 | 14 | @Override 15 | public LocalDate read(final JsonReader jsonReader) throws IOException { 16 | return LocalDate.parse(jsonReader.nextString()); 17 | } 18 | 19 | @Override 20 | public void write(JsonWriter jsonWriter, LocalDate localDate) throws IOException { 21 | jsonWriter.value(localDate.toString()); 22 | 23 | } 24 | } -------------------------------------------------------------------------------- /UD09.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joseluisgs/Programacion-09-2021-2022/188c0476c2f30e7149340dda33239a3df1488e4b/UD09.pdf --------------------------------------------------------------------------------