12

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

4

7 回答 7

13

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

properties.put("eclipselink.persistencexml", "/org/acme/acme-persistence.xml");
EntityManagerFactory factory = Persistence.createEntityManagerFactory("acme", properties);
于 2012-12-05T13:59:38.913 回答
7

这个解决方案对我有用

    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");
于 2012-12-21T06:17:58.383 回答
2

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

于 2012-12-05T06:34:58.960 回答
1

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

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

于 2016-08-27T14:45:30.780 回答
1

我的解决方案适用于 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。这非常重要,因为最终路径将通过添加descriptorPathpuRootUrl.

所以,假设我们有文件/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并且我们需要保持我们的persistence.xml 处于打开状态/home/Smith/program/META-INF/persistence.xml才能被找到。
于 2017-10-10T17:59:41.683 回答
0

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

  • Write your persistence.xml to the resources/META-INF/persistence.xml of the jar

    I had problem with this way: Java write .txt file in resource folder

  • Create META-INF folder in the jar directory and put your persistence.xml into it, then execute this command:

    jar uf $jarName META-INF/persistence.xml

    This command will replace META-INF/persistence.xml (your file) in the jar

    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

于 2021-01-04T13:52:52.133 回答
0

A solution by creating tweaked PersistenceUnitDescriptor.

import org.hibernate.jpa.boot.internal.ParsedPersistenceXmlDescriptor;
import org.hibernate.jpa.boot.internal.PersistenceXmlParser;
import org.hibernate.jpa.boot.spi.Bootstrap;
import org.hibernate.jpa.boot.spi.EntityManagerFactoryBuilder;


public class HibernateEntityManagerFactoryBuilder {

    public static final EntityManagerFactory build(URL xmlUrl) {
        final ParsedPersistenceXmlDescriptor xmlDescriptor = PersistenceXmlParser.locateIndividualPersistenceUnit(xmlUrl);
        final HibernatePersistenceUnitDescriptor hibernateDescriptor = new HibernatePersistenceUnitDescriptor(xmlDescriptor);
        final EntityManagerFactoryBuilder builder = Bootstrap.getEntityManagerFactoryBuilder(hibernateDescriptor, Collections.emptyMap(), (ClassLoader) null);
        final EntityManagerFactory factory = builder.build();
        return factory;
    }
    
    
    public static final EntityManagerFactory build(URL xmlUrl, final String name) {
        final ParsedPersistenceXmlDescriptor xmlDescriptor = PersistenceXmlParser.locateNamedPersistenceUnit(xmlUrl, name);
        if(xmlDescriptor == null) throw new RuntimeException("Persistence unit with name '"+name+ "' not found.");
        final HibernatePersistenceUnitDescriptor hibernateDescriptor = new HibernatePersistenceUnitDescriptor(xmlDescriptor);
        final EntityManagerFactoryBuilder builder = Bootstrap.getEntityManagerFactoryBuilder(hibernateDescriptor, Collections.emptyMap(), (ClassLoader) null);
        final EntityManagerFactory factory = builder.build();
        return factory;
    }
    
    public static void main(String[] args) {
        try {
            final EntityManagerFactory factory = build(new File("D:/ini/persistence.xml").toURI().toURL());
        } catch (Exception e) {e.printStackTrace();}
    }
}


public class HibernatePersistenceUnitDescriptor implements PersistenceUnitDescriptor {

    private final PersistenceUnitDescriptor descriptor;
    
    public HibernatePersistenceUnitDescriptor(PersistenceUnitDescriptor descriptor) {
        this.descriptor = descriptor;
    }

    @Override
    public URL getPersistenceUnitRootUrl() {
        return null;
    }

    @Override
    public String getName() {
        return descriptor.getName();
    }

    @Override
    public String getProviderClassName() {
        return descriptor.getProviderClassName();
    }

    @Override
    public boolean isUseQuotedIdentifiers() {
        return descriptor.isUseQuotedIdentifiers();
    }

    @Override
    public boolean isExcludeUnlistedClasses() {
        return descriptor.isExcludeUnlistedClasses();
    }

    @Override
    public PersistenceUnitTransactionType getTransactionType() {
        return descriptor.getTransactionType();
    }

    @Override
    public ValidationMode getValidationMode() {
        return descriptor.getValidationMode();
    }

    @Override
    public SharedCacheMode getSharedCacheMode() {
        return descriptor.getSharedCacheMode();
    }

    @Override
    public List<String> getManagedClassNames() {
        return descriptor.getManagedClassNames();
    }

    @Override
    public List<String> getMappingFileNames() {
        return descriptor.getMappingFileNames();
    }

    @Override
    public List<URL> getJarFileUrls() {
        return descriptor.getJarFileUrls();
    }

    @Override
    public Object getNonJtaDataSource() {
        return descriptor.getNonJtaDataSource();
    }

    @Override
    public Object getJtaDataSource() {
        return descriptor.getJtaDataSource();
    }

    @Override
    public Properties getProperties() {
        return descriptor.getProperties();
    }

    @Override
    public ClassLoader getClassLoader() {
        return descriptor.getClassLoader();
    }

    @Override
    public ClassLoader getTempClassLoader() {
        return descriptor.getTempClassLoader();
    }

    @Override
    public void pushClassTransformer(EnhancementContext enhancementContext) {
        descriptor.pushClassTransformer(enhancementContext);
        
    }

}
于 2021-11-30T11:04:35.653 回答