Do I need <class> elements in persistence.xml?
Asked Answered
E

12

115

I have very simple persistance.xml file:

<?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>

and it works.

But when I remove <class> elements application doesn't see entities (all classes are annotated with @Entity).

Is there any automatic mechanism to scan for @Entity classes?

Eba answered 22/11, 2009 at 22:57 Comment(0)
M
81

The persistence.xml has a jar-file that you can use. From the Java EE 5 tutorial:

<persistence>
    <persistence-unit name="OrderManagement">
        <description>This unit manages orders and customers.
            It does not rely on any vendor-specific features and can
            therefore be deployed to any persistence provider.
        </description>
        <jta-data-source>jdbc/MyOrderDB</jta-data-source>
        <jar-file>MyOrderApp.jar</jar-file>
        <class>com.widgets.Order</class>
        <class>com.widgets.Customer</class>
    </persistence-unit>
</persistence>

This file defines a persistence unit named OrderManagement, which uses a JTA-aware data source jdbc/MyOrderDB. The jar-file and class elements specify managed persistence classes: entity classes, embeddable classes, and mapped superclasses. The jar-file element specifies JAR files that are visible to the packaged persistence unit that contain managed persistence classes, while the class element explicitly names managed persistence classes.

In the case of Hibernate, have a look at the Chapter2. Setup and configuration too for more details.

EDIT: Actually, If you don't mind not being spec compliant, Hibernate supports auto-detection even in Java SE. To do so, add the hibernate.archive.autodetection property:

<persistence-unit name="eventractor" transaction-type="RESOURCE_LOCAL">
  <!-- This is required to be spec compliant, Hibernate however supports
       auto-detection even in JSE.
  <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>
    <!-- Scan for annotated classes and Hibernate mapping XML files -->
    <property name="hibernate.archive.autodetection" value="class, hbm"/>

    <property name="hibernate.hbm2ddl.auto" value="validate" />
    <property name="hibernate.show_sql" value="true" />
  </properties>
</persistence-unit>
Mayorga answered 22/11, 2009 at 23:10 Comment(8)
I see, but the entities (@Entity) are in separate Maven project, so jar-file name can change on every build. I'm looking something to scan all in specific package or classpath. I'm just to lazy to type many, many <class> elements in persistence.xml file.Dispirited
On every build?! I won't even ask why but... you could use filtering to solve this.Mayorga
Not everyone exactly but I want to be resistant to changes.Dispirited
Ancient thread, I know, but have a look at the jpa-maven-plugin.Diatonic
You can use <mapping-file> element (which contains the list of the entities) in persistence.xml, so you can keep the same name of the used files and integrate them in the build of the referenced jars.Courtroom
<property name="hibernate.archive.autodetection" value="class" /> did not work with WildFly 8.2.1.Final (Hibernate 4.3.7.Final), but this: https://mcmap.net/q/112487/-autodetect-classes-in-hibernate-from-jarPatronizing
hibernate.archive.autodetection does not work for me on java se. hibernate 6.0.0.Alpha4Muller
There is a more recent fork for the jpa-maven-plugin here: github.com/iSnow/jpa-maven-pluginNgocnguyen
V
44

In Java SE environment, by specification you have to specify all classes as you have done:

A list of all named managed persistence classes must be specified in Java SE environments to insure portability

and

If it is not intended that the annotated persistence classes contained in the root of the persistence unit be included in the persistence unit, the exclude-unlisted-classes element should be used. The exclude-unlisted-classes element is not intended for use in Java SE environments.

(JSR-000220 6.2.1.6)

In Java EE environments, you do not have to do this as the provider scans for annotations for you.

Unofficially, you can try to set <exclude-unlisted-classes>false</exclude-unlisted-classes> in your persistence.xml. This parameter defaults to false in EE and truein SE. Both EclipseLink and Toplink supports this as far I can tell. But you should not rely on it working in SE, according to spec, as stated above.

You can TRY the following (may or may not work in SE-environments):

<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>
Vesicatory answered 22/11, 2009 at 23:41 Comment(1)
<exclude-unlisted-classes>false</exclude-unlisted-classes> did not work with WildFly 8.2.1.Final + Hibernate 4.3.7Patronizing
C
12

For those running JPA in Spring, from version 3.1 onwards, you can set packagesToScan property under LocalContainerEntityManagerFactoryBean and get rid of persistence.xml altogether.

Here's the low-down

Checkroom answered 27/8, 2012 at 6:19 Comment(1)
Worked for me! The scenario was spring 4 + hibernate + jpa2 + maven. JUnit testing didn't find my entities but with this setting it did the job.Sleeper
C
12

Do I need Class elements in persistence.xml?

No, you don't necessarily. Here is how you do it in Eclipse (Kepler tested):

Right click on the project, click Properties, select JPA, in the Persistence class management tick Discover annotated classes automatically.

enter image description here

Corcoran answered 7/2, 2014 at 7:58 Comment(4)
Why upvote? OP doesn't even mentions Eclipse and this answer doesn't show what this Eclipse feature does under the hood so that one could do that wihout an IDE.Yippie
@Artem Novikov: I find this to harsh since often the question arises out of different environments and here we want to help or give hints that are useful! (like for me) It's useful since Eclipse is a common IDE for developing like this and under the hood is not so important, but I guess it will include all relevant workspace projects (e.g. my project is depending on).Patronizing
#17951797 nice trick, but apparently it works only if entities end up in same classloader as the persistence.xmlPrint
@Corcoran Please show the persistence.xml that Eclipse generates.Tamarin
B
8

You can provide for jar-file element path to a folder with compiled classes. For example I added something like that when I prepared persistence.xml to some integration tests:

 <jar-file>file:../target/classes</jar-file>
Belsky answered 25/7, 2013 at 9:43 Comment(2)
This is what I was looking for!Schertz
Works with EclipseLink, too!Caoutchouc
M
8

for JPA 2+ this does the trick

 <jar-file></jar-file>

scan all jars in war for annotated @Entity classes

Maclean answered 18/9, 2014 at 9:2 Comment(5)
do you have more information about this? does this work by accident or is it written in the specification? Is it dependent on the implementation?Lerma
scanner is in class extending AbstractScannerImpl, hibernate - no idea if it's bug or feature, sorryMaclean
In Java SE with Hibernate 5.1.2.Final, this solution doesn't work. Hibernate expects a jar filename (java.lang.IllegalArgumentException: Unable to visit JAR file:).Strychninism
works! :) with WildFly 8.2.1.Final + Hibernate 4.3.7.FinalPatronizing
Thx man, searched a lot and this is the neatest solution available. Wildfly10 + Hibernate 5.0.7 working.Afraid
K
7

Hibernate doesn't support <exclude-unlisted-classes>false</exclude-unlisted-classes> under SE, (another poster mentioned this works with TopLink and EclipseLink).

There are tools that will auto-generate the list of classes to persistence.xml e.g. the Import Database Schema wizard in IntelliJ. Once you've got your project's initial classes in persistence.xml it should be simple to add/remove single classes by hand as your project progresses.

Killebrew answered 30/8, 2010 at 5:15 Comment(1)
Auto detection of entities in Java SE is just not part of JPA. Applications relying on this are not portable.Mayorga
W
4

Not sure if you're doing something similar to what I am doing, but Im generating a load of source java from an XSD using JAXB in a seperate component using Maven. Lets say this artifact is called "base-model"

I wanted to import this artifact containing the java source and run hibernate over all classes in my "base-model" artifact jar and not specify each explicitly. Im adding "base-model" as a dependency for my hibernate component but the trouble is the tag in persistence.xml only allows you to specify absolute paths.

The way I got round it is to copy my "base-model" jar dependency explictly to my target dir and also strip the version of it. So whereas if I build my "base-model" artifact it generate "base-model-1.0-SNAPSHOT.jar", the copy-resources step copies it as "base-model.jar".

So in your pom for the hibernate component:

            <!-- 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>

Then I call the hibernate plugin in the next phase "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>

and finally in my persistence.xml I can explicitly set the location of the jar thus:

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

and add the property:

<property name="hibernate.archive.autodetection" value="class, hbm"/>
Wayzgoose answered 27/9, 2012 at 22:22 Comment(0)
S
3

It's not a solution but a hint for those using Spring:

I tried to use org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean with setting persistenceXmlLocation but with this I had to provide the <class> elements (even if the persistenceXmlLocation just pointed to META-INF/persistence.xml).

When not using persistenceXmlLocation I could omit these <class> elements.

Straighten answered 9/8, 2011 at 9:33 Comment(2)
I used persistenceXmlLocation property in my LocalContainerEntityManagerFactoryBean settings. But all the queries are working even if I omit the <class> elements. Its on a Spring/Hibernate/Maven application. But in you hint you say that "When not using persistenceXmlLocation I could omit these <class> elements." but its the other way around for me.Valet
@Ethan you're right, because persistenceXmlLocation overrides packagesToScan - if you look in the sources. So don't use it, when using packagesToScan.Yippie
K
2

I'm not sure this solution is under the spec but I think I can share for others.

dependency tree

my-entities.jar

Contains entity classes only. No META-INF/persistence.xml.

my-services.jar

Depends on my-entities. Contains EJBs only.

my-resources.jar

Depends on my-services. Contains resource classes and META-INF/persistence.xml.

problems

  • How can we specify <jar-file/> element in my-resources as the version-postfixed artifact name of a transient dependency?
  • How can we sync the <jar-file/> element's value and the actual transient dependency's one?

solution

direct (redundant?) dependency and resource filtering

I put a property and a dependency in 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>

Now get the persistence.xml ready for being filtered

<?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>

Maven Enforcer Plugin

With the dependencyConvergence rule, we can assure that the my-entities' version is same in both direct and transitive.

<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>
Kelleher answered 18/8, 2016 at 2:53 Comment(0)
A
0

Not necessarily in all cases.

I m using Jboss 7.0.8 and Eclipselink 2.7.0. In my case to load entities without adding the same in persistence.xml, I added the following system property in Jboss Standalone XML:

<property name="eclipselink.archive.factory" value="org.jipijapa.eclipselink.JBossArchiveFactoryImpl"/>

Accelerate answered 26/8, 2019 at 11:26 Comment(0)
G
0

I solved this issue by linking the jar file as below.

<persistence-unit name="omPersistenceUnit" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
      <jar-file>file://home/xxxx/yyyy.core-lib-1.2.0-SNAPSHOT.jar</jar-file>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties>
        <property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect" />
        <property name="hibernate.show_sql" value="false" />
        <property name="hibernate.hbm2ddl.auto" value="none" />
        <property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.EhCacheRegionFactory" />
        <property name="hibernate.cache.use_second_level_cache" value="true" />
        <property name="hibernate.cache.use_query_cache" value="true" />
    </properties>
  </persistence-unit>
Germiston answered 5/4, 2023 at 17:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.