Saltar navegación

20260120 JPA_5 - Contenido educativo

Ajuste de pantalla

El ajuste de pantalla se aprecia al ver el vídeo en pantalla completa. Elige la presentación que más te guste:

Subido el 27 de enero de 2026 por Raquel G.

1 visualizaciones

Descargar la transcripción

Bueno, pues entonces, así rápidamente, recordad que las herramientas ORM que nos facilitan el acceso a las bases de datos porque nos ocultan el SQL y nos permiten trabajar directamente con los objetos, siempre y cuando sean persistentes, 00:00:00
Que esas herramientas necesitaban una configuración, lógicamente, en el modelo de datos para que pudieran hacer un mapeo con las tablas. Eso lo habíamos hecho aquí, a través de las anotaciones, ¿vale? Que esto todo lo habréis repasado y lo tendréis más o menos claro, ¿vale? 00:00:18
Entonces, ahora ya que teníamos el modelo de datos con las anotaciones que especificaban exactamente la correspondencia entre tablas y clases, a partir de ahí ya podemos trabajar directamente con los objetos, una vez que los hayamos hecho persistentes, ¿vale? 00:00:36
Entonces, para eso, pues probamos hacerlo mediante un main así a lo bestia, ¿vale? Mediante un main así a lo bestia, pues probamos a hacerlo directamente con JPA, que exigía crear un contexto de persistencia, que es este, que se crea a través de un factory, como casi todas las cosas, y una vez creado el contexto de persistencia, ya podíamos trabajar en transacción o no. 00:00:51
En transacción obligatorio siempre y cuando quisiéramos hacer modificaciones en la base de datos. 00:01:21
Si no hay modificaciones en la base de datos, no obligatorio en transacción. 00:01:27
¿Vale? 00:01:30
Entonces, si estamos trabajando en transacción, se empieza así. 00:01:31
Y ahora ya, nuestros objetos de nuestro modelo, si son persistentes, cualquier cambio que hagamos en ellos, cualquier modificación, se va a reflejar en la base de datos según hacemos commit. 00:01:34
¿Vale? 00:01:47
entonces, ¿cómo hacemos 00:01:47
que los objetos sean persistentes? 00:01:50
¿cómo lo hacemos? pues esencialmente 00:01:52
de dos maneras 00:01:54
si el dato ya existe 00:01:55
el dato, lo podemos recuperar 00:01:58
de la base de datos con find y ya está 00:02:00
este objeto se convierte en persistente 00:02:02
y cualquier cambio que hagamos en él 00:02:04
para nuestra aplicación ya se va a quedar reflejado 00:02:05
en la base de datos 00:02:08
según hagamos con mi 00:02:10
esta es una manera de hacerlo persistente 00:02:11
y la otra 00:02:14
si mi dato todavía no existe 00:02:15
yo tengo el objeto 00:02:24
ese objeto es transitorio 00:02:26
y el dato no está en la base de datos todavía 00:02:28
yo haciendo esto 00:02:30
no solo lo convierto en persistente 00:02:33
sino que ya lo dejo marcado 00:02:36
para que se guarde en base de datos 00:02:37
cuando se haga el commit 00:02:39
ya cuando se haga el commit 00:02:41
todos los cambios se dejarán en la base de datos 00:02:43
entonces, cuando tenemos objetos persistentes 00:02:46
bien por el find, bien por el persist 00:02:49
la base de datos 00:02:51
perdón 00:02:52
el ORM, que en nuestro caso es 00:02:53
hibernate, claro, es el que implementa JPA 00:02:56
el ORM ya, según vayamos haciendo 00:02:58
cambios, la aplicación pues va trabajando con los objetos 00:03:00
pero es que además hibernate los va dejando 00:03:03
marcaditos, para que cuando llegue el commit 00:03:04
decir, uy, que estos se modificaron 00:03:06
desde su estado inicial de la base de datos 00:03:08
que no se me olvide, dejarlos tal y como 00:03:10
los ha dejado este humano 00:03:12
en su toqueteo, ¿vale? 00:03:14
Esencialmente esa era la idea. 00:03:17
Entonces, teníamos persist, find para recuperar, remove 00:03:19
si queremos marcar un objeto para que sea borrado, 00:03:23
métodos por si queremos sacarlos también del estado persistente a transitorio, 00:03:27
porque los objetos de mi aplicación pueden estar manejados por hibernate 00:03:32
o no manejados por hibernate. 00:03:39
Si están manejados por hibernate, son persistentes 00:03:41
y todos los cambios se sincronizarán con la base de datos en el commit 00:03:43
y si no son persistentes y por tanto son transitorios, 00:03:47
la aplicación trabaja con ellos y en ningún momento se va a sincronizar 00:03:54
su estado con la base de datos, porque son transitorios, van por libre. 00:04:00
Entonces, pues teníamos métodos para si están en estado persistente 00:04:05
en un momento dado, queremos que dejen de estar sincronizados 00:04:08
una base de datos y por libre, pues ponerlos 00:04:11
al estado separado, que se llamaba 00:04:13
y luego además tenemos un lenguaje 00:04:15
de consultas que era el JPQL 00:04:17
para hacer consultas 00:04:20
cualquier tipo, igual que 00:04:23
las que hacemos con SQL, pues igual 00:04:26
recuperar por otros campos que no fueran la clave 00:04:27
porque recuperar por la clave era este, sí o sí 00:04:30
pues hacer 00:04:32
cualquier cosa que hacemos con SQL, pues la 00:04:34
podemos hacer con JPQL que era 00:04:35
que es parecido 00:04:37
Entonces, JPQL, las pautas básicas es que su sintaxis es similar a SQL 00:04:39
Pero no trabaja con nombres de tablas, sino con nombres de clases 00:04:46
Porque recordad que tabla es clase 00:04:51
Y campo de tabla es propiedad de clase 00:04:53
Entonces, en el JPQL jamás va a aparecer ningún identificador de la base de datos 00:04:57
Nunca, no va a aparecer nunca ni un nombre de tabla, ni un nombre de campo, nada 00:05:03
En JPQL solamente van a aparecer nombres de clases y nombres de propiedades de la clase, porque JPQL trabaja ahí, entonces aquí seleccionábamos de todos los empleados cuyo nombre fuera este parámetro de aquí, entonces fijábamos el parámetro y escogíamos el resultado, este es un ejemplo. 00:05:07
Luego JPQL 00:05:30
Si no quiere hacer algo específico 00:05:32
O bien se ha hecho un cursito de JPQL 00:05:34
Y se lo sabe todo 00:05:37
O si no, consulta específicamente 00:05:38
Oye, ¿cómo puedo hacer una consulta JPQL 00:05:40
Para que haga esto? 00:05:43
Pues ya está, si te la dicen bien 00:05:44
Estupendo, si te la dicen mal 00:05:46
Pues como tú sabes y controlas 00:05:48
Pues la cambias un poquito y ya está 00:05:49
¿Vale? Recordad que aquí el parámetro 00:05:51
No es como el prepare de statement 00:05:54
Que era con una interrogación 00:05:56
El parámetro es dos puntos 00:05:57
Y un nombre, el que a ti te dé la gana 00:05:59
Porque luego lo fijas 00:06:01
A través de ese nombre que tú hayas puesto ahí 00:06:03
Lo fijas a través de ese nombre 00:06:05
¿Es como la? 00:06:07
No, la es un alias 00:06:10
Porque en JPQL es obligatorio 00:06:11
Poner un alias 00:06:13
En este caso a la clase 00:06:15
No a la tabla 00:06:18
Es un alias para luego tú aquí referirte 00:06:18
A esto 00:06:22
Vale, JPQL es como 00:06:22
Una 00:06:27
Bueno, nada 00:06:28
vale, pues 00:06:30
para qué mencionar nombres para nada 00:06:33
para liar, vale 00:06:35
ya está, entonces 00:06:37
este es el uso del 00:06:39
JPA puro, de cómo funciona 00:06:41
JPA 00:06:43
pero nosotros lo que hicimos fue 00:06:45
vamos a meterlo en un patrón 00:06:47
de diseño un poco mejor, no vamos a poner esta mierda 00:06:49
de un main donde hacemos ahí todo 00:06:51
vale, entonces el patrón de diseño 00:06:53
de acceso a datos siempre es 00:06:55
el patrón DAO 00:06:57
Entonces, por cada entidad hacíamos una clase DAO 00:06:59
con las operaciones atómicas, en realidad. 00:07:02
Ahí, digamos que a los DAOs no les importan nada 00:07:06
los casos de uso de la aplicación. 00:07:09
Es decir, ¿para qué sirve mi aplicación? 00:07:11
Los casos de uso, los requisitos, como lo queráis llamar. 00:07:13
A los DAOs no les importan. 00:07:16
Los DAOs hacen el CRUD. 00:07:18
Y luego ya mi aplicación tendrá unos casos de uso, 00:07:21
unos requisitos. 00:07:24
Pues el servicio, la clase servicio, es la que los mete. Y ya la clase servicio llamará a los métodos DAO que necesite, a varios de ellos seguidos, a uno, a dos, según necesite para construir su caso de uso o su requisito. 00:07:25
Y ahí las transacciones, claro 00:07:42
Claro, porque un caso de uso 00:07:45
A lo mejor necesita 00:07:48
Llamar a varios DAO en transacción 00:07:49
Para que se haga todo o ninguno 00:07:51
Pues el sitio para manejarlo es ahí 00:07:52
Lo cual nos lleva 00:07:55
Ahora ya a nuestro DAO 00:07:57
Que 00:08:00
Era este 00:08:01
Y dijimos, hombre 00:08:03
Pues si se trata de un 00:08:05
CRUB básico 00:08:07
Pues vamos a jugar 00:08:08
un poco, vamos a hacerlo 00:08:11
genérico 00:08:13
porque este CRUD me vale para cualquier 00:08:14
entidad, me vale para 00:08:17
empleado, para departamento, para cualquiera 00:08:19
pues esa entidad 00:08:21
pero si la mayoría de casos de datos 00:08:22
se hacen en el periódico 00:08:25
el DAO solo se hace en el CRUD 00:08:26
normalmente, a ver, no es que haya una 00:08:28
rigidez en esto, pues hay una flexibilidad 00:08:31
en el DAO puede haber otros métodos 00:08:33
que no sean exclusivamente estos cuatro, porque el CRUD 00:08:35
es esto, vale, entonces 00:08:37
hombre, pues podéis ver dados con algunas otras cositas 00:08:39
porque 00:08:41
ese modelo de datos en particular 00:08:42
pues tiene una operación, que se hace mucho 00:08:45
lo que sea, pero la idea es que sean cosas 00:08:47
lo más atómicas posible 00:08:49
Sí, es la idea 00:08:51
pero todo esto son ideas generales 00:08:57
más o menos, pautas generales de diseño 00:08:59
luego ya pues podéis 00:09:01
encontrar muchas cosas 00:09:03
son como pautas generales y este sería 00:09:04
el club más puro del mundo 00:09:07
Claro, normalmente, efectivamente 00:09:08
Hacemos capas, pero además capas 00:09:27
En diferentes contextos semánticos 00:09:29
En el acceso a datos en particular 00:09:33
Pues sí, tú tienes tu modelo 00:09:37
El modelo que es independiente de cualquier acceso a datos 00:09:40
Ahora, resulta que ese modelo tiene una correspondencia con una base de datos y tú quieres, por tanto, poder hacer inserciones, pues bueno, lo haces, metes todo eso relacionado con el CRUD, todo eso lo metes en otra capa, que es la capa DAO, en esa capa DAO metes lo relacionado con el CRUD de ese modelo. 00:09:42
Ahora, normalmente tu aplicación 00:10:03
No hace insert, get, delete 00:10:05
Tu aplicación hará 00:10:07
Recuperar todos los empleados 00:10:08
A los que le falta un ojo 00:10:10
Pues yo que sé, hará esas cosas 00:10:12
Esas cosas no las metes aquí 00:10:13
Entonces, luego ya pones una clase 00:10:15
En la que pones todos esos casos de uso 00:10:17
Que es lo que hace tu aplicación 00:10:18
No son los casos de uso 00:10:20
La capa de servicio 00:10:21
También va asociada a un DAO 00:10:22
La capa de servicio 00:10:25
Usa objetos DAO 00:10:27
Los que necesite 00:10:28
Los que necesite 00:10:32
O los DAOs de una base 00:10:33
Usa los DAOs de la aplicación 00:10:35
Los que necesite 00:10:38
¿Vale? 00:10:39
Sí, lo que no sabía yo 00:10:43
Sí, claro, hombre 00:10:44
Lo que no sabía yo 00:10:45
Si teníamos la clase de servicios 00:10:46
Por cada DAO que necesitase 00:10:46
No necesariamente 00:10:48
No, eso no es tan rígido 00:10:49
La clase de servicios 00:10:51
Es como más abierta 00:10:52
El DAO es como más rígido 00:10:52
Que es 00:10:54
Tú tienes ahí 00:10:55
Normalmente 00:10:56
Normalmente 00:10:56
Un DAO 00:10:57
Por entidad 00:10:58
Con el CRUD 00:10:59
normalmente, pero son pautas 00:11:01
todo, ideas 00:11:03
y luego el servicio es como más abierto porque ya el servicio 00:11:03
sí que depende de la aplicación 00:11:07
y la aplicación hay mil 00:11:08
¿vale? 00:11:10
bueno, pues entonces, aquí 00:11:13
hay muy preguntones hoy 00:11:14
no me lo creo, seguro que el DAO se ha quedado claro 00:11:18
eso seguro 00:11:26
¿perdón? 00:11:26
A ver, el DAO 00:11:37
en cada aplicación se supone 00:11:43
que hay un DAO para su modelo de datos 00:11:46
y cada aplicación tendrá su modelo 00:11:48
de datos 00:11:50
entonces cada aplicación 00:11:50
con su modelo de datos y con modelo de datos 00:11:54
me refiero a las clases que definen 00:11:56
las entidades 00:11:58
con las que trabaja, empleados 00:11:59
facturas, pues cada aplicación 00:12:02
tiene su modelo de datos y su DAO 00:12:04
Y ya está, tú no coges DAOs de otra aplicación 00:12:05
Hombre, a ver, puedes hacer un copy y pega 00:12:08
Si tienes varias, pero 00:12:10
A ver, cuando digo DAO 00:12:11
Digo patrón DAO en general, que serán varias clases DAO 00:12:16
¿Vale? 00:12:18
En general, sí 00:12:21
Lo normal es una clase DAO 00:12:22
Por entidad, ¿vale? 00:12:24
Es lo habitual 00:12:26
Es la idea 00:12:27
¿Vale? Es la idea, porque luego además hay otras clases 00:12:28
Luego están, puedes hacer 00:12:32
incluso otra cosa intermedia que es 00:12:34
el DTO que se llama 00:12:36
que es una clase en la que metes un objeto 00:12:37
que vas a 00:12:40
llevarlo a la base 00:12:41
de datos pero todavía no 00:12:44
está en el DAO, pero bueno 00:12:46
nos olvidamos de esas cosas 00:12:47
porque si lo veis alguna vez pues veréis que es muy fácil 00:12:50
de entender, o sea que se pueden poner 00:12:52
todavía más capas intermedias me refiero 00:12:54
en el diseño, pero esto 00:12:56
es más que suficiente y lo habitual 00:12:58
modelo, DAO y el servicio 00:12:59
Encima que el servicio ya depende de la aplicación 00:13:02
Con lo cual el servicio ya es más abierto 00:13:05
¿Vale? Pero como pauta 00:13:07
¿Eh? 00:13:09
Pero vamos que DTO es nada, es otro 00:13:13
DTO es otra clase, una 00:13:15
Por entidad 00:13:17
También, ¿vale? Es un objeto 00:13:19
De transmisión de datos, el objeto 00:13:21
En donde tú metes los datos que vas a transmitir 00:13:23
¿Vale? 00:13:25
Vale 00:13:28
Justo 00:13:28
Bueno, creo, vamos, yo siempre digo 00:13:31
DTO y nunca de para pensar, pero asumo 00:13:33
por lo que hace que son data transmission 00:13:35
vale, pero nos olvidemos 00:13:37
de eso, porque eso son detallitos 00:13:40
luego veis una aplicación que tiene un DTO 00:13:41
y veréis que, bueno, vale, pues ya está 00:13:43
esto es trivial, no tiene más rollo 00:13:45
entendiendo un poco la filosofía 00:13:47
de diseño de las aplicaciones 00:13:50
que es desacoplar 00:13:51
vamos a desacoplar, vamos a hacer 00:13:53
todo en cosas separadas 00:13:55
aquí modelo, el modelo que no sepa nada 00:13:57
de cómo se hace el acceso a datos 00:13:59
El servicio que no sepa nada de cómo se hace 00:14:00
Tampoco el acceso a datos 00:14:03
Pero unas se llaman a otras porque se tienen que encargar las tareas 00:14:05
Bueno, pues dicho esto 00:14:08
Para 00:14:10
Pues jugar un poco 00:14:11
Y abrirnos la mente 00:14:13
Y que no os olvidéis de programar, sobre todo 00:14:15
Porque es lo que esencialmente todavía vais a hacer 00:14:17
Esperamos 00:14:19
Este es un DAO 00:14:20
Puro y duro 00:14:24
¿Vale? Un DAO puro y duro 00:14:26
Porque tiene el CRUD tal cual 00:14:27
Entonces para hacer dos DAOs 00:14:29
Idénticos en departamento y empleado 00:14:31
Pues hacemos uno genérico 00:14:33
Y ya está 00:14:35
Entonces T puede ser departamento o empleado 00:14:36
¿Y por qué habíamos puesto 00:14:40
Otro tipo genérico? 00:14:42
Porque 00:14:44
Algunos 00:14:45
Porque algunos 00:14:46
De estos métodos tiran de la clave 00:14:49
Como el GET 00:14:52
Entonces la clave, pues tampoco sabemos cuál es 00:14:52
El tipo de datos de la clave 00:14:56
Dependerá de la entidad que estemos 00:14:57
pues entonces esta es el DAO genérico 00:14:59
y además la interfaz sin más 00:15:03
entonces ahora vamos a implementarla 00:15:05
la implementación la podemos seguir dejando genérica 00:15:08
que era la que teníamos aquí 00:15:11
la implementación la podemos seguir dejando genérica 00:15:12
y ahora ya, si nos íbamos directamente 00:15:16
al método 00:15:21
crear, vale 00:15:22
crear 00:15:25
si yo tengo el objeto 00:15:28
Que quiero meter en la base de datos 00:15:30
Quiero hacer persistente 00:15:33
Insert 00:15:34
Quizá queda mejor 00:15:37
Lo que pasa es que 00:15:38
Vale, pues ya está 00:15:39
Haces el objeto persistente 00:15:42
Vale 00:15:44
Y se acabó, ahora volvemos aquí 00:15:45
El recuperar 00:15:48
El recuperar se hace por find 00:15:50
Pero recordad que aquí 00:15:52
Había que poner el objeto 00:15:53
Que describe la clase 00:15:56
¿Recordáis el rollo del punto class? 00:15:58
Del otro día 00:16:00
Vale, pues entonces 00:16:01
¿Qué ocurre? Que el objeto que describe la clase 00:16:04
Depende 00:16:06
Será o departamento.class 00:16:07
O empleado.class 00:16:10
O alumno.class, no lo sé 00:16:11
¿Cuál es? Porque depende de T 00:16:14
Y T.class no puede ser 00:16:16
Por eso se lo pasábamos por parámetro 00:16:18
Claro, si tú ya das 00:16:20
Si este fuera departamento.dao 00:16:23
Tú aquí pondrías 00:16:25
Departamento.class 00:16:27
Claro, vale, pero como es T y T.class no se puede hacer 00:16:29
¿Vale? Porque T es genérico 00:16:35
Entonces T.class no se puede hacer 00:16:37
Pues si lo pasamos por parámetro 00:16:41
Diciéndole, oye, esto cuando esté instanciado 00:16:42
Va a ser un objeto de esta clase 00:16:47
Que aquí sí que podemos poner el T 00:16:50
Porque aquí no estamos todavía instanciando 00:16:52
Estamos declarando 00:16:54
Sin embargo, ahí abajo 00:16:55
Sí que ya es el objeto creado 00:16:57
Luego aquí no se puede poner t.class 00:17:00
Porque t.class 00:17:02
No es nada 00:17:07
¿Vale? 00:17:08
Entonces, aquí ponemos 00:17:10
Esto, ¿vale? 00:17:13
Entonces, entonces 00:17:15
Perdona, ese que es solo el tener 00:17:15
No hace falta el commit 00:17:18
No, aquí no 00:17:20
¿Vale? Entonces 00:17:22
Como le pasamos estos dos 00:17:23
Por parámetro al dao 00:17:26
El contexto de persistencia 00:17:28
Y el tipo 00:17:31
Pues hacíamos un constructor así 00:17:34
¿Vale? 00:17:36
Le pasábamos el contexto de persistencia 00:17:38
Porque claro, podríamos hacer 00:17:41
Que se creara el contexto de persistencia 00:17:43
Cada vez 00:17:45
Pero entonces le complicamos 00:17:45
Al servicio, manejar transacciones 00:17:48
Y todo eso 00:17:50
Es que aunque los creara 00:17:51
Luego aquí se va a crear otro 00:17:57
Entonces no podemos hacerlo tan atómico 00:17:58
¿Vale? Entonces 00:18:01
Y además teníamos 00:18:02
El problema del lazy y el eager 00:18:05
Que no sé si os acordáis, pero bueno, ahora volverá a salir 00:18:07
Vale 00:18:09
Pues nada, remove lo mismo 00:18:10
Y actualizar 00:18:12
En realidad actualizar 00:18:15
Aquí 00:18:17
No habría nada que hacer 00:18:17
Porque cuando se cambie el objeto 00:18:21
En el servicio 00:18:23
¿Vale? 00:18:24
Pero bueno, este es el método 00:18:26
Que se suele poner 00:18:27
Para forzar una actualización 00:18:30
Entonces lo vais a encontrar mucho 00:18:32
Aunque en realidad 00:18:33
No es la base de datos en un NET 00:18:35
Aunque no le de un COM 00:18:37
No, no, no 00:18:39
Tienes que hacer el COM 00:18:41
Pero es el método que se asocia 00:18:42
Normalmente a actualizar 00:18:45
Cuando tienes que, pues lo sacas 00:18:47
A otro método aparte o lo que sea 00:18:49
Más que nada porque es que si no el UPDATE se quedaría vacío 00:18:51
No sería necesario 00:18:53
Porque tú 00:18:54
Desde la aplicación 00:18:55
Si tú cambias el objeto cuando ya se haga commit 00:18:58
¿Vale? 00:19:01
Bueno, entonces 00:19:03
Aquí, realmente aquí 00:19:04
Deberíais haberme dicho 00:19:06
Esto que hay aquí es contradictorio 00:19:07
Con lo que has dicho antes 00:19:10
Claro, hay una cosa aquí horrorosamente contradictoria 00:19:11
En este código 00:19:14
En serio 00:19:15
A ver, lo que es contradictorio 00:19:17
Es que estoy diciendo todo el rato 00:19:24
que démosle al servicio 00:19:26
la potestad de gestionar 00:19:28
qué operaciones se hacen en transacción 00:19:30
y cuáles no 00:19:32
y yo he clavado aquí 00:19:33
entonces 00:19:36
es imposible que luego el servicio 00:19:37
pueda meter 00:19:40
este create, lo pueda meter 00:19:41
en una transacción para forzar a que 00:19:44
solo se haga si se hace otra cosa después 00:19:46
es imposible porque lo acabo de meter en una transacción 00:19:48
aquí, con lo cual create se va a hacer 00:19:50
sí o sí, independientemente 00:19:52
de si se hace en el resto de operaciones del servicio 00:19:54
es que no hay 00:19:56
transacciones dentro de transacciones no existen 00:19:59
entonces, conclusión 00:20:02
que lo primero que vamos a hacer 00:20:04
que feo esto, quitarlo 00:20:05
pero lo pongo 00:20:08
y lo dejo en comentarios 00:20:10
para que quede claro 00:20:11
entonces 00:20:14
aquí no ponemos 00:20:15
la transacción 00:20:23
porque 00:20:26
Es el servicio 00:20:29
El que decide que se mete en transacción 00:20:31
Y que no 00:20:34
No es la idea 00:20:34
No es la idea 00:20:40
Vale, pero esto 00:20:42
Lleva una tilde 00:20:52
Vale, pues esto mismo que he quitado 00:20:53
Aquí, por tanto 00:21:00
Lo quito de aquí 00:21:01
También, y lo quito 00:21:03
De aquí también, vale 00:21:07
Y el dado se queda así, tan ancho 00:21:13
Vale, ahora ya vamos a hacer 00:21:15
el servicio, vale 00:21:17
a ver 00:21:19
no, este ya está 00:21:19
bueno, luego, pero eso ya es servicio 00:21:22
vale 00:21:27
entonces, vale, vamos a ver 00:21:28
pues venga, un paquete 00:21:31
¿qué? 00:21:33
¿qué? 00:21:33
todo lo que veas sencillo 00:21:36
preocúpate, porque 00:21:38
que no, hombre, es sencillo porque no 00:21:40
no, no, no 00:21:43
en absoluto 00:21:45
A ver, vale, pues este ya en lugar de hacer una clase servicio por empleado, departamento, 00:21:49
pues una clase servicio para la aplicación, con los casos de uso que se hayan derivado del análisis de la aplicación, ¿vale? 00:22:15
Y ahora aquí, pues por ejemplo 00:22:24
A ver, que voy a mirar aquí para no perderme 00:22:30
Lo vamos a hacer 00:22:33
Departamento por ID 00:22:39
Vale, pues entonces 00:22:41
Recuperar un departamento 00:22:46
Eso es lo más natural del mundo 00:22:50
Que quiera hacer un servicio 00:22:51
Pues venga, podríamos hacer 00:22:53
Departamento 00:22:55
Y ahora aquí 00:22:56
Aquí podemos ponerlo 00:22:58
Lo de inglés 00:23:03
Esto es que ya es mucho más abierto 00:23:06
Esto ya es la aplicación 00:23:08
Entonces aquí 00:23:09
Depende 00:23:11
Porque el DAO está como más estandarizado 00:23:13
Más estandarizado 00:23:17
Y para que todos lo entendamos 00:23:18
Pues lo mejor es que esté en inglés 00:23:20
Porque así lo entendemos todos 00:23:22
Pero el servicio ya es propio de la aplicación 00:23:23
No es tan estandarizado 00:23:26
Entonces aquí uno lo pone como le salga 00:23:27
De cualquier lado que tenga 00:23:30
Recuperar, hemos dicho, departamento 00:23:33
Por id, porque aquí vamos a ver 00:23:37
Lo de lazy y el eager 00:23:38
Y la madre que lo trajo 00:23:40
Vale 00:23:42
Sí, porque departamento 00:23:59
Su clave es íntegro 00:24:02
Vale, entonces aquí lo tenemos tan fácil 00:24:03
Como, ¿qué daos necesitamos? 00:24:06
El del departamento 00:24:09
Porque es un get, punto pelota 00:24:10
Pues entonces 00:24:12
Nos vamos a hacer una implementación 00:24:13
Dao 00:24:16
de que 00:24:17
de departamento 00:24:21
ínteger 00:24:24
este es el dado que vamos a necesitar 00:24:26
para este método 00:24:29
y este va a ser 00:24:30
new 00:24:33
y ahora aquí 00:24:34
hay que pasarle los parámetros 00:24:40
que necesita el dado 00:24:46
¿qué parámetros necesita el dado? 00:24:48
necesita la clase de la que 00:24:51
estamos hablando 00:24:52
perdón, el constructor 00:24:53
el constructor necesita 00:24:56
el objeto 00:24:58
de class 00:25:01
departamento y el entity 00:25:02
manager, entonces este lo tenemos 00:25:04
facilísimo, porque es 00:25:06
departamento 00:25:08
punto class, este lo tenemos 00:25:10
muy fácil, y el otro 00:25:12
es el entity manager 00:25:15
entonces 00:25:17
podríamos crearlo aquí, entity manager 00:25:18
y ya está, pero vamos a sacarlo 00:25:20
a un método, porque es lo típico 00:25:22
tener el, tanto cuando usas 00:25:24
el hibernate puro como el JPA 00:25:26
un método que te devuelve el entity manager 00:25:28
y tú lo llamas y ya está 00:25:30
entonces, eso 00:25:31
aquí 00:25:34
a ver, aquí hay muy pocos paquetes 00:25:37
lo normal cuando tú abres una aplicación 00:25:49
es ver 00:25:51
30 paquetes 00:25:52
para luego 00:25:55
esa aplicación igual hace 5 cosas 00:25:57
pero tiene 30 paquetes 00:25:59
para que sea escalable 00:26:01
perdón, la he llamado 00:26:03
como me ha... 00:26:05
perdón 00:26:07
¿eh? 00:26:08
¿por pijería? 00:26:09
efectivamente 00:26:17
una aplicación organizada 00:26:18
en muchos paquetes distintos 00:26:19
aunque cada paquete tenga nada 00:26:21
si efectivamente la tienes que escalar o lo que es lo mismo 00:26:23
la tienes que ampliar con alguna funcionalidad 00:26:25
es infinitamente más fácil 00:26:27
ampliarlo con una funcionalidad y que siga 00:26:29
siendo clara, porque cualquier aplicación 00:26:31
es escalable, es decir, cualquier aplicación 00:26:34
es ampliable, pero el problema es que 00:26:35
si la aplicación no está bien diseñada 00:26:37
desde el principio con todos los paquetitos por separado 00:26:39
según esa aplicación va recibiendo 00:26:41
los parches, cada vez se va 00:26:43
convirtiendo en un 00:26:45
magma horroroso 00:26:47
entonces si está muy bien diseñada desde el principio 00:26:49
cualquier ampliación la sigue dejando clarita 00:26:51
clarita, clarita, los paquetes pueden ir engordando 00:26:53
pero va quedando todo claro 00:26:56
Entonces tendrá un tiempo de vida mucho más largo 00:26:57
Porque cuando tomas tú la decisión 00:26:59
De esta aplicación a la basura, que no puedo más con ella 00:27:01
Pues si la tienes organizada desde el principio 00:27:03
Tomas esa decisión mucho más tarde 00:27:05
Vale 00:27:07
Entonces esto a cuento de que venía 00:27:09
De que estábamos refactorizando esto 00:27:11
Que lo había llamado mal 00:27:13
Bueno porque 00:27:14
Yo que sé, dime otro nombre 00:27:17
¿Cómo quieres que la llame? 00:27:20
Es para el entity manager 00:27:22
¿Eh? 00:27:24
Vale 00:27:27
Venga, Persistence 00:27:27
Muy listos sois 00:27:32
Está muy bien elegido 00:27:33
Mejor que, vale, porque conexión 00:27:34
Hace referencia más al barro 00:27:36
Y aquí no nos estamos manchando 00:27:39
Muy bien, vale, muy bien 00:27:41
¿Veis como sois muy espabilados 00:27:43
Y muy listos? 00:27:45
Vale, entonces estas clases 00:27:47
Estas clases se suelen llamar 00:27:49
Con el apellido útil 00:27:51
De hecho está el famoso hibernate útil 00:27:53
Si ponéis en internet 00:27:56
De hibernate útil os salen mil pipipi. 00:27:57
Entonces, esta vamos a llamarla JPA útil 00:28:00
porque estamos sacando el contexto de persistencia de JPA, 00:28:02
no del hibernate directamente. 00:28:06
Entonces, ¿yo qué estaba haciendo aquí? 00:28:08
Una nueva clase JPA útil. 00:28:10
Entonces, aquí vamos a dar un método, ¿vale? 00:28:18
Click static que me devuelva el entity manager. 00:28:28
Y entonces 00:28:31
Public static entity manager 00:28:37
Entity manager 00:28:43
Vale 00:28:44
Y ahora, este método 00:28:46
Esto se hacía 00:28:48
Lo tenemos aquí en este main 00:28:50
Lo tenéis en el main de la propia aplicación 00:28:52
Esto 00:28:54
Se hacía así 00:28:55
Y ya está 00:28:57
Vale 00:28:59
Y aquí tendríamos que retornar 00:29:02
El m 00:29:10
Esto no es un singleton 00:29:11
Y no es un singleton 00:29:17
Ni queremos que lo sea 00:29:19
Porque el EM 00:29:20
Se instancia uno nuevo cada vez 00:29:23
Que luego cerraremos 00:29:25
¿Vale? 00:29:26
No queremos un entity manager vivo 00:29:28
Para toda la aplicación para siempre 00:29:30
El mismo objeto, no 00:29:32
Porque eso podría tener muchos efectos colaterales secundarios 00:29:34
Cada vez que el servicio 00:29:37
Quiera un contexto de persistencia 00:29:39
Para su caso de uso 00:29:40
Su entity manager que luego cierra 00:29:42
luego tiene quizá más sentido 00:29:44
de nuevo no es una regla 00:29:47
estricta, tiene quizá más sentido 00:29:48
un contexto de persistencia por caso 00:29:51
de uso, con lo cual el caso de uso 00:29:53
lo llama y luego ya lo va a cerrar 00:29:55
¿vale? con el em close 00:29:57
entonces esto no es un singleton 00:29:59
em no queremos que haya una única 00:30:01
instancia, pero a lo mejor lo que 00:30:03
si podemos hacer para aprovechar un poco 00:30:05
las cosas, el factory 00:30:07
ese si que podría ser uno y único 00:30:09
por aplicación 00:30:11
El factory es el creador de EntityManager 00:30:13
Entonces, ¿para qué obligar a 00:30:15
Instanciar uno? 00:30:17
Claro, instanciarlo 00:30:20
Para que luego 00:30:22
Como variable local se pierda el recolector de basura 00:30:22
Pues los va periódicamente 00:30:26
Pues para qué, ¿no? 00:30:27
Entonces vamos a ponerlo aquí ya 00:30:28
Este sí que sí 00:30:30
Como este factory 00:30:31
Es static y ahora ya 00:30:45
Este se limita 00:30:47
A devolver esto 00:30:51
Entonces vamos a poner esto aquí 00:30:52
vale, entonces este 00:30:54
sí que va a ser ya un único 00:31:07
en toda la aplicación y bien 00:31:09
y ya está 00:31:10
y te devuelve uno cada vez que el caso de uso 00:31:12
lo necesite 00:31:15
vale 00:31:16
bueno, una posibilidad que tiene sentido 00:31:18
vale, ahora ya 00:31:20
en el servicio nos vamos 00:31:23
aquí otra vez 00:31:25
y ahora ya este 00:31:26
el caso de uso, este de aquí 00:31:28
sí que saca el 00:31:30
LM y se lo pasa a este 00:31:33
JPA 00:31:36
Bueno, como luego lo tenemos que cerrar 00:31:38
Necesitamos una referencia para él 00:31:41
Porque luego hay que hacerle el en.close 00:31:43
Entonces, vamos 00:31:45
Tenemos que hacerlo aquí fuera 00:31:47
Para luego poder cerrarlo 00:31:48
Y ahora ya a este constructor se lo pasamos 00:32:01
volver a donde 00:32:05
al útil este 00:32:10
es simplemente 00:32:12
para crear un entity manager 00:32:14
vale y ahora ya 00:32:16
recuperar departamento 00:32:21
por id pues el dao me puede 00:32:23
ayudar 00:32:25
ah bueno tenemos que abrir la transacción 00:32:25
vale ahora nosotros aquí decidimos 00:32:28
si esto va en transacción o no 00:32:31
como implica modificar va en transacción 00:32:32
y en este caso solo tiene 00:32:34
un método pero bueno 00:32:36
Aún así es obligatorio 00:32:38
Es obligatorio porque modifica la base de datos 00:32:40
Y JPA funciona así, esencialmente 00:32:53
Vale 00:32:55
Entonces, getTransaction 00:32:57
Ahora ya sí 00:33:00
Dao.find 00:33:01
find 00:33:04
departamento 00:33:09
de igual a 00:33:17
dado punto find nos llamaba get 00:33:20
¿verdad? get y de 00:33:23
y ahora podríamos devolver de 00:33:25
y ya está, ya estaría hasta caso de uso 00:33:29
pero a ver, tampoco pasa nada porque 00:33:33
perdón, sí, sí, sí 00:33:36
Sí. Está muy bien 00:33:39
que estéis despiertos. 00:33:41
Sí, porque estoy... ¡Ay, no, jolines! 00:33:45
Que estoy recuperando. No me hace falta. Es que estoy 00:33:47
obsesionada con que estaba insertando. 00:33:49
No me hace falta. 00:33:51
Mira, estabas dormido hace un rato, pero te has despertado 00:33:53
muy rápido. 00:33:55
Pues no te he entendido. 00:34:00
Vale, creía que te referías a que como hay 00:34:05
solo una sentencia, aunque fuera de insertar 00:34:07
hacer una transacción para 00:34:09
una sentencia, pero creía que te 00:34:11
referías a eso. Vale, pues 00:34:13
efectivamente aquí no haría 00:34:15
falta hacer esto en transacción, ¿vale? 00:34:17
Entonces ahora ya sí. 00:34:20
Vale, lo que pasa es que bueno 00:34:21
también lo que podemos es acostumbrarnos 00:34:23
en cuanto a la lista esa enorme 00:34:25
de buenas prácticas 00:34:26
una buena práctica de programación 00:34:28
sería no 00:34:31
pongas en peligro a los demás 00:34:32
aquí que puede ocurrir 00:34:36
que esto me puede devolver un null 00:34:38
perfectamente, porque si el find 00:34:40
dentro del 00:34:42
DAO, el find 00:34:45
como funciona, pues el find que está aquí 00:34:46
claro 00:34:49
este find 00:34:50
si miramos en la documentación 00:34:52
de find, pues te devuelve 00:34:55
null, lo dirá ahí 00:34:57
abajo 00:34:58
ves, or null, aquí 00:34:59
entonces uno mira estas cosas, uy cuidado 00:35:06
porque podría ser que no devolviera null 00:35:09
Que devolvía yo que sé 00:35:10
Un departamento vacío, que sería muy raro 00:35:11
Pero bueno, te devuelve null 00:35:14
Entonces, no pongamos en peligro a los demás 00:35:16
Dándoles un null 00:35:19
Porque ya sabemos que es un null pointer exception 00:35:20
Entonces, ¿por qué no 00:35:23
Se lo envolvemos en un optional? 00:35:25
Vamos a envolvérselo en un optional 00:35:28
¿Vale? 00:35:31
Envolvérselo en un optional 00:35:34
No, no, no 00:35:35
Esto, ¿vale? 00:35:41
Se lo envolvemos en un optional 00:35:42
Que 00:35:43
Ya está 00:35:45
Off 00:35:47
La diferencia entre los dos 00:35:48
Vale, un optional con el valor 00:35:51
Si no es 00:35:57
Y si no, un optional vacío 00:36:00
Si es null 00:36:02
Y la diferencia con el off de arriba 00:36:02
Vale 00:36:04
El de arriba 00:36:09
No, si null 00:36:10
Si el valor que metes 00:36:12
Es null 00:36:13
te da un null pointer exception, entonces no gusta 00:36:15
este más, no, porque el de abajo 00:36:17
no te da un null pointer exception, te devuelve 00:36:19
un, ah, sí 00:36:21
no, simplemente que te frena 00:36:22
ahí ya, te frena ahí ya 00:36:25
al que tú puedas devolver un null 00:36:27
te pone ahí un corte antes 00:36:28
venga, a mí me ha gustado este 00:36:31
si vosotros queréis hacerlo de otra manera 00:36:33
vale, entonces aquí 00:36:35
ponemos de, y ya está 00:36:37
con lo cual ahora aquí devolvemos 00:36:39
un optional 00:36:41
de departamento 00:36:42
vale 00:36:46
y así hombre, casi que queda más bonito 00:36:49
porque este método 00:36:52
no va a devolver null nunca jamás 00:36:54
de los jamases 00:36:56
entonces un null pointer exception no hay 00:36:57
entonces el de arte 00:36:59
ya, pero la persona que lo saca 00:37:00
para empezar ya tiene que hacer 00:37:06
un get, con lo cual ya 00:37:08
tiene que por código 00:37:10
operar para sacarlo de ahí 00:37:12
y ya a través de su get 00:37:14
puede ya decidir qué hace si es null 00:37:15
o sea, es una protección, está claro 00:37:17
un null no devuelves 00:37:19
el que te llama jamás va a tener un null 00:37:21
pues eso ya es algo 00:37:24
es decir, le das 00:37:25
no le das la bomba 00:37:27
tú le das la bomba en una caja 00:37:30
entonces 00:37:32
la bomba no le va a explotar jamás 00:37:33
a menos que él diga, mira, la caja 00:37:35
la basura y cojo la bomba con la mano 00:37:37
pero mi línea de pensamiento es la misma 00:37:39
o sea, tú le podías dar el null ahí 00:37:42
y él también sabe que puede requerir una bomba 00:37:43
lo que pasa es que 00:37:46
pero es más fácil 00:37:46
cometer errores, porque tú haces un 00:37:50
recuperar departamento por ID 00:37:52
punto no sé cuántos 00:37:54
recuperar departamento por ID, punto no sé cuántos 00:37:56
¿vale? y le vas a ir 00:37:58
a un puente de excepción 00:38:00
si tú lo haces así, él cuando escriba 00:38:01
recuperar departamento por ID, punto, va a decir 00:38:04
no, no puedes hacer eso, y ya por código 00:38:05
te va a obligar a sacarlo 00:38:07
antes de la caja, entonces tú ya 00:38:10
estás de alguna manera como más avisado, si no 00:38:12
tú pones regularmente el punto, no sé cuántos 00:38:14
y ahí te cajas el muy fuerte de esencia 00:38:16
hombre, más rápido 00:38:18
o que si te dan la caja 00:38:22
con la bomba, la caja 00:38:38
te la puedes quedar ahí tranquila 00:38:40
no, vamos a ver, el ejemplo 00:38:42
te dan una bomba 00:38:44
y cuando tú 00:38:46
no, a ver 00:38:46
el ejemplo, lo que queda 00:38:49
más claro es, ahí te dan una 00:38:52
bomba, tú la coges con la mano 00:38:54
y tal cual la coges con la mano 00:38:56
te explota porque es manosensible 00:38:57
con lo cual te dan con la bomba y tú la coges 00:38:59
con la mano, te ha explotado 00:39:02
pero si te dan una bomba en una caja, tú coges 00:39:03
la caja con la mano y no explota 00:39:05
y luego tú ya 00:39:08
y luego tú ya si eres tonto 00:39:09
pues dices, y ahora voy a meter la mano 00:39:11
y la cojo, entonces te explota 00:39:14
pero al menos 00:39:15
hombre, pero con el 00:39:16
opcional tú puedes ya, si es nula 00:39:22
hacer lo que sea 00:39:24
pero puedes abrir la tapa de arriba y cogerla con la caja 00:39:25
y ya ver lo que 00:39:28
bueno 00:39:28
pero a ver, yo creo que sí que 00:39:32
es, o sea, sí que se ve 00:39:35
que es más fácil a nivel de código 00:39:38
generar null pointer exception 00:39:40
sino porque con el optional 00:39:42
ya le impides usar el método tal cual 00:39:44
se lo impides usar 00:39:46
claro, pues es suficiente 00:39:47
se lo impides usar 00:39:50
le obligas por lo menos a mirar dentro 00:39:51
pero a ver, que se supone 00:39:54
que estamos hablando de programadores expertos 00:39:58
como vosotros 00:40:00
yo quiero que me exploten la cara 00:40:01
bueno, dígame 00:40:04
El optional lo que te da 00:40:08
es la posibilidad de envolver 00:40:18
un objeto 00:40:20
en otro. 00:40:21
Entonces, la ventaja 00:40:24
del optional es que también puedes envolver 00:40:26
null. Entonces, el optional 00:40:28
es un objeto. Es decir, esto que yo 00:40:30
devuelvo, esto es un objeto. 00:40:32
Y ese objeto 00:40:34
nunca va a ser null. 00:40:35
Pero lo que tiene dentro podría serlo. 00:40:38
Entonces, aquí tengo dos posibilidades. 00:40:40
Devolver el de sin más. 00:40:42
Entonces, puedo devolver null. 00:40:44
¿Vale? 00:40:46
Ya está. 00:40:47
¿Qué pasa si devuelvo null? 00:40:47
Que si alguien llama a recuperar departamento id 1 00:40:48
y tal cual escribe todo seguido, punto, 00:40:51
get no sé cuántos, 00:40:55
si ese objeto es null, 00:40:56
null pointer es de. 00:40:57
Vale. 00:40:59
Posibilidad b. 00:41:00
Creo otro objeto, 00:41:02
que es un objeto de tipo optional departamento. 00:41:03
¿Pensado para qué? 00:41:05
para meter objetos departamento dentro 00:41:06
pues eso es lo que estoy haciendo 00:41:08
con esto, crear un objeto 00:41:10
optional en el que estoy guardando 00:41:12
mi D, y ese es el que devuelvo 00:41:14
ese nunca jamás va a ser neutral 00:41:16
nunca, entonces 00:41:18
vale, sí 00:41:20
pero, ¿cuál es la ventaja 00:41:24
más inmediata? entonces, yo he devuelto un 00:41:26
optional, entonces al que me escribe el código por 00:41:28
arriba, cuando 00:41:30
esté escribiendo 00:41:32
recuperar 00:41:33
departamento 00:41:36
id1 00:41:39
y haga, quiera poner 00:41:41
aquí, .getNombre 00:41:43
pues no puede poner 00:41:46
getNombre, porque este es un optional 00:41:47
luego no admite el método getNombre 00:41:49
entonces él ya ve, ah, tengo que sacarlo 00:41:51
primero de la caja, entonces sí, puede ser 00:41:53
bestia por segunda vez 00:41:55
sacarlo de la caja, get 00:41:56
y luego aliviar el getOf 00:41:59
pero hombre, la idea es ir poniendo 00:42:01
de alguna manera, pues 00:42:03
avisos, protecciones 00:42:05
para eso son las excepciones 00:42:07
cuando algo lanza una excepción, el otro puede decir 00:42:08
a mí me la suda 00:42:11
o puede decir, la capturo 00:42:12
para eso pones un throw en el otro método 00:42:14
ya ves que no te duele 00:42:18
bueno, vale, pones un throw pero estás propagando la 00:42:20
bueno 00:42:24
no lo estás propagando, lo estás entregando 00:42:25
en un objeto 00:42:31
que nunca te va a generar un pointer exception 00:42:32
si luego tú perseveras 00:42:34
en que no, que yo quiero mi null pointer 00:42:36
excepción, pues ya, chico, tú verás. 00:42:38
¿Vale? 00:42:41
Pero, hombre. 00:42:42
Bueno, venga. 00:42:50
Déjala. 00:42:53
A ver, tu problema no va a ser en ningún caso 00:43:00
aunque devuelvas tu null, tampoco lo va a ser. 00:43:02
Pero, bueno. 00:43:05
Vale, pues ya está. Entonces, vamos ahora a nuestro main para probar esto. 00:43:06
Venga. 00:43:14
¿Alguien necesita una paradinha? 00:43:16
De tres mesecitos o por ahí. 00:43:20
William, ¿es una pregunta o necesitas una parada? 00:43:23
Venga, pon una parada rápida. 00:43:26
Materias:
Programación
Niveles educativos:
▼ Mostrar / ocultar niveles
  • Formación Profesional
    • Ciclo formativo de grado superior
      • Segundo Curso
Subido por:
Raquel G.
Licencia:
Todos los derechos reservados
Visualizaciones:
1
Fecha:
27 de enero de 2026 - 12:50
Visibilidad:
Clave
Centro:
IES ROSA CHACEL
Duración:
43′ 28″
Relación de aspecto:
1.78:1
Resolución:
1920x1080 píxeles
Tamaño:
190.33 MBytes

Del mismo autor…

Ver más del mismo autor


EducaMadrid, Plataforma Educativa de la Comunidad de Madrid

Plataforma Educativa EducaMadrid