【问题标题】:JPA using alternative "persistence.xml"JPA 使用替代“persistence.xml”
【发布时间】:2011-11-05 20:50:59
【问题描述】:

我知道有说明:

Persistence.createEntityManagerFactory("persistence-unit-name");

JPA持久化机制读取“persistence.xml”文件,寻找名为“persistence-unit-name”的持久化单元,并基于它构造EntityManagerFactory。

我的问题是,如何强制 JPA 获取与“persistence.xml”不同的文件?例如,“persistence-test.xml”。

【问题讨论】:

  • 因为我想使用替代的 persistence.xml 进行测试。
  • @edutesoy 您可以在同一个 persistence.xml 文件中拥有多个持久性单元,并在测试中使用适当的一个。
  • 我在 Maven 中遇到了一些错误,有时(随机)在测试期间选择了错误的 persistence.xml 文件。

标签: java hibernate jpa ejb


【解决方案1】:

没有标准化的 JPA 方法来执行此操作,尽管个别 JPA 提供者可能会提供一种方法。我建议使用标准方法为 main 和 test 设置不同的类路径。

例如,如果您使用 Maven,并且您有两个 META-INF/persistence.xml 文件,一个在 src/main/resources 中,一个在 src/test/resources 中,测试将选择 src/test/resources 中的一个,因为 Maven 放置了测试类/资源在类路径中的主要类/资源之前。您可以轻松地将 Ant 配置为以类似的方式工作。

如果您需要更高级的逻辑,请考虑使用Spring's JPA support。它会让你处理像integrating multiple persistence.xml files这样的高级情况。

【讨论】:

  • persistence.xml 文件仅在我运行 mvn test 命令时才从 src/test/resources 使用。一旦你运行 mvn install,你的测试也会运行,并且文件是从 src/main/resources 中获取的,这会导致问题。
  • @Alexandr 这不是 Maven 的工作方式。当您触发生命周期阶段时,将执行直到并包括该阶段的所有阶段。测试阶段的执行是完全一样的,与你启动 Maven 是用 test 还是 install 无关。见maven.apache.org/guides/introduction/…
【解决方案2】:

在 EclipseLink 中,您可以执行以下操作:

Properties pros = new Properties();

pros.setProperty(PersistenceUnitProperties.ECLIPSELINK_PERSISTENCE_XML, 
                 "META-INF/persistence-alternative.xml");


EntityManagerFactory factory = 
    Persistence.createEntityManagerFactory("pu-name", pros);

【讨论】:

    【解决方案3】:

    我不认为你可以。这样做的漫长方法是:

    【讨论】:

      【解决方案4】:

      所以我们想要有 2 个独立的 persistence.xml 文件。一个只能由生产配置读取,另一个用于测试。这个想法是重命名或隐藏生产文件。

      战争解决方案

      不要将persistence.xml 放入src\main\resources\META-INF\。而是将其放入src\main\webapp\WEB-INF\classes\META-INF\。那是文件应该在的位置,在这个位置它不会被测试看到。

      此解决方案在 gradle 环境中适用于我,但我希望其他人也可以。

      罐子解决方案

      将生产文件重命名为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 个独立的命名持久单元。

      【讨论】:

      • 你救了我的命!我已经为这个问题苦苦挣扎了一个星期,上帝只知道如果我没有看到你的答案,我会苦苦挣扎多久。在我将“测试”persistence.xml 移动到“src\main\webapp\WEB-INF\classes\META-INF”之后,它对我很有用。非常非常非常感谢!
      【解决方案5】:

      如果您使用 OpenEJB 来驱动您的测试,那么您可以使用任何您想要的 JPA 提供程序来做您想做的事。类似的问题和相关答案在这里:

      How to instruct Maven to ignore my main/resources/persistence.xml in favor of test/...?

      【讨论】:

        【解决方案6】:

        你可以像这样在 Spring 中完全不使用 persistence.xml 来配置 Hibernate:

        @Bean
        public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean()
        {
        Map<String, Object> 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,你应该创建一个bean,它返回你在上面设置数据源的方法中指定的DataSource:

        @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 注释。

        最后,不要忘记在你的存储库中注入EntityManager(这个存储库类应该有@Repository 注释)。

        【讨论】:

        • 如果您需要在生产服务器上使用 jtaDataSource,我不会这样做。然后你需要persistence.xml,hibernate会在测试期间找到并处理它。
        猜你喜欢
        • 2012-05-01
        • 2010-11-11
        • 1970-01-01
        • 2014-03-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-11-25
        • 2012-01-06
        相关资源
        最近更新 更多