JPA使用替代“persistence.xml”
我知道这说明:
Persistence.createEntityManagerFactory("persistence-unit-name");
JPA持久性机制读取“persistence.xml”文件,查找名为“persistence-unit-name”的持久性单元,并基于它构造EntityManagerFactory。
我的问题是,如何强制JPA 采用与“persistence.xml”不同的文件 ? 例如,“persistence-test.xml”。
虽然单个JPA提供者可能提供一种方法,但没有标准化的JPA方法来实现这一点。 我建议使用标准方法为main和test设置不同的类路径。
例如,如果您使用Maven,并且您有两个META-INF/persistence.xml
文件,一个在src/main/resources
,另一个在src/test/resources
,则测试将在src/test/resources
选择一个,因为Maven将测试类/资源放在类路径中的主类/资源之前。 您可以轻松地将Ant配置为以类似方式工作。
如果您需要更高级的逻辑,请考虑使用Spring的JPA支持 。 它将让您处理高级情况,如集成多个persistence.xml文件 。
在EclipseLink中,您可以执行以下操作:
Properties pros = new Properties(); pros.setProperty(PersistenceUnitProperties.ECLIPSELINK_PERSISTENCE_XML, "META-INF/persistence-alternative.xml"); EntityManagerFactory factory = Persistence.createEntityManagerFactory("pu-name", pros);
我认为你不能。 这样做的好方法是:
- 创建一个工厂,它将读取您的
persistence-test.xml
并呈现Map
属性,以及。 - 调用
Persistence.createEntityManagerFactory(persistenceUnitName, Map properties)
。 这样,它从properties
映射中读取而不是从persistence.xml
读取。
如果您使用OpenEJB来推动测试,您可以使用您想要的任何JPA提供商完成您想要的任务。 类似的问题和相关答案:
如何指示Maven忽略我的main / resources / persistence.xml以支持test / …?
您可以在Spring中配置Hibernate而不使用persistence.xml,如下所示:
@Bean public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() { Map properties = new Hashtable<>(); properties.put("javax.persistence.schema-generation.database.action", "none"); HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter(); adapter.setDatabasePlatform("org.hibernate.dialect.MySQL5InnoDBDialect"); //you can change this if you have a different DB LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); factory.setJpaVendorAdapter(adapter); factory.setDataSource(this.springJpaDataSource()); factory.setPackagesToScan("package name"); factory.setSharedCacheMode(SharedCacheMode.ENABLE_SELECTIVE); factory.setValidationMode(ValidationMode.NONE); factory.setJpaPropertyMap(properties); return factory; }
由于您没有使用persistence.xml,因此您应该创建一个返回DataSource的bean,您可以在上面设置数据源的方法中指定它:
@Bean public DataSource springJpaDataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setUrl("jdbc:mysql://localhost/SpringJpa"); dataSource.setUsername("tomcatUser"); dataSource.setPassword("password1234"); return dataSource; }
然后在此配置文件上使用@EnableTransactionManagement
批注。 现在当您放置该注释时,您必须创建一个最后一个bean:
@Bean public PlatformTransactionManager jpaTransactionManager() { return new JpaTransactionManager( this.entityManagerFactoryBean().getObject()); }
现在,不要忘记对那些处理DB的方法使用@Transactional
Annotation。
最后,不要忘记在您的存储库中注入EntityManager
(此存储库类应该对其进行@Repository
注释)。
所以我们想要有两个独立的persistence.xml
文件。 一个应该只能通过生产配置读取,另一个应该用于测试。 我们的想法是重命名或隐藏生产文件。
战争解决方案
不要将persistence.xml
放在src\main\resources\META-INF\
。 而是将它放入src\main\webapp\WEB-INF\classes\META-INF\
。 这是文件所在的位置,在这个位置它不会被测试看到。
这个解决方案适合我在gradle环境中,但我希望其他人也会这样做。
Jar解决方案
将生产文件重命名为persistence-ee.xml
。 现在我们完成了测试配置。 对于生产,我们必须采用一些处理。 每个环境都有自己的方式,这就是我在gradle中的方式:
tasks.withType(Jar) { rename { fileName -> fileName == "persistence-ee.xml" ? "persistence.xml" : fileName; } }
在我的应用程序中,只有在部署时才需要生成persistence.xml
文件,即jar / war包中。 这些是这个文件可见的唯一地方。 没有双persistence
我无法启动我的数据库。 主要原因是使用了jta-data-source
,另一个是:2个独立的命名持久性单元。