简体   繁体   中英

Having a separate persistence.xml file for testing

Inspired by this question: JPA using alternative "persistence.xml" I have created a folder structure as outlined below:

  • src/main/resources/META-INF/persistence.xml
  • src/test/resources/META-INF/persistence.xml

Both persistence-units have the same name, since my goal is that tests should pick up the one in the test-folder and otherwise the " normal " one should be used. The answer to the question above claims that "Maven puts test classes / resources ahead of main classes / resources in the classpath" This however is not what I see. If the persistence-units have the same name, it will always use the one in src/main/resources/ ...

Any suggestions for how to solve this problem would be appreciated

So it seems that the reply to the original quoted question was wrong? So I ended up with another strategy as sketched below: I have a static class, which are always used to fetch the name for the Persistence Unit to use.

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

Whenever I create an EntityManager I do it as sketched below. In this example it changes the name to use a "test persistence-unit"

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

The real class is a bit more "advanced" since it also detects the presence of an OPENSHIFT environment variable and shifts to the Persistence Unit that uses the "production" database up there.

I have the same situation, with two persistence.xml in test and main resources. Always cannot detect the unique PU name in test classpath, even when I ensure hiberante-entitymanager and the test file are on classpath.

At last I go for a solution: construct the entityManagerFactory programmatically, like here: create entity manager programmatically without persistence file .

So I did sth very similar:

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


But then, I found it still return null . Why? Then I found in com.hibernate.ejb.HibernatePersistence class, the provider should not be com.hibernate.jpa.HibernatePersistenceProvider , but com.hibernate.ejb.HibernatePersistenc . The class HibernatePersistenceProvider is not even among my classpath.

In 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 {

So I went back to the first solution, and change provider name, and now it works.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM