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

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

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

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

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

这个解决方案对我有用

  Thread.currentThread().setContextClassLoader(new ClassLoader() { @Override public Enumeration 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"); 

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 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 getResources(String name) throws IOException { if (name.equals("META-INF/persistence.xml")) { return Collections.enumeration(Arrays.asList(alternativePersistenceXmlUrl)); } return super.getResources(name); } }; } 

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

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

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

 URL puRootUrl = computePURootURL(descUrl, descriptorPath); 

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

那么,假设我们在/home/Smith/program/some-folder/persistence.xml上有文件,那么我们有:

 Thread currentThread = Thread.currentThread(); ClassLoader previousClassLoader = currentThread.getContextClassLoader(); Thread.currentThread().setContextClassLoader(new ClassLoader(previousClassLoader) { @Override public Enumeration 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 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。