marp: true theme: uncover paginate: false size: 16:9 backgroundColor: #f4f5f7 color: #1f2933 style: | section {
font-size: 1.9em;
}
h1, h2, h3 {
color: #0f172a;
}
/* Texto secundario */ p, li {
color: #1f2933;
}
/* Cajas destacadas */ .box {
border: 3px solid #2563eb;
padding: 1em;
border-radius: 12px;
background-color: #e0e7ff;
color: #1e293b;
}
.columns {
display: flex;
gap: 1em;
justify-content: center;
align-items: stretch;
}
.box.warning {
border-color: #f97316;
background-color: #ffedd5;
}
/* Alineación */ .left {
text-align: left;
}
/* Código */ pre, code {
background-color: #e5e7eb;
color: #111827;
} .w-30 { width: 30%; } .w-40 { width: 40%; } .w-50 { width: 50%; } .w-60 { width: 60%; } .w-70 { width: 70%; } .w-80 { width: 80%; } .center {
margin-left: auto;
margin-right: auto;
}
Un paseo (de 2h) buceando en código
Spring Data es el paquete del ecosistema Spring para acceder a datos de forma consistente.
Spring Data:
Aplicación
↓
Spring Data — Abstracción de repositorios
Abstracción para definir repositorios y consultas
↓
JPA — API estándar de persistencia
Especificación estándar (interfaces y anotaciones)
↓
Hibernate — ORM (Object–Relational Mapping)
Traducción y mapeo de objetos a SQL
↓
JDBC Driver — Comunicación con la base de datos
Ejecuta SQL contra la base de datos
↓
Base de datos
Spring Data facilita el acceso a datos pero no elimina el modelo relacional.
La base de datos trabaja con:
La aplicación trabaja con:
En Spring Data no consultamos tablas.
Consultamos:
Una entidad define:
Aunque trabajemos con entidades:
Un Repository es:
En Spring Data podemos consultar usando:
@Query)nativeQuery)
A mayor abstracción:
A menor abstracción:
Cuando trabajamos con bases de datos:
Pues... No siempre.
Depende de:
N+1 SELECT
SELECT t1.*, t2.*, ((t1.actual/t2.total)*100) DIV 1 AS progreso,
CASE WHEN t1.actual = t2.total AND t1.nbpar = t2.total AND t1.nbcomp = 1 THEN 'bg-success'
WHEN actual > 0 AND t1.fact <> factorial(actual) AND t1.nbcomp = 1 THEN 'bg-success'
WHEN t1.nbpar = t2.total AND t1.nbcomp = 0 THEN 'bg-danger'
WHEN actual > 0 AND t1.fact = factorial(actual) THEN 'bg-info'
WHEN actual > 0 AND t1.fact <> factorial(actual) AND t1.nbcomp = 0 THEN 'bg-warning'
WHEN t1.discard = 1 THEN 'bg-secondary'
ELSE 'text-black'
END AS class,
CASE
WHEN t1.actual = t2.total AND t1.nbpar < t2.total AND t1.nbcomp = 1 THEN '*'
ELSE ''
END AS aux
FROM
(SELECT al.usuario, al.id_alumno, al.observaciones AS obs, al.muerto AS discard, MAX(n_problema) AS actual,
CAST(SUM(CASE WHEN completa = 0 THEN 1 ELSE 0 END) AS SIGNED) AS nbpar,
CAST(SUM(CASE WHEN completa = 1 THEN 1 ELSE 0 END)AS SIGNED) AS nbcomp,
SUM(n_problema) AS fact
FROM awpsolver.resultados_json rj
LEFT JOIN awpsolver.alumnos al ON al.id_alumno = rj.id_alumno
WHERE rj.id_grupo_experimento = :v
GROUP BY al.usuario, al.id_alumno
UNION
SELECT al.usuario, al.id_alumno, al.observaciones AS obs, al.muerto AS discard, 0 AS actual,
0 AS nbpar, 0 AS nbcomp, 0 AS self_fact
FROM awpsolver.alumnos al
LEFT JOIN grupos_experimentos ge ON al.id_grupo = ge.id_grupo
WHERE ge.id_grupo_experimento = :v AND al.id_alumno NOT IN(
SELECT id_alumno FROM awpsolver.resultados_json WHERE id_grupo_experimento = :v)
ORDER BY 2) AS t1,
(SELECT COUNT(*) AS total, factorial(COUNT(*)) AS fact FROM awpsolver.problemas WHERE id_experimento
IN(SELECT id_experimento FROM awpsolver.grupos_experimentos WHERE id_grupo_experimento = :v)) AS t2;
Ambos ejecutan SQL.
Diferencias:
Queries específicas Aprovecha la potencia de la BD no tengas miedo a escribir 100 lineas de SQL
Proyecciones Traer solo lo necesario (tablas intermedias, vistas materizalidas, ...).
Agregados
(COUNT, SUM, AVG) sobre el SGBD y no en dominio
Paginación real
Traer solo lo necesario, no todo + filtro posterior
Simulación de un juego de estrategia MMO (multijugador masivo en línea) multimundo.