20260120 JPA_5 - Contenido educativo
Ajuste de pantallaEl ajuste de pantalla se aprecia al ver el vídeo en pantalla completa. Elige la presentación que más te guste:
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
de
00:04:22
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
00:17:30
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
.
00:31:51
.
00:31:55
.
00:31:56
M
00:31:59
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
y
00:34:35
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
ya
00:37:04
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
y
00:42:17
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