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

时间:2012-12-05 06:08:30

标签: java jpa persistence.xml

我希望将persistence.xml放在我的应用的conf文件夹中。我如何告诉Persistence.createEntityManagerFactory它应该从那里读取它?

6 个答案:

答案 0 :(得分:13)

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

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

答案 1 :(得分:6)

此解决方案适合我

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

答案 2 :(得分:2)

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

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

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

org.eclipse.persistence.internal.jpa.deployment.PersistenceUnitProcessor line 236上,我们看到以下代码:

URL puRootUrl = computePURootURL(descUrl, descriptorPath);

EclipseLink使用此代码计算persistence.xml路径的根URL。这非常重要,因为最终路径是将descriptorPath添加到puRootUrl

所以,我们假设我们在/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);
}

详细说明:

  1. 请注意,在创建新的类加载器时,我会传递前一个类加载器,否则它不起作用。
  2. 我们设置了属性eclipselink.persistencexml。如果我们不这样做,那么默认descriptorPath将等于META-INF/persistence.xml,我们需要保持我们的/home/Smith/program/META-INF/persistence.xml上的persistence.xml。

答案 5 :(得分:0)

我在程序启动时(在主函数的第一行)尝试了这些方法:

  • 将你的persistence.xml 写入jar 的resources/META-INF/persistence.xml

    这种方式有问题:Java write .txt file in resource folder

  • 在jar目录下创建META-INF文件夹并将你的persistence.xml放入其中,然后执行这个命令:

    jar uf $jarName META-INF/persistence.xml

    此命令将替换 jar 中的 META-INF/persistence.xml(您的文件)

    private fun persistence() {
        val fileName = "META-INF/persistence.xml"
        val jarName: String?
        val done = try {
            jarName = javaClass.protectionDomain.codeSource.location.path
            if (File(fileName).exists() && !jarName.isNullOrBlank()
                    && jarName.endsWith(".jar") && File(jarName).exists()) {
                Command().exec("jar uf $jarName META-INF/persistence.xml", timeoutSec = 30)
                true
            } else false
        } catch (e: Exception) {
            false
        }
        if (done) {
            logger.info { "$fileName exist and will be loaded :)" }
        } else {
            logger.info {
                "$fileName not exist in current folder so it will be read from .jar :(" +
                        " you can run: jar uf jarName.jar META-INF/persistence.xml"
            }
        }
    }

Running Command Line in Java