5.1. Configuración#
El primer paso es saber cómo configurar nuestro proyecto para poder usar la especificación JPA. Necesitamos dos cosas:
Importar librerías.
Crear una configuración.
5.1.1. Depedencias#
<dependencies>
<!-- Driver JDBC para SQLite -->
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.49.1.0</version>
</dependency>
<!-- JPA -->
<dependency>
<groupId>jakarta.persistence</groupId>
<artifactId>jakarta.persistence-api</artifactId>
<version>3.2.0</version>
</dependency>
<!-- Hibernate (Implementación de JPA) -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>7.0.0.Beta4</version>
</dependency>
<!-- Soporte en Hibernate para SQLite -->
<dependency>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-community-dialects</artifactId>
<version>7.0.0.Beta4</version>
</dependency>
<!-- Opcional para anotaciones de comprobación -->
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
<version>3.1.1</version>
</dependency>
<!-- Opcional para que Hibernate implemente las anotaciones de comprobación -->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>9.0.0.CR1</version>
</dependency>
</dependencies>
En resumidas cuentas es:
El driver JDBC para soportar el SGBD que nos interese (para SQLite es sqlite-jdbc).
El soporte para JPA proporcionado por jakarta.persistence-api.
El soporte para Hibernate. En el caso particular de SQLite, hibernate-core no soporta de serie SQLite, por lo que se debe añadir uan librería más (hibernate-community-dialects).
En principio, basta con lo anterior, pero si se quiere llevar a cabo comprobaciones sobre los valores de los datos, serán necesaria la especificación sita en jakarta.validation-api y su implementación en hibernate-validator.
5.1.2. Configuración de la persistencia#
Debe escribirse en el archivo resources/META-INF/persistence.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="3.0"
xmlns="https://jakarta.ee/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence
https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd">
<!-- Nombre de la unidad de persistencia -->
<persistence-unit name="MiUnidadP" transaction-type="RESOURCE_LOCAL">
<!-- Proveedor de JPA (Hibernate) -->
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<!-- Entidades (deberían autodetectarse si están anotadas con @Entity) -->
<class>edu.acceso.ejemplo.modelo.MiClase</class>
<!-- Más clases ... -->
<properties>
<!-- Propiedades generales (conexión a la base de datos) -->
<property name="jakarta.persistence.jdbc.driver" value="org.sqlite.JDBC"/>
<property name="jakarta.persistence.jdbc.url" value="jdbc:sqlite::file:memory:"/>
<!-- Innecesarios para SQLite -->
<property name="jakarta.persistence.jdbc.user" value=""/>
<property name="jakarta.persistence.jdbc.password" value=""/>
<!-- Configuración propia de Hibernate -->
<property name="hibernate.dialect" value="org.hibernate.community.dialect.SQLiteDialect"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.show_sql" value="false"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.use_sql_comments" value="true"/>
</properties>
</persistence-unit>
</persistence>
En este archivo:
Debemos recordar el nombre que le damos a la unidad de persistencia, porque la usaremos luego; y hay propiedades que
El proveedor indica cuál es la implementación JPA que usaremos. Algunos muy usandos son:
Proveedor
Hibernate
org.hibernate.jpa.HibernatePersistenceProvider
EclipseLink
org.eclipse.persistence.jpa.PersistenceProvider
OpenJPA
org.apache.openjpa.persistence.PersistenceProviderImpl
BatooJPA
org.batoo.jpa.persistence.PersistenceProviderImpl
En caso de que no se detecten, se pueden registrar las clases del modelo cuyos objetos se quieren hacer persistentes.
La url, el driver y dialecto específico dependen de cuál sea el SGBD que utilicemos. La enumeración de los más utilizados la tenemos en una tabla de la unidad anterior, pero necesitamos añadir a ella cómo se llaman los dialectos específicos de Hibernate:
SGBD
Dialecto
SQLite
org.hibernate.community.dialect.SQLiteDialect[1]
MariaDB
org.hibernate.dialect.MariaDBDialect
MySQL
org.hibernate.dialect.MySQLDialect
PostgreSQL
org.hibernate.dialect.PostgreSQLDialect
Oracle
org.hibernate.dialect.OracleDialect
SQL Server
org.hibernate.dialect.SQLServerDialect
La propiedad
hibernate.hbm2ddl.auto
define cómo actuará la aplicación al comparar el esquema definido en las clases con el existente en la base de datos, y puede tener cuatro valores:Valor
Descripción
Efecto
Sin esquema previo
Con esquema previo
none
No hace nada
-
-
validate
Comprueba el esquema
Error
Error si no son iguales
update
Actualiza el esquema
Crea el esquema
Actualiza y conserva datos
create
Crea el esquema
Crea el esquema
Lo crea de nuevo (pérdida de datos)
create-drop
Crea el esquema y lo desecha al cerrar.
Como el anterior en ambos casos, pero se pierde todo al cerrar la sesión de Hibernate.
Las tres últimas propiedades se refieren al registro y son útiles a efectos de depuración: se registran las sentencias SQL que genera el ORM (en el nivel DEBUG), tales sentencias se formatean para que resulten más legibles y, además, se acompañan de comentarios.
Ahora bien, ¿qué ocurre cuándo los datos de conexión o el tipo de base de datos no están definidos de antemano, sino que se definen en tiempo de ejecución? En ese caso, puede definirse un java.util.HashMap que defina las valores de propiedades y pasar el mapa cuando se usa la unidad de persistencia para crear el objeto EntityManagerFactory (véase a continuación cómo conectar). En ese caso, las definiciones del mapa sobrescribirán a las que pudieran existir en el archivo. Por ejemplo:
Map<String, String> props = new HashMap<>();
props.put("jakarta.persistence.jdbc.url", "jdbc:sqlite:centro.db");
props.put("hibernate.show_sql", "true");
EntityManagerFactory emf = Persistence.createEntityManagerFactory("MiUnidadP", props);
Notas al pie