Skip to content

Commit 579cf57

Browse files
committed
Sustituye JpaEMUtils por JpaBackend
1 parent 65f379f commit 579cf57

File tree

13 files changed

+322
-252
lines changed

13 files changed

+322
-252
lines changed

source/05.orm/01.conf.rst

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,19 @@ Depedencias
1313

1414
.. code-block:: xml
1515
16+
<properties>
17+
<maven.compiler.release>21</maven.compiler.release>
18+
<hibernate.version>7.1.0.Final</hibernate.version>
19+
</properties>
20+
21+
<!-- ... -->
22+
1623
<dependencies>
1724
<!-- Driver JDBC para SQLite -->
1825
<dependency>
1926
<groupId>org.xerial</groupId>
2027
<artifactId>sqlite-jdbc</artifactId>
21-
<version>3.49.1.0</version>
28+
<version>3.50.3.0</version>
2229
</dependency>
2330
2431
<!-- JPA -->
@@ -32,14 +39,14 @@ Depedencias
3239
<dependency>
3340
<groupId>org.hibernate</groupId>
3441
<artifactId>hibernate-core</artifactId>
35-
<version>7.0.0.Beta4</version>
42+
<version>${hibernate.version}</version>
3643
</dependency>
3744
3845
<!-- Soporte en Hibernate para SQLite -->
3946
<dependency>
4047
<groupId>org.hibernate.orm</groupId>
4148
<artifactId>hibernate-community-dialects</artifactId>
42-
<version>7.0.0.Beta4</version>
49+
<version>${hibernate.version}</version>
4350
</dependency>
4451
4552
<!-- Opcional para anotaciones de comprobación -->
@@ -53,7 +60,14 @@ Depedencias
5360
<dependency>
5461
<groupId>org.hibernate.validator</groupId>
5562
<artifactId>hibernate-validator</artifactId>
56-
<version>9.0.0.CR1</version>
63+
<version>9.0.1.Final</version>
64+
</dependency>
65+
66+
<!-- Opcional para Expression Language (necesario para Hibernate Validator) -->
67+
<dependency>
68+
<groupId>org.glassfish</groupId>
69+
<artifactId>jakarta.el</artifactId>
70+
<version>4.0.2</version>
5771
</dependency>
5872
</dependencies>
5973
@@ -66,11 +80,10 @@ En resumidas cuentas es:
6680
hibernate-core_ no soporta de serie SQLite_, por lo que se debe añadir
6781
uan librería más (`hibernate-community-dialects`).
6882
* En principio, basta con lo anterior, pero si se quiere llevar a cabo
69-
comprobaciones sobre los valores de los datos, serán necesaria la
70-
especificación sita en `jakarta.validation-api`_ y su implementación en
71-
hibernate-validator_.
72-
73-
.. ¿Qué pasa con slf4j-api_ y slf4j-simple_?
83+
comprobaciones sobre los valores de los datos (p.ej. las :ref:`referidas más
84+
adelante <orm-mapping-check>`), serán necesaria la especificación sita en
85+
`jakarta.validation-api`_, su implementación en hibernate-validator_ y
86+
`jakarta.el-api`_, que es necesaria para dicha implementación.
7487

7588
Configuración de la persistencia
7689
--------------------------------
@@ -82,7 +95,8 @@ Debe escribirse en el archivo :file:`resources/META-INF/persistence.xml`:
8295
En este archivo:
8396

8497
* Debemos recordar el nombre que le damos a la unidad de persistencia, porque
85-
la usaremos luego; y hay propiedades que
98+
la usaremos luego; y hay propiedades cuyos valores dependen del |ORM| y el
99+
|SGBD| utilizados.
86100

87101
* El proveedor indica cuál es la implementación |JPA| que usaremos. Algunos
88102
muy usandos son:
@@ -189,3 +203,4 @@ sobrescribirán a las que pudieran existir en el archivo. Por ejemplo:
189203
.. _hibernate-validator: https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator
190204
.. _jakarta.persistence-api: https://mvnrepository.com/artifact/jakarta.persistence/jakarta.persistence-api
191205
.. _hibernate-community-dialects: https://mvnrepository.com/artifact/org.hibernate.orm/hibernate-community-dialects
206+
.. _jakarta.el-api: https://mvnrepository.com/artifact/jakarta.el/jakarta.el-api

source/05.orm/02.basico.rst

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ En este ejemplo:
3434
anotación comentada en el código de más arriba.
3535
- Si el identificador puede ser definido por el usuario y, si no lo hace, el
3636
|SGBD| se encarga de adjudicar uno (``GENERATED AS DEFAULT BY IDENTITY``),
37-
no hay manera de expresarlo con Hibernate_.
37+
no hay manera de expresarlo con |JPA|.
3838

3939
+ Los atributos que son campos se notan con ``@Column`` y pueden añadirse
4040
parámetros para afinar la definición (nombre del campo si no coincide con el
@@ -118,9 +118,7 @@ Como puede verse:
118118
.. rubric:: Notas al pie
119119

120120
.. [#] Más adelante sugerimos :ref:`cómo crear una fábrica que asegure su
121-
unicidad <orm-conn>`.
122-
123-
.. _Hibernate: https://www.hibernate.org
121+
unicidad <orm-pattern>`.
124122
125123
.. |CRUD| replace:: :abbr:`CRUD (Create, Read, Update, Delete)`
126124
.. |JPA| replace:: :abbr:`JPA (Java Persistent API)`

source/05.orm/03.conexion.rst

Lines changed: 0 additions & 64 deletions
This file was deleted.

source/05.orm/04.mapeo.rst

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ Fundamentalmente sirven para:
1515
- Establecer restricciones sobre los valores.
1616
- Definir relaciones entre tablas.
1717

18+
.. _orm-mapping-bas:
19+
1820
Anotaciones básicas
1921
===================
2022
Ya introdujimos las anotaciones más básicas al presentar el :ref:`ejemplo de
@@ -240,6 +242,8 @@ ampliar nuestro conocimientos sobre las anotaciones válidas:
240242
Y el conversor se aplicará automáticamente a todos los atributos de tipo
241243
``Titularidad`` sin necesidad de anotar los atributos individualmente.
242244

245+
.. _orm-mapping-check:
246+
243247
Otras anotaciones
244248
=================
245249
Existen otras anotaciones relacionadas con la validación de valores (el
@@ -335,15 +339,15 @@ Hay tres tipos de relaciones binarias en el modelo relacional:
335339
relación, ya que un extremo puede que informe de una cosa distinta a la
336340
que informa el otro. En el caso anterior, el *estudiante* informa de que
337341
no está matriculado, mientras la lista de estudiantes en el centro
338-
informa de que sí lo está. En casos de discrepancia, Hibernate_ hará
342+
informa de que sí lo está. En casos de discrepancia, |JPA| hará
339343
prevalecer la información del extremo de la relación que realmente
340344
existe en la base de datos, esto es, la información que ofrece
341345
*estudiante*.
342346

343347
**Relación 1:1**: ``@OneToOne``
344348
Expresa que cada registro de una tabla se relaciona exclusivamente con uno (o
345349
ninguno) registro de la otra tabla. En |SQL| se resuelve colocando el campo
346-
en cualquiera de las dos tablas. En Hibernate_ para significar este tipo
350+
en cualquiera de las dos tablas. En |JPA| para significar este tipo
347351
relaciones se usa la notación ``@OneToOne`` y, como en el caso anterior,
348352
podemos reflejarla de modo **unidireccional** o **bidireccional**.
349353

@@ -384,7 +388,7 @@ Hay tres tipos de relaciones binarias en el modelo relacional:
384388
quisiéramos relacionar con estudiantes, ya que los estudiantes tienen varios
385389
profesores; y cada profesor imparte sus enseñanzas a varios estudiantes. Por
386390
tanto, la relación entre las tablas *Profesor* y *Estudiante* es una relación
387-
**N:M**. Para implementar en Hibernate_ estas relaciones, han de distinguirse
391+
**N:M**. Para implementar en |JPA| estas relaciones, han de distinguirse
388392
dos casos:
389393

390394
a. La relación no tiene atributos propios: ``@ManyToMany``.

source/05.orm/08.transaction.rst

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -23,34 +23,10 @@ del |ORM| siguiendo la especificación |JPA|:
2323
}
2424
2525
Tuvimos que introducirlas tan temprano porque |JPA| nos obliga a explicitar la
26-
transacción siempre que se realioza alguna operación que implica cambios en la
27-
base de datos. Ciertamente la sintaxis es algo farragosa, por lo que podríamos
28-
definir algunos métodos en :ref:`JpaEMUtils <orm-conn>` que simplificaran su
29-
creación:
30-
31-
32-
.. literalinclude:: files/JpaEMUtils.java
33-
:language: java
34-
:start-after: // Transacciones
35-
:end-before: // Fin transacciones
36-
:dedent:
37-
38-
39-
La existencia de los tres métodos responde a las mismas causas por las que
40-
hicimos varias versiones de ``.getEntityManagerFactory``. Si manejamos una
41-
sola fábrica y ya la creamos antes, que será lo habitual, sólo necesitaremos
42-
pasar la acción:
43-
44-
.. code-block:: java
45-
46-
JpaEMUtils.transaction(em -> {
47-
Centro castillo = new Centro(11004866, "IES Castillo de Luna", Centro.Titularidad.PUBLICA);
48-
em.persist(castillo);
49-
});
50-
51-
Este método simplifica las operaciones en la base de datos, pero a costa de que
52-
los objetos creados dentro de la expresión lambda, no son visibles fuera de
53-
ella.
26+
transacción siempre que se realiza alguna operación que implica cambios en la
27+
base de datos. Ciertamente la sintaxis es algo farragosa, por lo que :ref:`más
28+
adelante introduciremos algunos métodos <orm-pattern>` que simplificarán su
29+
creación.
5430

5531
Hay otros métodos que están asociados al objeto
5632
:jakarta-persistence:`EntityManager`:

source/05.orm/09.dao.rst

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
.. _orm-pattern:
2+
3+
Estrategias de diseño
4+
=====================
5+
Cuando analizamos :ref:`conectores <conn>`, ya expusimos que uno de los patrones
6+
de diseño más socorridos es el patrón |DAO|. Al usar un |ORM| podríamos seguir
7+
esa misma estrategia y definir una interfaz |CRUD| para crear clases |DAO| para
8+
todas las entidades del modelo. En este caso, la única salvedad es que las
9+
implementaciones de los métodos de la interfaz no se basarían en |JDBC| sino en
10+
|JPA|. Ahora bien, muy comúnmente y a menos que nuestra intención sea
11+
reaprovechar una interfaz antigua implementada con |JDBC|, obrar de esta manera
12+
es un poco redundante, ya que el propio |JPA| tiene una orientación semejante a
13+
|DAO|.
14+
15+
Lo que sí es muy conveniente es intentar liberar al resto del código de las
16+
particularidades del acceso, así que conviene encerrarlas en una clase auxiliar.
17+
Podríamos proponer esta:
18+
19+
.. literalinclude:: files/JpaBackend.java
20+
:class: toggle
21+
:caption: JpaBackend.java
22+
:language: java
23+
:start-at: public class
24+
25+
Esta clase implementa un `patrón Singleton`_ ampliado que posibilita la creación
26+
de una única fábrica por entidad de persistencia. Cada una de estas fábricas se
27+
asocia a un índice a partir del **1** para que podamos recuperarlas
28+
posteriormente cuando nos sean necesarias:
29+
30+
.. code-block:: java
31+
32+
public static main(String[] args) throws Exception {}
33+
// Propiedades configuradas en tiempo de ejecución.
34+
Map<String, String> props = new HashMap<>();
35+
props.put("jakarta.persistence.jdbc.url", "jdbc:sqlite:centro.db");
36+
props.put("hibernate.show_sql", "true");
37+
38+
int idx = JpaBackend.createEntityManagerFactory("MiUnidadP", props);
39+
40+
// ...
41+
42+
try(EntityManagerFactory emf = JpaBackend.getEntityManagerFactory(idx)) {
43+
operaciones(idx); // Aquí se crean y usan objetos EntityManager
44+
}
45+
}
46+
47+
private static void operaciones(int idx) {
48+
// ¡Ojo! No hay que cerrarlo.
49+
EntityManagerFactory emf = JpaEmFactory.getInstance(idx); // Devuelve el mismo objeto.
50+
51+
try(em EntityFactory = emf.createEntityManager()) {
52+
EntityTransaction tr = em.getTransaction();
53+
try {
54+
tr.begin();
55+
Centro centro = new Centro(11004866, "IES Castillo de Luna", Centro.Titularidad.PUBLICA);
56+
em.persist(centro);
57+
tr.commit();
58+
}
59+
catch(Exception e) {
60+
if(tr != null && tr.isActive()) tr.rollback();
61+
throw new RuntimeException("Error al almacenar el centro", err);
62+
}
63+
}
64+
}
65+
66+
.. tip:: Se ha permitido también que en caso de que sólo se haya creado una
67+
fábrica, ni siquiera sea necesario facilitar el índice:
68+
69+
.. code-block:: java
70+
71+
try(EntityManagerFactory emf = JpaBackend.getEntityManagerFactory()) {
72+
operaciones();
73+
}
74+
75+
Obtener la fábrica, sin embargo, nos obligaría a crear objetos
76+
:jakarta-persistence:`EntityManager` y a gestionar correctamente las
77+
transacciones con lo que no abstraería el código de las particularidades del
78+
almacenamiento. Por ese motivo la clase incluye algunos métodos para manejar
79+
automáticamente las transacciones:
80+
81+
.. code-block:: java
82+
83+
// Usamos la fábrica 1 para hacer persistente un centro.
84+
// También podríamos obviar el índice, si sólo hubiera una fábrica
85+
JpaBackend.transaction(1, em -> {
86+
Centro centro = new Centro(11004866L, "IES Castillo de Luna", Centro.Titularidad.PUBLICA);
87+
em.persist(centro);
88+
});
89+
90+
91+
// Este método es capaz de devolver lo que devuelve la función del argumento.
92+
// Como en el caso anterior, se puede obviar el índice 1.
93+
Centro otro = JpaBackend.transactionR(1, em -> em.get(Centro.class, 11004866L));
94+
95+
96+
.. |DAO| replace:: :abbr:`DAO (Data Access Object)`
97+
.. |CRUD| replace:: :abbr:`CRUD (Create, Read, Update, Delete)`
98+
.. |JDBC| replace:: :abbr:`JDBC (Java DataBase Connectivity)`
99+
.. |ORM| replace:: :abbr:`ORM (Object-Relational Mapping)`
100+
.. |JPA| replace:: :abbr:`JPA (Java Persistence API)`
101+
102+
.. _patrón Singleton: https://es.wikipedia.org/wiki/Singleton

source/05.orm/10.crud.rst

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@
22

33
Operaciones |CRUD|
44
******************
5-
Ya hemos discutido cómo :ref:`conectar y abrir sesiones de un modo eficiente
6-
<orm-conn>` e incluso :ref:`hemos ilustrado cómo hacer uso de esta estrategia
7-
<orm-uso-sf>`. Toca ahora profundizar en cómo realizar operaciones de
8-
persistencia con la base de datos.
5+
Toca ahora profundizar en cómo realizar operaciones de persistencia con la base
6+
de datos.
97

108
.. rubric:: Contenidos
119

0 commit comments

Comments
 (0)