5.1. Configuración#

El primer paso es saber cómo configurar nuestro proyecto para poder usar la especificación JPA. Necesitamos dos cosas:

  1. Importar librerías.

  2. 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