2012-12-05 64 views
10

我想要我的應用程序的conf文件夾中的persistence.xml。我如何告訴Persistence.createEntityManagerFactory它應該從那裏讀取它?是否可以在META-INF以外的地方使用persistence.xml?

+1

如果您使用的是Spring,至少可以通過使用org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean並指定屬性persistenceXmlLocation指向該文件來實現。 – RJo

+0

哪個JPA實現? DataNucleus JPA允許您指定它的存儲位置。也許其他人也是。明顯不是JPA規範的一部分 – DataNucleus

回答

2

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

+0

看來我找到了一個可行的解決方案,請看看我的回答 –

+0

是的,這是對的,很棒的工作! –

12

如果您正在使用的EclipseLink您可以設置與持久性單元屬性persistence.xml中的位置,「的EclipseLink .persistencexml」。

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

當persistence.xml位於jar外部時,例如當persistence.xml路徑爲'/ home/foo/downloads/persistence.xml'時,可以使用此解決方案嗎? –

+0

我嘗試過不同的變體,無法使其工作。從這裏http://www.eclipse.org/eclipselink/documentation/2.4/jpa/extensions/p_persistencexml.htm'目前,該屬性僅用於規範模型生成器。將來,它可用於定製編織和應用程序引導。' –

3

該解決方案爲我

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

你能詳細解釋一下你的答案嗎?我不太瞭解Spring內部插件,需要添加上面的代碼片段。 – sloven

+0

在春季我會考慮http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/new-in-3.1.html#new-in-3.1-jpa-without- XML首先 –

+0

我會使用你的解決方案,但它不適用於我的配置:Java 1.6.0_24,EclipseLink 2.3.2。我有一個異常「javax.persistence.PersistenceException:沒有名爲XXX的EntityManager的持久性提供者」。你知道爲什麼嗎? – njames

0

類加載器可以爲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); 
      } 
     }; 
    } 

它應該工作。在某些測試等條件下適用於我。 請這是一個黑客,不應該在生產中使用。

0

我的解決方案是用於EclipseLink 2.7.0和Java 9,它是修改和@Evgeniy Dorofeev答案的詳細版本。

org.eclipse.persistence.internal.jpa.deployment.PersistenceUnitProcessorline 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。如果我們不這樣做,那麼默認描述符路徑將等於META-INF/persistence.xml,我們需要保持我們的persistence.xml找到/home/Smith/program/META-INF/persistence.xml