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
Is it possible to have persistence.xml in a location other than META-INF?
提问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.PersistenceUnitProcessor
on line 236
we see the following code:
在org.eclipse.persistence.internal.jpa.deployment.PersistenceUnitProcessor
上line 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 descriptorPath
to puRootUrl
.
EclipseLink 使用此代码来计算persistence.xml 路径的根URL。这非常重要,因为最终路径将通过添加descriptorPath
到puRootUrl
.
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:
细节:
- Pay attention that when creating new class loader I pass there previous classloader otherwise it doesn't work.
- We set property
eclipselink.persistencexml
. If we don't do that then default descriptorPath will be equal toMETA-INF/persistence.xml
and we would need to keep our persistence.xml on/home/Smith/program/META-INF/persistence.xml
to be found.
- 请注意,在创建新的类加载器时,我会传递以前的类加载器,否则它不起作用。
- 我们设置属性
eclipselink.persistencexml
。如果我们不这样做,那么默认的descriptorPath 将等于META-INF/persistence.xml
,我们需要保持我们的persistence.xml/home/Smith/program/META-INF/persistence.xml
才能被找到。