java 是否可以在 META-INF 以外的位置使用persistence.xml?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13717324/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 13:44:31  来源:igfitidea点击:

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

javajpapersistence.xml

提问by Evgeniy Dorofeev

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?

我想在我的应用程序的 conf 文件夹中有我的persistence.xml。我如何告诉 Persistence.createEntityManagerFactory 它应该从那里读取它?

采纳答案by Yogesh A Sakurikar

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

createEntityManagerFactory 方法在任何 CLASSPATH 元素的 META-INF 目录中搜索 persistence.xml 文件。如果您的 CLASSPATH 包含 conf 目录,您可以在 conf/META-INF/persistence.xml 中放置一个 EntityManagerFactory 定义

回答by James

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

如果您使用 EclipseLink,您可以使用持久性单元属性“eclipselink.persistencexml”设置 persistence.xml 位置。

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

回答by Evgeniy Dorofeev

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

回答by poshjosh

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

ClassLoader 可能是一个 URLClassLoader,所以试试这样:

        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.

它应该工作。在某些测试等条件下对我有用。请这是一个黑客,不应该在生产中使用。

回答by Pavel_K

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

我的解决方案适用于 EclipseLink 2.7.0 和 Java 9,它是@Evgeniy Dorofeev 答案的修改和详细版本。

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

org.eclipse.persistence.internal.jpa.deployment.PersistenceUnitProcessorline 236我们看到以下代码:

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 descriptorPathto puRootUrl.

EclipseLink 使用此代码来计算persistence.xml 路径的根URL。这非常重要,因为最终路径将通过添加descriptorPathpuRootUrl.

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

所以,假设我们有 file on /home/Smith/program/some-folder/persistence.xml,那么我们有:

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.xmland we would need to keep our persistence.xml on /home/Smith/program/META-INF/persistence.xmlto be found.
  1. 请注意,在创建新的类加载器时,我会传递以前的类加载器,否则它不起作用。
  2. 我们设置属性eclipselink.persistencexml。如果我们不这样做,那么默认的descriptorPath 将等于META-INF/persistence.xml,我们需要保持我们的persistence.xml/home/Smith/program/META-INF/persistence.xml才能被找到。