Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to have persistence.xml in a location other than META-INF?

I want to have my persistence.xml in conf folder of my app. How can I tell Persistence.createEntityManagerFactory that it should read it from there?

like image 701
Evgeniy Dorofeev Avatar asked Dec 05 '12 06:12

Evgeniy Dorofeev


People also ask

Where should persistence xml be located?

xml should be put in the EJB JAR's META-INF directory. If you package the persistence unit as a set of classes in a WAR file, persistence. xml should be located in the WAR file's WEB-INF/classes/META-INF directory.

Where does persistence xml go in spring boot?

Spring Boot will not search for or use a META-INF/persistence. xml by default. If you prefer to use a traditional persistence. xml , you need to define your own @Bean of type LocalEntityManagerFactoryBean (with an ID of 'entityManagerFactory') and set the persistence unit name there.

Could not find any meta-INF persistence xml file in the classpath in Maven?

You need to move persistence. xml to a location on your app server's class path. For a Maven project, that is typically in the src/main/resources folder. Check the Hibernate documentation to see if Hibernate expects the file to be in a sub-folder, or if putting it in the root of the classpath is OK.

Can we have multiple persistence xml?

xml files. Have multiple persistence units in one persistence.


2 Answers

My solution is for EclipseLink 2.7.0 and Java 9 and it is modified and detailed version of @Evgeniy Dorofeev answer.

In org.eclipse.persistence.internal.jpa.deployment.PersistenceUnitProcessor on line 236 we see the following code:

URL puRootUrl = computePURootURL(descUrl, descriptorPath);

This code is used by EclipseLink to compute root url of the persistence.xml path. That's very important because final path will be made by adding descriptorPath to puRootUrl.

So, let's suppose we have file on /home/Smith/program/some-folder/persistence.xml, then we have:

Thread currentThread = Thread.currentThread();
ClassLoader previousClassLoader = currentThread.getContextClassLoader();
Thread.currentThread().setContextClassLoader(new ClassLoader(previousClassLoader) {
    @Override
    public Enumeration<URL> getResources(String name) throws IOException {
        if (name.equals("some-folder/persistence.xml")) {
            URL url = new File("/home/Smith/program/some-folder/persistence.xml").toURI().toURL();
            return Collections.enumeration(Arrays.asList(url));
        }
        return super.getResources(name);
    }

});
Map<String, String> properties = new HashMap<>();
properties.put("eclipselink.persistencexml", "some-folder/persistence.xml");
try {
    entityManagerFactory = Persistence.createEntityManagerFactory("unit-name", properties);
} catch (Exception ex) {
    logger.error("Error occured creating EMF", ex);
} finally {
    currentThread.setContextClassLoader(previousClassLoader);
}

Details:

  1. Pay attention that when creating new class loader I pass there previous classloader otherwise it doesn't work.
  2. We set property eclipselink.persistencexml. If we don't do that then default descriptorPath will be equal to META-INF/persistence.xml and we would need to keep our persistence.xml on /home/Smith/program/META-INF/persistence.xml to be found.
like image 190
Pavel_K Avatar answered Sep 27 '22 02:09

Pavel_K


This solution worked for me

    Thread.currentThread().setContextClassLoader(new ClassLoader() {
        @Override
        public Enumeration<URL> getResources(String name) throws IOException {
            if (name.equals("META-INF/persistence.xml")) {
                return Collections.enumeration(Arrays.asList(new File("conf/persistence.xml")
                        .toURI().toURL()));
            }
            return super.getResources(name);
        }
    });
    Persistence.createEntityManagerFactory("test");
like image 26
Evgeniy Dorofeev Avatar answered Sep 26 '22 02:09

Evgeniy Dorofeev