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

眉间皱痕 提交于 2019-11-27 16:31:14

问题


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?


回答1:


The createEntityManagerFactory methods search for persistence.xml files within the META-INF directory of any CLASSPATH element. if your CLASSPATH contains the conf directory, you could place an EntityManagerFactory definition in conf/META-INF/persistence.xml




回答2:


If you are using EclipseLink you can set the persistence.xml location with the persistence unit property, "eclipselink.persistencexml".

properties.put("eclipselink.persistencexml", "/org/acme/acme-persistence.xml");
EntityManagerFactory factory = Persistence.createEntityManagerFactory("acme", properties);



回答3:


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");



回答4:


The ClassLoader may be a URLClassLoader, so try it this way:

        final URL alternativePersistenceXmlUrl = new File("conf/persistence.xml").toURI().toURL();

    ClassLoader output;

    ClassLoader current = Thread.currentThread().getContextClassLoader();

    try{

        URLClassLoader parent = (URLClassLoader)current;

        output = new URLClassLoader(parent.getURLs(), parent){

            @Override
            public Enumeration<URL> getResources(String name) throws IOException {

                if (name.equals("META-INF/persistence.xml")) {

                    return Collections.enumeration(Arrays.asList(alternativePersistenceXmlUrl));
                }

                return super.getResources(name);
            }
        };
    }catch(ClassCastException ignored) {

        output = new ClassLoader() {

            @Override
            public Enumeration<URL> getResources(String name) throws IOException {

                if (name.equals("META-INF/persistence.xml")) {

                    return Collections.enumeration(Arrays.asList(alternativePersistenceXmlUrl));
                }

                return super.getResources(name);
            }
        };
    }

It should work. Works for me under certain test etc conditions. Please this is a hack and should not be used in production.




回答5:


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.


来源:https://stackoverflow.com/questions/13717324/is-it-possible-to-have-persistence-xml-in-a-location-other-than-meta-inf

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!