Saltar navegación

20251209 BDR-Servlet_2 - 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 9 de diciembre de 2025 por Raquel G.

1 visualizaciones

Descargar la transcripción

Porque no estará el serlet correctamente configurado. 00:00:00
Si tú tienes la anotación web serlet bien puesta, 00:00:03
tiene que llegar a ese serlet. 00:00:06
Otra cosa es que ese serlet no haga nada, como es mi caso. 00:00:08
No hace nada. 00:00:10
¿Vale? 00:00:12
Vale. 00:00:20
A ver, como lo tenéis hecho, vamos, 00:00:21
el serlet entero, vamos a completarlo. 00:00:26
Que no os va funcionando a algunos. 00:00:30
ya lo arreglaremos, pero es que no quiero que nos paremos 00:00:32
mucho porque si no lo completamos 00:00:33
todo hoy, entonces vamos a 00:00:35
eternizarnos, que es lo que queremos evitar. 00:00:37
Venga, vale, pues ahora 00:00:40
vamos a completar el servlet. 00:00:42
Ahora ya el servlet 00:00:44
instanciará el servicio y todo eso. 00:00:45
Entonces ahora, tened abierto, porque vamos a ir 00:00:47
copiando y pegando de ahí, 00:00:49
tened abierto el servlet que os he pasado. 00:00:51
¿Qué he metido el qué? 00:00:59
Bueno, hijo, a ver 00:01:00
Espera 00:01:02
A ver, esto lo puedes dejar escrito así 00:01:05
No pasa nada, vamos a irlo completando 00:01:06
Copiando y pegando con lo que hay ahí 00:01:08
Para ir entendiendo lo que hace ese serlet 00:01:10
Entonces, ese serlet es 00:01:12
Debería ser 00:01:14
Este de aquí 00:01:17
Vale, entonces lo primero que os he incluido aquí 00:01:19
Es lo que os he dicho antes 00:01:24
Un serlet por acción, no 00:01:25
Uno por entidad y dentro del distinguir 00:01:27
Uno por entidad 00:01:30
entonces nos vamos a nuestro 00:01:31
serlet 00:01:36
esto lo comentamos ahora 00:01:36
esta es la acción 00:01:39
que la he metido en una acción para comparar 00:01:43
pero da igual, he hecho lo mismo 00:01:45
vale, entonces ahora 00:01:47
si la acción es listar 00:01:49
¿qué hay que hacer? pues llamará al método 00:01:51
getVentas del servicio 00:01:53
y ya está, y ahora construir la salida 00:01:55
y nada más, pero claro 00:01:57
el servicio tiene que estar instanciado 00:01:59
en algún sitio, bueno pues 00:02:01
el servicio, su sitio para ponerle 00:02:03
es que sea una propiedad 00:02:05
del serlet 00:02:08
que es una propiedad del serlet, pues venga 00:02:09
copiad y pegad, esta de aquí 00:02:11
esto de aquí 00:02:13
lo copiáis y pegáis 00:02:14
y lo ponéis en vuestro 00:02:17
serlet 00:02:20
como propiedad del serlet 00:02:21
vale 00:02:24
ala, este es nuestro 00:02:26
objeto-servicio, que es imprescindible 00:02:28
que exista 00:02:30
para que 00:02:31
el método 00:02:33
do-get y do-post puedan hacer 00:02:36
acciones. ¿Vale? Esto es que se está 00:02:38
recargando todo el rato, que es un coñazo. 00:02:40
¿Vale? Entonces, esto 00:02:43
lo que nosotros hacemos a mano, es lo 00:02:44
que ese maravilloso Spring que adoráis 00:02:46
se encarga de hacer, crear los 00:02:48
objetos y meterlos para adentro. Ya está. 00:02:50
Mete los objetos para adentro. 00:02:53
O sea, no hace nada más que 00:02:55
llamar dentro a estas cositas 00:02:56
bueno, pues ahora ya 00:02:58
¿qué queremos hacer si la acción 00:03:01
es lista? pues 00:03:03
si queréis 00:03:05
copiar y pegar 00:03:07
esto que hay dentro de if action 00:03:08
y bueno, primero 00:03:11
copiar esta línea del print writer 00:03:12
que está en el serlet que os he 00:03:17
pasado, porque aquí 00:03:19
esta es 00:03:21
la tubería de salida por la que 00:03:23
el serlet va a mandar el resultado 00:03:25
el serlet una vez que obtenga su resultado 00:03:26
lo va a mandar por su tubería 00:03:30
de salida que es esta 00:03:32
que vamos a sacarla del objeto response 00:03:33
pues vamos a crear primero esa tubería de salida 00:03:35
vamos a sacarla de ahí 00:03:38
pues venga la tubería de salida la copiáis 00:03:39
y la ponéis en vuestro serlet 00:03:42
ala aquí 00:03:44
esa es nuestra tubería de salida 00:03:45
y ahora que tenemos que hacer 00:03:50
pues llamar al servicio para sacar nuestra lista de ventas 00:03:52
pues venga 00:03:55
que es lo que está aquí 00:03:57
Llegamos al servicio 00:03:58
Para sacar nuestra lista de ventas 00:04:00
Y ahora ya construimos la salida 00:04:02
Entonces copiáis esto que está aquí dentro 00:04:04
De este if 00:04:06
Pues lo copiáis aquí 00:04:07
Vale, entonces 00:04:14
El método getVentas del servicio 00:04:26
Que llamará a su vez al del dao 00:04:29
El que yo os pedí que hicierais 00:04:34
¿Verdad? 00:04:36
Pues vamos a hacerlo rápidamente 00:04:38
Este ya sí que lo vamos a hacer nosotros 00:04:40
Entonces vámonos a la clase servicio 00:04:41
vámonos a nuestra clase servicio 00:04:43
que es, a ver si yo no me meto en el proyecto 00:04:46
malo 00:04:49
vámonos a nuestra clase servicio 00:04:50
que teníamos 00:04:53
ya hecho un crear venta y un get venta 00:04:55
pues vamos a hacer 00:04:57
get ventas 00:05:00
un get venta me da una lista de ventas, ¿verdad? 00:05:01
que efectivamente no tiene 00:05:07
parámetros de entrada 00:05:12
porque me da todas las ventas de mi base 00:05:13
de datos, y ahora 00:05:17
¿Qué me devolverá este? 00:05:18
Pues me devolverá lo que haga el DAO 00:05:20
En su método 00:05:23
Que se supone que tenéis que completar 00:05:25
FindAll 00:05:26
Entonces habrá que hacer 00:05:27
De la implementación correspondiente 00:05:32
Que estamos usando 00:05:35
Habrá que hacer el método FindAll 00:05:36
Para poder hacer GetVentas 00:05:38
O sea GetVentas y aquí ya lo tenemos 00:05:41
¿Vale? 00:05:42
Aquí 00:05:43
El rojito 00:05:44
Este no sé dónde 00:05:47
pero da igual, vale 00:05:48
bueno, el ventaservice ya está 00:05:49
ahora, vámonos al 00:05:52
dao implementación para hacer ese método 00:05:54
vale 00:05:56
entonces, find all 00:06:02
lo tenéis en blanco 00:06:06
¿verdad? pues 00:06:08
fuera, todo fuera 00:06:11
todo fuera 00:06:14
vale, esto es lo que se supone, vosotros teníais que 00:06:15
haber hecho ahora, igual que este de aquí 00:06:18
pero 00:06:20
este ya sí que es parte de acceso a datos pura y dura 00:06:21
igual que hicisteis 00:06:24
una sentencia select pero por id 00:06:25
hará un select enterito 00:06:27
un select para todos 00:06:29
pues venga, lo que pasa es que ahora ya 00:06:31
sí que en lugar del objeto statement 00:06:33
vamos a usar el prepare 00:06:35
de statement que no permite 00:06:37
la inyección SQL porque este sí que 00:06:39
lo permite, es una chapuza 00:06:41
metéis ahí un drug database, lo mete 00:06:43
alguien en su formulario bien formado 00:06:45
con un or true o lo que 00:06:47
sea y ahí pasa cualquier cosa 00:06:50
pues venga, vamos a hacer nuestro 00:06:51
find all, ala 00:06:53
nuestro objeto resultante va a ser una lista de ventas que es el que vamos a 00:06:55
devolver inicialmente vacío inicialmente vacío y ahora ya vamos a hacer la 00:07:00
sentencia la sentencia ahora ya no va a ser un 00:07:10
statement normal sino un prepare statement de éste 00:07:14
statement y ahora este se crea a partir de la 00:07:21
conexión y la 00:07:25
conexión la sacamos 00:07:27
ya la tenemos 00:07:29
la conexión es la propiedad 00:07:31
de nuestro da implementación 00:07:33
pues con el método 00:07:36
prepareStatement 00:07:37
y aquí le damos el string 00:07:38
de la consulta, le damos 00:07:41
el string 00:07:43
pero donde le metemos los parámetros 00:07:44
interrogaciones, lo que pasa es que 00:07:47
en este caso, precisamente en este 00:07:49
no necesitamos interrogar parámetros 00:07:51
Escofron ventas 00:07:53
Vale, entonces 00:07:57
Este es un recurso que luego habrá que cerrar 00:08:01
Entonces este recurso 00:08:03
Vamos a meterlo en un try 00:08:05
Con recursos de estos 00:08:06
Y ahora 00:08:09
Vamos a 00:08:11
¿Vale? 00:08:12
Hombre, ¿cómo querrías hacerlo? 00:08:14
Si no 00:08:21
Ah, pero ¿y cómo lo has hecho? 00:08:21
Bueno, habrás hecho un statement 00:08:26
Normal 00:08:28
bueno ya, vale 00:08:30
pero bueno, estamos mencionando esto 00:08:33
entonces ahora ya 00:08:34
este, esto cuando 00:08:37
se ejecute, se va a ejecutar 00:08:39
con un 00:08:41
ejecutar query, vale 00:08:41
y este que me va a dar un result set 00:08:44
que el result set es la estructura 00:08:47
para 00:08:52
recoger registros de una consulta 00:08:53
también es un recurso que se va a cerrar 00:08:56
entonces podemos ponerlo 00:08:58
dentro del propio 00:09:00
try, entonces dentro 00:09:02
del propio try 00:09:04
podemos poner esto 00:09:05
entonces aquí abro los recursos 00:09:07
y luego 00:09:14
ya los 00:09:16
los uso 00:09:17
entonces 00:09:19
ahí tenemos el 00:09:22
cat 00:09:27
entonces voy a poner para que se quite el error de 00:09:27
compilación de arriba voy a poner ya 00:09:31
desde aquí el retumbentas 00:09:32
vale 00:09:34
bueno pues ahora 00:09:36
¿Qué vamos a hacer aquí? 00:09:38
Pues vamos a ir recorriendo el result set 00:09:42
Y para cada registro del result set 00:09:44
Instanciamos un objeto 20 y lo mandamos aquí 00:09:46
Y ya está 00:09:49
¿Vale? Pues como recorremos el result set 00:09:49
El result set tiene una sentencia 00:09:52
Un método que es next 00:09:55
Que te va avanzando el registro 00:09:57
Como inicialmente el result set se queda colocado 00:10:00
Antes de la primera lista de registros 00:10:03
pues tenemos que hacer un result set inicial 00:10:08
y el result set 00:10:10
además te devuelve true o false 00:10:12
si hay registro, no hay 00:10:14
entonces la recorrida estándar 00:10:16
de un result set siempre es así 00:10:18
avanzo y si tengo 00:10:20
avanzo y si tengo 00:10:23
avanzo y si tengo, ¿qué hacemos? 00:10:25
vamos a sacar los valores, primero vamos a instanciar 00:10:27
un venta 00:10:29
vacío y ahora le damos los valores 00:10:31
venta.set 00:10:34
pues vamos a sacar del registro 00:10:39
rs el campo 00:10:42
get integer 00:10:44
que se llame 00:10:45
es decir, con esto saco del registro 00:10:48
en el que estoy colocada 00:10:54
el campo que se llame id 00:10:55
ahora, vset 00:10:57
coche 00:11:00
pues con este saco el campo 00:11:02
que se llame, en la tabla como se llamaba 00:11:05
esto 00:11:09
Coche sería, ¿verdad? 00:11:09
Voy a ir abriéndolo por aquí 00:11:13
Vale 00:11:15
Se llamaría este campo, se llamaría coche 00:11:18
Imagino 00:11:21
V.set 00:11:22
Color 00:11:25
Pues saco del registro 00:11:27
El campo 00:11:30
Que se llame color 00:11:31
Y v.set 00:11:33
Nif comprador 00:11:38
Saco del registro 00:11:39
El campo que se llama 00:11:41
Nif barra baja 00:11:44
comprador curraría 00:11:47
si no lo cambiamos cuando toque 00:11:49
y ahora esta venta que acabo 00:11:51
de instanciar la añado a ventas 00:11:59
ala pues ya me he hecho 00:12:01
este método de find all 00:12:07
vale aquí 00:12:09
en particular haber usado la sentencia 00:12:11
pre compilada es un poco 00:12:14
tonto porque es que no 00:12:16
necesito pasarle parámetros 00:12:17
luego en el delete 00:12:19
que es el otro que nos falta por hacer 00:12:21
ahí si tiene más sentido hacer la sentencia 00:12:23
pre compilada porque ahí 00:12:25
Así que vamos a meter el ID. 00:12:27
¿Vale? 00:12:29
Pero bueno. 00:12:30
¿Vale? 00:12:31
Meteremos la venta. 00:12:32
Entonces, estos campos son los campos de la tabla. 00:12:32
Los nombres de los campos de la tabla. 00:12:36
Que están todos en el registro porque yo le he hecho asterisco. 00:12:38
Si mi select hubiera sido solo select coche color, por ejemplo, 00:12:42
pues yo solamente podría acceder a los campos coche color. 00:12:46
¿Vale? 00:12:49
Es decir, el result set tiene los registros del select. 00:12:51
Los que me ha devuelto el select. 00:12:54
con los campos que me haya devuelto 00:12:55
el select, yo los saco 00:12:57
con los métodos correspondientes 00:12:59
cada rs.next me avanza 00:13:00
un registro siguiente 00:13:03
y me devuelve true si ese registro 00:13:04
existe, entonces cuando ya me avance 00:13:07
a uno que no existe y por tanto me devuelva 00:13:09
falso, el while ya deja de entrar 00:13:11
el recorrido estándar 00:13:13
vale, pues 00:13:15
el find all está 00:13:17
dime 00:13:18
cuando preparo la declaración 00:13:21
ahí le meto la query 00:13:24
Utiliza prepárate statement 00:13:26
Justo 00:13:28
Es el statement normal 00:13:29
¿Vale? 00:13:33
Que en el statement normal también puedes ponerle la query 00:13:34
Cuando la creas, ¿eh? 00:13:37
Con el create statement y luego hacer el execute sin parámetros 00:13:38
Tienes las dos posibilidades 00:13:40
En el otro, ¿vale? 00:13:42
A ver, la diferencia 00:13:44
La diferencia es cómo le metes la query 00:13:45
Es que en el otro me da igual que le metas en el execute 00:13:48
Que arriba 00:13:51
La query la metes concatenando 00:13:51
Rompiendo el string y concatenando 00:13:54
con los parámetros, con lo cual te admite inyección 00:13:56
aquí no, aquí lo vamos a 00:13:58
hacer, lo vamos a ver mejor en el delete 00:14:00
aquí no se va a hacer concatenando 00:14:02
aquí se va a hacer poniendo interrogaciones 00:14:03
y luego vas a tener que hacer 00:14:06
luego unas acciones 00:14:08
adicionales 00:14:10
para inyectarlo por fuera 00:14:12
es decir, no los pones directamente en el 00:14:14
sino a través de métodos, los vas a ir metiendo 00:14:16
con lo cual no puedes hacer la inyección 00:14:18
esa es la diferencia 00:14:20
hombre, si le pones en el asterisco 00:14:21
entonces tienes que poner los nombres de los campos 00:14:25
¿qué quieres? 00:14:27
si quieres todos asterisco 00:14:29
y si quieres unos en concreto 00:14:32
los nombres de los campos separados por comas 00:14:34
vale, pues entonces 00:14:36
el find all está 00:14:38
el ventaservice entonces ya está 00:14:39
find all 00:14:42
get ventas 00:14:44
y ahora ya mi servlet 00:14:45
¿qué hace? llama al get ventas 00:14:47
y ya se construye una tabla 00:14:50
y va recorriendo 00:14:53
Todas estas ventas que ha sacando 00:14:55
Y las va metiendo en la tablita 00:14:57
Las va metiendo en la tablita 00:14:58
¿Vale? Entonces, ahora 00:15:00
Me falta, una vez que 00:15:02
He terminado el for, cerrar la tabla 00:15:06
Que eso lo vamos a copiar y pegar 00:15:09
Pues del 00:15:11
Del servlet, del servlet que os he dado 00:15:11
Que lo tendré 00:15:15
Aquí 00:15:16
¿Vale? Es decir 00:15:17
Falta cerrar la tablita 00:15:20
Falta cerrar la tablita después del for 00:15:22
Pues después del for cerramos la tablita 00:15:26
Y esto cierra mi if 00:15:29
De listar 00:15:32
Vale, ahora aquí 00:15:36
Lógicamente habría un 00:15:40
El save 00:15:43
Bueno, voy a poner abajo 00:15:50
Pues que 00:15:57
El save 00:15:58
Recuerdes para mi 00:16:00
Interaction 00:16:04
En el series que os he pasado 00:16:05
Lo tengo guardado en un string antes 00:16:08
Para que quede más bonito 00:16:09
Y no arrastrarlo todo el rato 00:16:10
Si la acción sin embargo 00:16:12
Fuera 00:16:16
Eliminar 00:16:17
Que es la otra 00:16:21
Que vamos a hacer 00:16:23
La otra eliminar 00:16:24
Porque es la que nos faltaba el método 00:16:25
Pues entonces lo que sea 00:16:26
lo que sea 00:16:29
la de eliminar me devolverá 00:16:29
un HTML diciendo si ha eliminado correctamente 00:16:35
o no se ha eliminado 00:16:37
no sé si he entendido tu pregunta 00:16:37
el parámetro, no se envía un parámetro 00:16:40
en el index 00:16:44
sí, lo tendremos que recoger aquí 00:16:44
bueno, a ver 00:16:48
es que la opción de eliminar, quien la va a invocar 00:16:49
es el formulario de eliminar 00:16:52
que todavía no tenemos hecho 00:16:54
claro, el formulario de eliminar 00:16:55
claro, nos falta el formulario de eliminar, que es el otro que os he pasado 00:16:56
vale, por ahora este seble 00:17:00
Se queda aquí vacío 00:17:01
Entonces este serlet es 00:17:02
El serlet para la entidad ventas 00:17:04
Y que recoge todo el club de ventas 00:17:07
¿Vale? 00:17:09
Bueno, pues entonces 00:17:12
Vamos a probar esto de listar ventas 00:17:13
A ver si las lista 00:17:16
Tendréis que lanzar la instancia del 00:17:17
Vale, a ver 00:17:20
Antes de probar nada 00:17:32
Porque no va a funcionar 00:17:34
Nos falta el properties, lógicamente 00:17:35
Vamos a revisar la conexión 00:17:37
Esto ya, ¿vale? 00:17:39
es decir, este 00:17:40
getConnection que me 00:17:43
inyecta aquí el service 00:17:45
que usa el serlet 00:17:47
vamos a revisar conexión 00:17:49
cuidado porque conexión 00:17:51
saca 00:17:55
las propiedades de un fichero de propiedades 00:17:56
que este no lo hemos puesto 00:17:59
entonces nos falta este 00:18:00
¿vale? porque si no nos va a decir 00:18:02
uy, nos saca 00:18:05
es decir, nuestra clase 00:18:06
de conexión que hemos copiado y pegado tranquilamente 00:18:09
sale de un archivo de properties 00:18:11
pues hombre, vamos a meter 00:18:13
ese archivo de properties 00:18:15
entonces como está 00:18:16
dentro del cargador de objetos 00:18:18
sácame como un recurso 00:18:21
como flujo, pues tenemos que ponerlo 00:18:23
en una ruta del path 00:18:25
que por defecto en los proyectos de Maven 00:18:27
es la de resources 00:18:28
pero el Eclipse no te crea 00:18:30
el main java resources 00:18:34
directamente, entonces hay que 00:18:37
crearlo a mano, pero no pasa nada 00:18:39
entonces directamente 00:18:41
la carpeta java 00:18:43
en la carpeta 00:18:44
no en la main 00:18:46
en la carpeta main 00:18:48
creáis una folder resources y ya está 00:18:49
entonces 00:18:52
aquí src 00:18:54
aquí en main, veis donde están abajo 00:18:56
todas las carpetas, aquí en main 00:18:58
creáis una 00:19:00
una folder 00:19:02
exactamente 00:19:04
resources 00:19:05
que esta 00:19:07
por llamarse así, por llamarse 00:19:10
resources y no Pepito Pérez 00:19:12
cuando esto se empaquete 00:19:14
en war, en jar, como sea 00:19:16
esto va a ir a la raíz, al pad 00:19:18
con lo cual se va a encontrar todo lo que hay ahí dentro 00:19:20
pues ahora ya en resources 00:19:23
el mismo base de datos property 00:19:24
del otro proyecto lo metéis ahí 00:19:26
pues del otro proyecto 00:19:28
el mismo base de datos 00:19:32
properties 00:19:34
lo metéis ahí 00:19:35
ala, ahí está el base de datos properties 00:19:39
que tendrá la url 00:19:51
donde está el sistema gestor de base de datos 00:19:53
con la base de datos 00:19:55
con la que vais a trabajar 00:19:57
y el usuario, root 1, 2, 3, 4 00:19:58
muy mal usado, pero bueno 00:20:01
vale 00:20:02
pues en principio 00:20:05
estaría todo, en principio 00:20:08
la conexión debería encontrarla 00:20:10
porque con nuestro objeto conexión 00:20:13
saca los datos del properties 00:20:14
y hace la getConnection 00:20:16
y me la devuelve a través del método 00:20:18
getConnection. El service 00:20:20
me llama al DAO, 00:20:24
el DAO llama a findAll, 00:20:26
el findAll 00:20:28
ahora ya 00:20:29
a través de la conexión saca 00:20:32
la lista de ventas y me la devuelve 00:20:34
y el serlet 00:20:36
que ya no sé ni dónde está 00:20:37
aquí, y el serlet 00:20:40
con esas ventas que me ha sacado 00:20:42
pues las construye. 00:20:44
Muy sencillito, ¿vale? 00:20:46
Vale, pues vamos a 00:20:48
volver a lanzar esta aplicación 00:20:50
con que 00:20:52
reiniciéis el 00:20:56
server, ya se redespliega 00:20:58
sola, si aquí os vais al server 00:21:01
y le decís restart 00:21:03
se redespliega la nueva versión de la aplicación 00:21:04
entonces 00:21:07
restart, ahí está 00:21:09
y ahora me voy a abrir el explorador 00:21:15
y voy a 00:21:17
llamar a mi aplicación 00:21:19
que es esta 00:21:21
este es mi formulario 00:21:21
Ahora 00:21:25
Vamos a llamar 00:21:28
Cualquiera de estos que llamemos 00:21:29
Me va a decir que no encuentra el recurso 00:21:31
Porque cualquiera de estos va a un formulario 00:21:33
Que no tenemos hecho 00:21:36
Entonces cualquiera de estos que llame yo 00:21:36
Va a un formulario que todavía no está 00:21:38
Con lo cual no va a salir 00:21:40
Y este ya sí que va al serle directamente 00:21:41
El de abajo sí 00:21:43
Vamos a ver qué pasa 00:21:44
Toma ya 00:21:46
Vale 00:21:48
Connection is null 00:21:51
¿Vale? 00:21:54
00:21:57
La tengo levantada 00:22:01
Vale, si yo voy hasta arriba 00:22:05
En toda mi traza, no 00:22:06
Este error lo esperaba 00:22:08
Y esto es lo más bonito y maravilloso que os quería explicar hoy 00:22:10
Y me dice 00:22:13
Lo siento 00:22:15
Pero no encuentro el driver 00:22:17
Para esta URL 00:22:18
El properties lo ha leído bien 00:22:20
Porque si no, no habría encontrado esta URL 00:22:23
Que está en el properties 00:22:25
y la cadena de conexión está estupenda 00:22:26
¿cómo que no encuentras 00:22:29
un driver? ¿cómo puede ser 00:22:31
que no lo encuentres? 00:22:33
si tú tienes en tu POM 00:22:35
aquí 00:22:36
tienes aquí en el POM, y no hace falta que entre en el POM 00:22:37
os vais a las dependencias 00:22:41
de Maven y tienes aquí un driver 00:22:43
como un castillo 00:22:45
¿cómo puede ser que no lo encuentre? 00:22:46
pues no lo encuentra 00:22:50
¿y por qué no lo encuentra? 00:22:51
pues claro, aquí viene 00:22:54
la maravilla 00:22:57
y es 00:22:59
porque aquí hay dos programas vivos 00:23:00
sin contar la máquina virtual 00:23:03
aquí está mi aplicación 00:23:05
y está el Tomcat 00:23:07
y cada uno de ellos 00:23:09
tiene su ámbito de instancias 00:23:11
distinto 00:23:13
antes yo tenía 00:23:15
en la aplicación de escritorio teníamos una única instancia 00:23:16
que era mi aplicación 00:23:20
con lo cual todos los objetos existentes 00:23:21
incluyendo los propios driver 00:23:23
estaban en un único ámbito 00:23:25
todos se miraban, se veían con todos 00:23:27
ahora que ha pasado aquí 00:23:30
cuando la aplicación 00:23:32
se ha cargado 00:23:34
cuando el Tomcat se ha cargado 00:23:35
perdón, cuando la aplicación se ha cargado 00:23:38
se ha cargado 00:23:40
la clase 00:23:42
DriverManager 00:23:44
entonces DriverManager que es 00:23:45
a ver 00:23:47
DriverManager es esto 00:23:49
vámonos a la clase Connection 00:23:51
driverManager es este tío, ¿verdad? 00:23:53
donde tenemos el 00:23:59
este 00:24:00
driverManager es este, vale, esta es una clase 00:24:01
que se dedica 00:24:04
a manejar todos los objetos driver 00:24:06
que tenga la aplicación 00:24:08
en mi caso va a tener solo uno, el de MySQL 00:24:09
pero podría tener muchos 00:24:13
esta es una clase que se dedica a manejar 00:24:14
todos los objetos driver que tenga 00:24:16
esta clase cuando se carga 00:24:17
se carga con el 00:24:20
Tomcat, porque cuando mi aplicación arranca 00:24:22
cuando yo la haya arrancado 00:24:24
primero arranca el Tomcat 00:24:26
y luego arranca la aplicación 00:24:28
el Tomcat arranca 00:24:30
y arranca su driver manager 00:24:32
que es su gestor de drivers 00:24:35
que ahí se queda tan pancho 00:24:36
vale, luego arranca la aplicación 00:24:38
y la aplicación 00:24:41
instancia 00:24:43
sus dependencias, entre ellas 00:24:44
la del driver de MySQL, que es esta 00:24:46
vale, esta de aquí 00:24:49
luego 00:24:51
el driver 00:24:53
está en el contexto de objetos 00:24:54
de la aplicación 00:24:56
y el driver manager está en el contexto 00:24:57
de objetos del Tomcat, con lo cual no se ven 00:25:00
entonces, el driver 00:25:02
cuando yo le digo aquí 00:25:04
a driver manager getConnection 00:25:05
cuando hago esto de aquí 00:25:08
driver manager ¿qué hace? 00:25:10
voy a buscar un driver 00:25:12
para manejar esta conexión, voy a buscarlo 00:25:14
dice, pero si no tengo ningún driver 00:25:17
claro, porque driver manager está 00:25:18
mirando en su ámbito 00:25:20
de objetos, y su ámbito de objetos 00:25:22
instanciados es el ámbito del Tomcat 00:25:24
y sin embargo 00:25:25
nuestro driver está instanciado 00:25:27
en el ámbito de la aplicación, porque es una dependencia 00:25:30
de la aplicación, no es una dependencia del Tomcat 00:25:32
es una dependencia de la aplicación 00:25:34
entonces driver mayer te dice, perdóname 00:25:35
no tengo ningún driver, no lo tiene 00:25:37
vale, pues 00:25:40
¿cómo arreglamos esto? 00:25:42
pues hay que hacer una cosa 00:25:43
que es registrarlo 00:25:44
específicamente y decirle 00:25:48
aquí al Tomcat cuando el Tomcat está leyendo 00:25:50
esto, oye tú 00:25:52
instánciate esto, cógete este objeto 00:25:53
que te va a hacer falta, cógete este 00:25:56
porque está instanciado 00:25:58
está registrado, que se llama así 00:25:59
en el ámbito de objetos de la aplicación 00:26:01
pero en el tuyo 00:26:04
bueno, pues ¿cómo se le dice eso? 00:26:04
pues con una sentencia 00:26:08
que se llama 00:26:09
esta de aquí 00:26:10
que esta es la que te obliga 00:26:12
a registrar 00:26:19
objetos, en tu ámbito de objetos 00:26:22
entonces aquí vamos a poner 00:26:24
espera, el driver 00:26:26
que el driver, uno podría buscar desde aquí 00:26:29
como se llama, se iría a la dependencia 00:26:31
lo buscaría, como se llama 00:26:33
com.mysql 00:26:35
cjjdbc 00:26:37
driver, este es 00:26:39
mi driver, este es el objeto que yo quiero 00:26:43
este es el objeto que quiero 00:26:45
que se quede visible 00:26:47
en el ámbito de objetos del podcast 00:26:48
pues transformamos y ponemos todo 00:26:50
com.mysql 00:26:52
punto 00:26:56
punto jdbc, no este es el antiguo, es con el cj delante, con el cj, es el moderno, 00:26:59
está aquí, este sería, driver, este sería que está en comma y sql, cj.jdbc.driver, 00:27:12
Y esto puede lanzar una excepción 00:27:26
Porque esa clase no existiera 00:27:33
No pasa nada 00:27:35
Bueno pues con esto 00:27:37
Hacemos que la instancia 00:27:41
Driver que estaba solamente 00:27:43
En el ámbito de dependencias de la aplicación 00:27:44
Pum, pase al Tomcat 00:27:46
Porque Tomcat es el que va haciendo todo eso 00:27:48
Es que se me abre sola la ventanita esa 00:27:50
Entonces 00:27:56
Esto 00:28:00
esta sentencia 00:28:01
es la sentencia que se ha llamado de toda la vida 00:28:09
registrar el driver 00:28:11
para que el driver manager lo encuentre 00:28:13
entonces hasta la versión no sé qué 00:28:15
de los 00:28:18
drivers MySQL hasta la 8 00:28:20
o no sé cuál, había que verlo siempre sí o sí 00:28:21
pero a partir de la 00:28:24
versión 8 de los drivers 00:28:26
el driver se carga solo 00:28:27
con lo cual no hay que 00:28:29
ponerla, pero claro, se carga 00:28:31
solo en tu aplicación 00:28:33
si te está ejecutando otro como es el Tomcat 00:28:35
a él no le vale lo que tú te has cargado 00:28:37
por eso tienes que poner esto 00:28:39
para que él lo vea visible 00:28:41
con lo cual, las aplicaciones web 00:28:43
que se ejecutan a través de 00:28:45
un secundario que es el Tomcat 00:28:47
pues vas a tener que registrar 00:28:49
todos los objetos que necesite 00:28:51
el Cyber Manager 00:28:53
Entonces 00:28:54
A ver, voy a ver porque si lo tengo 00:29:01
Esto, este es el proyecto que voy a subir 00:29:03
Si lo tengo escrito por aquí 00:29:05
Lo copio y pego para que se quede subido 00:29:06
Se suponía 00:29:09
Que lo escribí por aquí para subirlo 00:29:12
Esto 00:29:14
Todo este rollo 00:29:16
En todo este rollo intenté explicar esto 00:29:18
Lo intenté explicar más o menos 00:29:20
Pues todo este rollo lo copio aquí 00:29:21
Para que cuando suba el proyecto 00:29:23
Pues se quede así 00:29:27
Esto lo voy a subir ahora 00:29:28
Porque lo estamos construyendo 00:29:37
¿Vale? Lo voy a subir cuando lo acabemos 00:29:38
Vale 00:29:41
¡Hala! 00:29:42
Pues ahora ya sí no debería 00:29:45
Darme ese error de que no encuentro el driver 00:29:47
Ahora tienes que encontrarlo muchacho 00:29:49
Vale 00:29:50
Pues vamos a 00:29:52
Reiniciar el server 00:29:54
Restart 00:29:57
Vamos a darle marcha a Catalina 00:30:01
Y... 00:30:06
Ah, que tenía cerrado yo mi explorador 00:30:11
Tengo aquí mi este 00:30:14
Listar ventas 00:30:17
Mirad que bonito 00:30:19
¿Vale? Ventas listadas 00:30:20
Todo estupendo 00:30:23
Vamos a hacer eliminar ventas 00:30:24
Que ahora ya sé que va a necesitar un formulario 00:30:26
Con otro, el método que nos faltaba 00:30:28
Eliminar ventas 00:30:30
claro, pero eso como una sentencia ya está 00:30:31
no haría falta devolver nada 00:30:38
en el método de 00:30:40
bueno, no hace falta devolver 00:30:43
hombre, un mensaje de ok 00:30:44
que menos 00:30:45
pero lo que sí que necesita a cambio es un parámetro 00:30:46
es que id quieres eliminar 00:30:50
que este no necesitaba nada 00:30:52
pues venga 00:30:53
dígame 00:30:55
¿te acuerdas de un cambio 00:30:56
de que estaba barra coche 00:30:57
que no fuera el barra venta 00:30:59
si, en el 00:31:01
index, en el index 00:31:04
aquí, en el 00:31:07
index, aquí 00:31:09
yo tenía puesto coches porque era la url 00:31:10
del otro proyecto, pues ventas 00:31:13
vale, pues vamos 00:31:14
ahora a hacer eliminar 00:31:17
que es el que nos faltaba, podríais 00:31:18
hacer estos 00:31:21
y ya está 00:31:22
desde webapp 00:31:23
todo lo que 00:31:30
webapp es la raíz 00:31:32
de la url, de alguna manera 00:31:34
vale, pues venga, eliminar 00:31:37
venta, pues vamos a hacer este 00:31:39
formulario al que me lleva este enlace 00:31:40
pues más que hacerlo, lo vais a copiar 00:31:42
de lo que os he pasado 00:31:45
yo y los domingos por la tarde, subiendo 00:31:46
cosas para que no 00:31:52
nos herniemos copiando 00:31:54
Venga, vamos a copiar el form 00:31:56
Eliminar 00:32:03
Y lo hacemos colgar 00:32:04
De webapp 00:32:10
Webapp, vale, ¿dónde está webapp? 00:32:11
Jolines, que no veo ni webapp 00:32:32
Ahí, paste 00:32:34
Vale, pues vamos a ver el formulario 00:32:35
De eliminar, aparte del estilo 00:32:40
ese tan bonito que nos ha dado ChaGPT. 00:32:42
Eliminar 00:32:45
venta. Cuidado 00:32:46
el action del formulario. 00:32:48
Vamos a cambiarlo 00:32:51
porque mi serlet yo lo he 00:32:51
hecho colgar de ventas. 00:32:53
Cuidado. Cuidado 00:32:56
primero. Action del formulario. 00:32:57
Juanjo y Ana. 00:33:00
Que luego decís, ¿dónde habéis cambiado? Pues en el 00:33:02
action del formulario. 00:33:03
Ventas. ¿Vale? 00:33:06
Y ahora, le pasamos 00:33:08
como parámetro escondido 00:33:10
qué queremos hacer con ese formulario, ¿vale? 00:33:11
Como parámetro escondido le pasamos E, que es eliminar, 00:33:14
lo que queremos hacer, ¿vale? 00:33:17
Que es eliminar. 00:33:19
Y ahora le pasamos el ID de la venta 00:33:20
con esta caja tan bonita de números 00:33:23
que me va a salir luego y un volver al menú y ya está. 00:33:25
Luego los parámetros que envía este formulario 00:33:28
son como escondido la acción a hacer 00:33:30
para que el ser le sepa que tiene que eliminar 00:33:32
y el ID y ya está. 00:33:35
Pero, importante, 00:33:37
este método no va en GET 00:33:40
no debería ir en GET 00:33:42
sino que va en POST 00:33:43
¿es obligatorio? 00:33:45
no es obligatorio 00:33:47
pero es conveniente para evitar mal funcionamiento 00:33:48
¿por qué este en POST y el otro en GET? 00:33:52
claro 00:33:55
el otro iba en GET 00:33:56
porque el otro consultaba 00:33:57
no cambiaba datos de la base de datos 00:33:58
este 00:34:01
al igual que el de actualizar o insertar 00:34:02
va a modificar los datos 00:34:05
con lo cual debería ir en POST 00:34:07
¿por qué exactamente? 00:34:09
pues bueno, por muchas implicaciones 00:34:11
o sea, una por ejemplo, una importante 00:34:13
cuando tú le das a F5 00:34:15
a un formulario 00:34:17
¿vale? si el formulario 00:34:18
es, tú lo tienes 00:34:21
como GET, no te pide 00:34:23
confirmación de reenvío 00:34:25
entonces, si estás modificando los datos 00:34:26
si es un formulario que modifica, igual lo estás 00:34:29
haciendo un insert una y otra vez, una y otra vez 00:34:30
y no quieres hacerlo, sin embargo, si el formulario 00:34:33
es POST y tú le das a F5 00:34:35
él te dice 00:34:37
desear reenviar los datos del formulario 00:34:38
esa ya es la primera cosa 00:34:41
interesante 00:34:43
segunda, los GET 00:34:43
van a la, los formularios GET 00:34:47
los resultados de los formularios GET 00:34:49
van a la caché 00:34:50
se cachean, los POST no 00:34:52
¿vale? 00:34:54
entonces, es que es justo lo que 00:34:57
queremos 00:34:59
los POST no queremos que se 00:34:59
cacheen, porque si se cachean, yo a lo mejor 00:35:03
creo que estoy insertando ventas 00:35:05
y no lo estoy haciendo 00:35:06
porque estoy todo el rato en local 00:35:07
con el get no es tan importante 00:35:09
que estar tirando de la cache 00:35:12
vale, si tiro de la cache 00:35:14
no estaré refrescando la consulta 00:35:16
pero lo grave es cuando estoy actualizando 00:35:18
cosas sin saber 00:35:20
entonces hay diferencias entre 00:35:21
cómo trata el navegador 00:35:24
un formulario get y un formulario post 00:35:25
cómo lo trata, vale 00:35:28
entonces precisamente por esa diferencia en cómo se trata 00:35:29
un formulario get y post desde el navegador 00:35:32
asumimos 00:35:34
Que las acciones CRU de modificar van en POST y las de consultar en GET. 00:35:36
Aparte que ya sabéis que en el POST los parámetros se mandan en el cuerpo de la petición, 00:35:45
con lo cual no son visibles a simple vista y en el GET se mandan. 00:35:51
Entonces, un segundo, en un formulario que vas a insertar datos y estás mandando los datos, 00:35:54
si lo mandas como get 00:36:00
es que van todos puestos 00:36:02
en la URL y los ves, se ven 00:36:04
se ven directamente 00:36:06
lo que vas a insertar Pepito con su DNI 00:36:07
con su no sé qué, mejor en post 00:36:09
y así va en el cuerpo y no ves los datos 00:36:12
que vas a insertar, estoy convencido 00:36:13
que me podría haber callado mucho antes 00:36:16
porque ya estarías convencido de antes 00:36:18
claro, vale 00:36:19
pues entonces, este va a hacer post 00:36:21
con lo cual 00:36:24
a qué punto de mi serlet va a llegar 00:36:26
va a llegar aquí 00:36:28
pero no pasa nada porque yo no me voy a duplicar 00:36:30
el mismo código en los dos sitios 00:36:33
de aquí hago este código y ya está 00:36:34
¿vale? no significa esto 00:36:36
que el formulario haya cambiado de post a get 00:36:39
el formulario sigue siendo post y se trata 00:36:41
como post en el navegador, pero el código 00:36:43
de respuesta pues se va 00:36:45
aquí arriba, entonces se va aquí arriba 00:36:47
y ahora ya sí, oye si el parámetro 00:36:49
action es igual a eliminar 00:36:50
que va a ser precisamente el parámetro 00:36:52
action que va a ser el que lleva 00:36:55
el formulario 00:36:57
¿no? lleva el parámetro 00:36:57
eliminar, pues entonces 00:37:00
ahora ya tendremos que sacar el id 00:37:02
y eliminar por id 00:37:04
pues venga, ahora ya tendremos que hacer 00:37:05
nuestro service y llamar 00:37:08
al método 00:37:10
service.delete 00:37:10
uy, no lo tenemos 00:37:17
eliminar venta, pues vamos a crearlo 00:37:18
en el servicio 00:37:20
a ver, el código 00:37:20
no es que lo esté dejando, o sea, es que 00:37:26
este método doPost 00:37:28
está ejecutando 00:37:30
este código, pero el formulario sigue siendo 00:37:32
post, lo que pasa es que no duplico el código 00:37:34
en los dos sitios, porque como va a ser el mismo 00:37:36
pero una cosa es el código de respuesta 00:37:37
y otra cosa es como trata 00:37:40
el navegador el formulario por cuestiones 00:37:41
independientes 00:37:44
vale, pues entonces aquí 00:37:46
vamos a hacernos 00:37:48
en el servicio 00:37:50
en el ventaservice este 00:37:51
vamos a hacernos el método que nos falta 00:37:55
que es el de 00:37:59
public 00:38:00
vamos a 00:38:02
en lugar de un void 00:38:05
pues para ya usar el parámetro 00:38:08
de retorno para ver si realmente se eliminó 00:38:10
o no, pues vamos a 00:38:13
un boolean, para yo poder devolver 00:38:14
en un html, si se eliminó correctamente 00:38:16
no, no se pudo eliminar, yo que sé 00:38:18
pues venga 00:38:20
delete venta 00:38:22
delete venta que 00:38:24
necesita un integer id 00:38:26
y ahora este es el que me va a llamar 00:38:28
directamente al dao.deleteventa by id 00:38:31
vale 00:38:36
que es el que tenemos que hacer 00:38:37
entonces me da un error porque el deleteventa by id 00:38:39
que yo había dejado planteado 00:38:42
no me devolvía boolean pero lo cambiamos a boolean y ya está 00:38:44
facilísimo 00:38:47
venga vámonos al dao implementación 00:38:50
y este deleteventa by id que estaba 00:38:54
sin hacer, vamos a ponerle 00:38:56
primero un boolean 00:38:59
y ahora ya si que vamos a las 00:39:00
maravillas del 00:39:04
prepare statement 00:39:06
pues venga 00:39:07
mi sentencia 00:39:09
va a ser prepare 00:39:11
statement 00:39:15
conexión 00:39:17
el objeto conexión que es 00:39:21
connection 00:39:23
connection punto 00:39:24
prepare statement 00:39:27
ahora delete 00:39:28
from 00:39:31
coches 00:39:32
creo que se llamaba la tabla 00:39:34
no, se llamaba ventas 00:39:37
coches era la base de datos 00:39:40
delete from ventas 00:39:41
where 00:39:43
id igual 00:39:44
y ahora ya si que si 00:39:47
pumba 00:39:49
interrogación, nada de concatenar y partir 00:39:50
ahí el este 00:39:53
ahora este como es un recurso que se va 00:39:54
a cerrar, pues lo meto yo en mi try 00:39:57
con recursos 00:39:59
lo meto en el try 00:40:00
con recursos este de aquí 00:40:04
y ahora ya 00:40:06
antes de ejecutar 00:40:10
el delete, tengo que fijar en los parámetros 00:40:11
pues venga 00:40:14
este solo tiene uno 00:40:16
que es entero, pues ps.set 00:40:18
int 00:40:21
la interrogación de posición 00:40:22
1, dale el valor id 00:40:24
uy, id 00:40:26
no, id 00:40:28
así 00:40:29
vale 00:40:31
que yo tengo una sentencia 00:40:33
con más interrogaciones 00:40:35
o el ID igual a no sé 00:40:38
cuántos que tienen más interrogaciones 00:40:40
por eso es un SQL gordote 00:40:42
pues voy fijando cada una 00:40:43
uno es la primera interrogación en orden de aparición 00:40:46
dos la segunda interrogación en orden de aparición 00:40:49
porque este no es una colección 00:40:50
de datos 00:40:57
lo que empieza por cero son las colecciones 00:40:57
los arrays, todo lo que es 00:41:00
Esto no son datos, en realidad. 00:41:02
Hombre, es la mejor forma de transmitir 00:41:09
aquí falta algo, ¿no? ¿Qué otro símbolo pondrías? 00:41:12
Interrogación no es porque yo lo diga, sino porque es así. 00:41:15
No, no, porque me apetece, no. 00:41:21
Porque el método prepareStateMath 00:41:23
interpreta donde hay interrogaciones 00:41:28
que tú lo vas a fijar luego. 00:41:31
Tienen que ser interrogaciones sí o sí por obligación 00:41:32
¿A qué te refieres? 00:41:35
¿Va a la interrogación por una X, por ejemplo? 00:41:41
Hombre, pero entonces 00:41:46
¿No estamos haciendo una sentencia 00:41:47
Con el preparo de statement? 00:41:49
¿Estás haciendo un statement normal a que puedes meter inyección? 00:41:51
Que no queremos eso 00:41:54
A ver, lo puedes hacer de esa manera 00:41:55
Pero tienes un código peligroso 00:41:59
Una aplicación con unos agujeros de seguridad 00:42:01
muy gordos 00:42:03
de inyecciones SQL 00:42:04
no, porque 00:42:09
esto ya se ha precompilado 00:42:10
con lo cual esto no es una concatenación tal cual 00:42:12
entonces si el usuario me mete 00:42:15
aquí un Drop Database 00:42:17
el Drop Database no encaja en ese 00:42:18
hueco, porque eso ya está precompilado 00:42:21
y él ya sabe por esa precompilación 00:42:23
que aquí tiene que ir un entero 00:42:25
entonces tú le metes algo que sea un entero 00:42:27
como un Drop Database y dice 00:42:29
uy, esto no me encaja aquí, aquí se lo ponen enteros 00:42:30
Entonces, no casa. 00:42:33
Sin embargo, con lo que tú has hecho... 00:42:34
¿Dónde? 00:42:35
Hombre, pero es que tal vez 00:42:41
te estás tú matando a ti mismo porque tú eres 00:42:42
el que nos está escribiendo esto. 00:42:43
Si puedes cambiar de lado abajo, puedes cambiar de lado arriba. 00:42:45
No tiene sentido. 00:42:47
¿Cómo que no tiene sentido? 00:42:49
No acabo de entender lo que me estás diciendo tú. 00:42:51
Aquí la idea, la aplicación 00:42:53
se craquea desde fuera. 00:42:55
Desde sus puntos de entrada. 00:42:57
Aquí el único punto de entrada es la interrogación. 00:42:59
No hay otro. 00:43:01
porque todo lo demás es código 00:43:02
que has escrito tú 00:43:05
en el otro, el más 00:43:07
y lo que pones aquí es un punto 00:43:13
de entrada, porque es directamente 00:43:16
el parámetro que tú metes 00:43:17
y ahí como es una concatenación 00:43:20
cuela cualquier cosa 00:43:22
porque es concatenación 00:43:24
pero aquí no estamos concatenando 00:43:25
aquí estamos 00:43:26
¿dónde? 00:43:27
en el primer caso 00:43:30
en el primer caso 00:43:40
no te explotas 00:43:42
no te explotas 00:43:43
pero tú tienes que concatenar bien 00:43:44
si tú lo concatenas 00:43:48
podemos hacer luego un ejemplito 00:43:49
que claro que te explota 00:43:51
pero tienes que ser listo 00:43:52
y no concatenar con lo que él espera 00:43:53
y luego concatenar 00:43:58
con el procedimiento almacenado que sea 00:43:59
de los database, o sea, poner una cosa 00:44:01
SQL que concatenada 00:44:03
con lo que tú has escrito tenga sentido 00:44:05
y claro que hay posibilidades 00:44:07
¿Cómo? 00:44:09
¿Qué has dicho? 00:44:15
A ver, esta situación 00:44:18
de aquí arriba 00:44:23
esta 00:44:24
y poner la interrogación 00:44:32
aquí dentro, no tienen nada que ver 00:44:36
¿por qué? 00:44:38
en esta, tú primero haces 00:44:42
un stream 00:44:44
que aquí no hay todavía ni jdbc 00:44:45
ni seguro, haces un stream 00:44:48
y ahora este stream lo haces 00:44:49
cogiendo este stream 00:44:51
y concatenándole algo que te ha metido 00:44:53
alguien en un formulario. 00:44:56
Imagínate que sea algo que te ha metido 00:44:58
alguien es uno 00:45:00
and no sé qué, and no sé 00:45:01
cuánto, punto y coma, 00:45:04
llamado de orden de almacenado. Algo 00:45:05
cuyo resultado final 00:45:07
es un script válido en SQL. 00:45:09
Bueno, pues ese 00:45:13
script válido en SQL ahora lo ejecuta 00:45:14
sin pensar. 00:45:16
Pues se hace todo lo que hay en ese 00:45:18
script. Claro, el que sea 00:45:20
tendría que hacer todas las pruebas necesarias 00:45:22
para que lo que pone aquí 00:45:24
encaje y te genera un SQL válido. 00:45:25
Pero no deja de ser 00:45:28
una prueba y error que se puede hacer y es un 00:45:29
agujero de seguridad y no es tan 00:45:31
difícil de hacer. La opción 00:45:33
la tienes abierta. Abajo es 00:45:35
imposible. Abajo es imposible 00:45:37
porque ahora cambio. Yo pongo 00:45:40
aquí una interrogación y luego 00:45:42
lo fijo con el set view. 00:45:43
Aquí, ahora ya 00:45:46
JDBC te analiza 00:45:47
esto, te hace un preanálisis 00:45:49
y te dice, vale, esto es una 00:45:51
sele y aquí tengo una cajita 00:45:53
donde solo voy a permitir que 00:45:55
entre un número entero, solo voy a permitir un número entero 00:45:57
y ese número entero lo meto 00:45:59
con setting, si tú le metes 00:46:01
aquí 00:46:04
le metes 00:46:05
algo que no sea 00:46:08
un entero, es que no te va a dejar 00:46:10
te va a decir, te va a petar 00:46:12
la aplicación, porque esto es una 00:46:13
cajita para un entero 00:46:15
sin embargo ahí es una concatenación para lo que te dé la gana 00:46:16
lo otro es lo que te dé la gana 00:46:20
el otro es una cadena 00:46:25
la cadena que tú quieras 00:46:26
pero que no te tiene 00:46:27
pero da igual 00:46:30
porque tú no verificas en ningún momento 00:46:32
que sea un íntegro, tú haces el ejecute 00:46:34
tú no verificas que sea un íntegro 00:46:36
aquí, ¿dónde estamos? 00:46:39
aquí 00:46:43
¿en qué momento? 00:46:44
¿en qué momento he comprometido yo 00:46:45
a que eso sea un íntegro? 00:46:48
¿en qué momento? 00:46:50
a ver, no, pero es que esto lo ha convertido 00:46:51
a stream, yo aquí puedo meter cualquier 00:46:58
cosa 00:47:00
a ver 00:47:00
aquí en el 00:47:09
te refieres, cuando tú llamas al find by id 00:47:11
este método sí te está haciendo 00:47:13
un filtrado 00:47:16
el método sí te está haciendo un filtrado 00:47:16
pero en un caso genérico 00:47:19
esto podría ser estructurado de otra manera 00:47:20
estamos hablando de que esta sentencia 00:47:22
tiene un agujero de seguridad 00:47:24
en mi arquitectura de aplicación en concreto 00:47:25
que yo he filtrado 00:47:29
poniendo un método antes que tenga un ID 00:47:30
pues hombre, no te va 00:47:32
a compilar, pero hablo 00:47:34
en general, en general esto es un agujero de seguridad 00:47:36
porque aquí puedes concatenar con cualquier 00:47:39
cosa 00:47:40
No he entendido nada de lo que has dicho 00:47:52
Más que no lo he entendido, que no lo he oído 00:47:57
Yo es que no lo he oído 00:48:00
Pero con que lo hayáis oído y entendido vosotros es suficiente 00:48:03
Pero bueno, la idea 00:48:06
La idea está, ¿no? 00:48:09
Claro 00:48:13
O sea, que esto, jolín, es que metes lo que vas a hacer 00:48:13
Claro, bueno 00:48:16
Vale, pues ya está 00:48:19
Vale, pues 00:48:25
Bueno, pues ahora 00:48:29
Fijamos 00:48:31
¿Quién se ha ido? 00:48:32
Vale, entonces fijamos este entero 00:48:39
Y ahora 00:48:41
Lo ejecutamos 00:48:42
como este es un delete 00:48:44
es un execute 00:48:49
update 00:48:51
¿vale? 00:48:52
porque actualiza la base de datos 00:48:55
entonces el execute update este 00:48:57
aparte te da información 00:48:59
sobre la cantidad de registros que se han visto 00:49:01
afectados, como estamos borrando 00:49:03
por id debería ser 1 00:49:05
entonces va a ser 1 o ninguno 00:49:06
vamos a utilizar ese dato para 00:49:09
devolver el true o false 00:49:11
Entonces pues vamos a hacerle aquí 00:49:12
Yo que sé 00:49:14
Return psqtudate 00:49:15
Igual a 1 00:49:18
¿Vale? 00:49:19
Y me va a devolver true 00:49:21
Y aquí 00:49:23
Y aquí 00:49:24
Return 00:49:29
¿Vale? 00:49:31
Y aquí 00:49:35
Falses 00:49:36
Si no ha salido por aquí 00:49:38
Es porque 00:49:42
Bueno, a ver, es que es por ID 00:49:44
Entonces 00:49:52
Retún falso, vale 00:49:53
Y aquí esto es por el catch 00:49:57
¿Verdad? 00:50:00
Ah, en el venta dao, efectivamente 00:50:05
Vale, en el venta dao 00:50:07
Que lo tengo abierto en algún sitio 00:50:09
En el venta dao 00:50:11
Sí, el venta dado 00:50:13
Lo tengo 00:50:17
El venta dado lo tenía con voy 00:50:19
Divertidamente 00:50:20
Vale 00:50:21
Venga, venta dado, me devuelve un boolean 00:50:24
Venta dado, implementación 00:50:27
Ahora ya sí 00:50:30
Me dice que añada el catch 00:50:32
Añadimos el catch 00:50:33
Vale 00:50:36
Y ahora me borra 00:50:37
Si lo 00:50:40
El resultado es igual a uno 00:50:41
Sale por aquí 00:50:43
Y ya está 00:50:44
Y si sale por el catch 00:50:52
Pues falso 00:50:53
Venga, delete venta está 00:50:55
Y ahora ya 00:50:57
Nuestro serlet 00:50:59
Que estaba 00:51:01
Vale, a ver 00:51:02
¿Os parece si le digo que lo retrasamos un poco? 00:51:05
No, no, no 00:51:07
Lo que pasa es que le tengo que decir 00:51:08
Que baje a 00:51:13
Firmar mi guardia 00:51:14
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:
9 de diciembre de 2025 - 14:16
Visibilidad:
Clave
Centro:
IES ROSA CHACEL
Duración:
51′ 17″
Relación de aspecto:
1.78:1
Resolución:
1920x1080 píxeles
Tamaño:
239.18 MBytes

Del mismo autor…

Ver más del mismo autor


EducaMadrid, Plataforma Educativa de la Comunidad de Madrid

Plataforma Educativa EducaMadrid