有一个单独的 persistence.xml 文件用于测试

Having a separate persistence.xml file for testing

受到这个问题的启发:JPA using alternative "persistence.xml"我创建了一个如下所示的文件夹结构:

两者 persistence-units 具有相同的名称,因为我的目标是测试应该选择 test-folder 中的那个,否则应该使用“normal”。 上述问题的答案声称 "Maven puts test classes / resources ahead of main classes / resources in the classpath" 然而,这不是我所看到的。如果 persistence-units 具有相同的名称,它将始终使用 src/main/resources/...

中的那个

如有任何解决此问题的建议,我们将不胜感激

原来引用的问题好像回复错了?所以我最终采用了另一种策略,如下所示: 我有一个静态 class,它总是用于获取要使用的持久性单元的名称。

public class PU_Name
{
  private static String puName = "pu_delopment";

  public static String getPU_Name(){
    return puName;
  }
  public static void setPU_Name(String name){
    puName = name;
  }
}

每当我创建一个 EntityManager 时,我都会按照下面的草图进行操作。在此示例中,它更改名称以使用 "test persistence-unit"

@BeforeClass
public static void initClass(){
  PU_Name.setPU_Name("puTest");
  emf = Persistence.createEntityManagerFactory(PU.getPU_Name());
}

真正的 class 多一点 "advanced" 因为它还检测到 OPENSHIFT 环境变量的存在并转移到使用 "production" 数据库的持久性单元。

我也有同样的情况,在测试和主要资源中有两个persistence.xml。始终无法在测试 classpath 中检测到唯一的 PU 名称,即使我确保 hiberante-entitymanager 并且测试文件位于 classpath.

最后我寻求解决方案:以编程方式构造 entityManagerFactory,如下所示:create entity manager programmatically without persistence file.

所以我做了非常相似的事情:

    @BeforeClass
    public static void prepare() {
        Map<String, Object> configOverrides = new HashMap<>();
        configOverrides.put("hibernate.connection.driver_class", "org.h2.Driver");
        configOverrides.put("hibernate.connection.url", "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1");
        configOverrides.put("hibernate.connection.username", "sa");
        configOverrides.put("hibernate.connection.password", "sa");
        configOverrides.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
        configOverrides.put("hibernate.show_sql", "true");
        configOverrides.put("hibernate.hbm2ddl.auto", "validate");
        //factory = new HibernatePersistence().createContainerEntityManagerFactory(
        //        new CustomPersistenceUnitInfo(), configOverrides
        //);
        factory = Persistence.createEntityManagerFactory("test");
        assertNotNull(factory);
    }
...
    private static class CustomPersistenceUnitInfo implements PersistenceUnitInfo {

        @Override
        public String getPersistenceUnitName() {
            return "test";
        }

        @Override
        public String getPersistenceProviderClassName() {
            return "org.hibernate.jpa.HibernatePersistenceProvider";
 // <------------note here: this is wrong!
        }

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

        @Override
        public DataSource getJtaDataSource() {
            return null;
        }

        @Override
        public DataSource getNonJtaDataSource() {
            return null;
        }

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

        @Override
        public List<URL> getJarFileUrls() {
            try {
                return Collections.list(this.getClass()
                        .getClassLoader()
                        .getResources(""));
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        }

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

        @Override
        public List<String> getManagedClassNames() {
            return Arrays.asList(
                    "com.app.Entity1",
                    "com.app.Entity2"
            );
        }

        @Override
        public boolean excludeUnlistedClasses() {
            return true;
        }

        @Override
        public SharedCacheMode getSharedCacheMode() {
            return null;
        }

        @Override
        public ValidationMode getValidationMode() {
            return null;
        }

        @Override
        public Properties getProperties() {
            return null;
        }

        @Override
        public String getPersistenceXMLSchemaVersion() {
            return null;
        }

        @Override
        public ClassLoader getClassLoader() {
            return null;
        }

        @Override
        public void addTransformer(final ClassTransformer classTransformer) {

        }

        @Override
        public ClassLoader getNewTempClassLoader() {
            return null;
        }
    }


但是后来,我发现还是returnnull。为什么?然后我在com.hibernate.ejb.HibernatePersistenceclass中发现,provider不应该是com.hibernate.jpa.HibernatePersistenceProvider,而是com.hibernate.ejb.HibernatePersistenc。 class HibernatePersistenceProvider 甚至不在我的 class 路径中。

Ejb3Configuration.class中:

        integration = integration != null ? Collections.unmodifiableMap(integration) : CollectionHelper.EMPTY_MAP;
        String provider = (String)integration.get("javax.persistence.provider");
        if (provider == null) {
            provider = info.getPersistenceProviderClassName();
        }

        if (provider != null && !provider.trim().startsWith(IMPLEMENTATION_NAME)) { // private static final String IMPLEMENTATION_NAME = HibernatePersistence.class.getName(); which, is, "com.hibernate.ejb.HibernatePersistence"
            LOG.requiredDifferentProvider(provider);
            return null;
        } else {

所以我回到第一个解决方案,更改提供商名称,现在可以了。