[java] ¿Necesito elementos de <clase> en persistence.xml?


Answers

En el entorno Java SE, por especificación debe especificar todas las clases como lo ha hecho:

Se debe especificar una lista de todas las clases de persistencia gestionadas nombradas en entornos Java SE para garantizar la portabilidad

y

Si no se pretende que las clases de persistencia anotadas contenidas en la raíz de la unidad de persistencia se incluyan en la unidad de persistencia, se debe usar el elemento exclude-unlisted-classes. El elemento exclude-unlisted-classes no está diseñado para su uso en entornos Java SE.

(JSR-000220 6.2.1.6)

En entornos Java EE, no tiene que hacer esto ya que el proveedor escanea las anotaciones por usted.

Extraoficialmente, puede intentar establecer <exclude-unlisted-classes>false</exclude-unlisted-classes> en su persistence.xml. Este parámetro se establece de manera predeterminada en false en EE y true en SE. Tanto EclipseLink como Toplink admiten hasta donde yo sé. Pero no debe confiar en que funcione en SE, de acuerdo con las especificaciones, como se indicó anteriormente.

Puede INTENTAR lo siguiente (puede o no funcionar en entornos SE):

<persistence-unit name="eventractor" transaction-type="RESOURCE_LOCAL">
     <exclude-unlisted-classes>false</exclude-unlisted-classes>

    <properties>
            <property name="hibernate.hbm2ddl.auto" value="validate" />
            <property name="hibernate.show_sql" value="true" />
    </properties>
</persistence-unit>
Question

Tengo un archivo persistance.xml muy simple:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
    xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">

    <persistence-unit name="eventractor" transaction-type="RESOURCE_LOCAL">
        <class>pl.michalmech.eventractor.domain.User</class>
        <class>pl.michalmech.eventractor.domain.Address</class>
        <class>pl.michalmech.eventractor.domain.City</class>
        <class>pl.michalmech.eventractor.domain.Country</class>

        <properties>
            <property name="hibernate.hbm2ddl.auto" value="validate" />
            <property name="hibernate.show_sql" value="true" />
        </properties>
    </persistence-unit>

</persistence>

y funciona.

Pero cuando @Entity elementos de <class> , la aplicación no ve entidades (todas las clases están anotadas con @Entity ).

¿Hay algún mecanismo automático para @Entity clases @Entity ?




No estoy seguro de que esta solución esté dentro de las especificaciones, pero creo que puedo compartirla con otras.

árbol de dependencia

my-entities.jar

Contiene clases de entidad solamente. No META-INF/persistence.xml .

my-services.jar

Depende de my-entities . Contiene EJB solo.

my-resources.jar

Depende de my-services . Contiene clases de recursos y META-INF/persistence.xml .

problemas

  • ¿Cómo podemos especificar el elemento <jar-file/> en my-resources como el nombre del artefacto postfixed de una dependencia transitoria?
  • ¿Cómo podemos sincronizar el valor del elemento <jar-file/> y el de la dependencia transitoria real?

solución

dependencia directa (¿redundante?) y filtrado de recursos

Puse una propiedad y una dependencia en my-resources/pom.xml .

<properties>
  <my-entities.version>x.y.z-SNAPSHOT</my-entities.version>
</properties>
<dependencies>
  <dependency>
    <!-- this is actually a transitive dependency -->
    <groupId>...</groupId>
    <artifactId>my-entities</artifactId>
    <version>${my-entities.version}</version>
    <scope>compile</scope> <!-- other values won't work -->
  </dependency>
  <dependency>
    <groupId>...</groupId>
    <artifactId>my-services</artifactId>
    <version>some.very.sepecific</version>
    <scope>compile</scope>
  </dependency>
<dependencies>

Ahora prepara persistence.xml para ser filtrado

<?xml version="1.0" encoding="UTF-8"?>
<persistence ...>
  <persistence-unit name="myPU" transaction-type="JTA">
    ...
    <jar-file>lib/my-entities-${my-entities.version}.jar</jar-file>
    ...
  </persistence-unit>
</persistence>

Complemento Maven Enforcer

Con la regla de dependencyConvergence convergencia, podemos asegurar que la versión de my-entities es la misma tanto en directo como transitiva.

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-enforcer-plugin</artifactId>
  <version>1.4.1</version>
  <executions>
    <execution>
      <id>enforce</id>
      <configuration>
        <rules>
           <dependencyConvergence/>
        </rules>
      </configuration>
      <goals>
        <goal>enforce</goal>
      </goals>
    </execution>
  </executions>
</plugin>



Para aquellos que ejecutan JPA en Spring, desde la versión 3.1 en adelante, puede establecer la propiedad packagesToScan bajo LocalContainerEntityManagerFactoryBean y deshacerse de persistence.xml por completo.

Aquí está el bajo-abajo




Hibernate no es compatible con <exclude-unlisted-classes>false</exclude-unlisted-classes> en SE, (otro cartel menciona que esto funciona con TopLink y EclipseLink).

Hay herramientas que generarán automáticamente la lista de clases en persistence.xml, por ejemplo, el asistente Importar esquema de base de datos en IntelliJ. Una vez que tenga las clases iniciales de su proyecto en persistence.xml, debería ser simple agregar / eliminar clases individuales a mano a medida que avanza su proyecto.




No estoy seguro de si está haciendo algo similar a lo que estoy haciendo, pero estoy generando una carga de Java fuente de un XSD usando JAXB en un componente separado usando Maven. Digamos que este artefacto se llama "modelo base"

Quería importar este artefacto que contiene el origen de Java y ejecutar Hibernate sobre todas las clases en mi jar de artefacto "base-model" y no especificarlo explícitamente. Estoy agregando "modelo base" como una dependencia para mi componente de hibernación, pero el problema es la etiqueta en persistence.xml solo le permite especificar rutas absolutas.

La forma en que lo solucioné es copiar mi dependencia de jar "modelo base" explícitamente en mi directorio de destino y también quitarle la versión. Entonces, si construyo mi artefacto "base-model", generaré "base-model-1.0-SNAPSHOT.jar", el paso copy-resources lo copiará como "base-model.jar".

Entonces en tu pom para el componente de hibernación:

            <!-- We want to copy across all our artifacts containing java code
        generated from our scheams. We copy them across and strip the version
        so that our persistence.xml can reference them directly in the tag
        <jar-file>target/dependency/${artifactId}.jar</jar-file> -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <version>2.5.1</version>
            <executions>
                <execution>
                    <id>copy-dependencies</id>
                    <phase>process-resources</phase>
                    <goals>
                        <goal>copy-dependencies</goal>
                    </goals>
                </execution>
            </executions>       
            <configuration>
                <includeArtifactIds>base-model</includeArtifactIds>
                <stripVersion>true</stripVersion>
            </configuration>        
        </plugin>

Luego llamo al plugin hibernate en la siguiente fase "process-classes":

            <!-- Generate the schema DDL -->
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>hibernate3-maven-plugin</artifactId>
            <version>2.2</version>

            <executions>
                <execution>
                    <id>generate-ddl</id>
                    <phase>process-classes</phase>
                    <goals>
                        <goal>hbm2ddl</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <components>
                    <component>
                        <name>hbm2java</name>
                        <implementation>annotationconfiguration</implementation>
                        <outputDirectory>/src/main/java</outputDirectory>
                    </component>
                </components>
                <componentProperties>
                    <persistenceunit>mysql</persistenceunit>
                    <implementation>jpaconfiguration</implementation>
                    <create>true</create>
                    <export>false</export>
                    <drop>true</drop>
                    <outputfilename>mysql-schema.sql</outputfilename>
                </componentProperties>
            </configuration>
        </plugin>

y finalmente en mi persistence.xml puedo establecer explícitamente la ubicación del contenedor de la siguiente manera:

<jar-file>target/dependency/base-model.jar</jar-file>

y agrega la propiedad:

<property name="hibernate.archive.autodetection" value="class, hbm"/>





Related