【问题标题】:Could not open JPA EntityManager for transaction (using LocalContainerEntityManagerFactoryBean)无法打开 JPA EntityManager 进行事务处理(使用 LocalContainerEntityManagerFactoryBean)
【发布时间】:2019-05-09 15:29:52
【问题描述】:

我在运行测试时看到了这个。我确信正在建立(或尝试)数据库连接,因为当我没有包含密码时它最初给出了错误,然后它抱怨,因为该名称的数据库不存在。一旦我创建了数据库,它就会给我这个错误:

$ mvn clean test
...
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 2.317 sec <<< FAILURE!
testGetAccounts(com.oreilly.repositories.JpaAccountRepositoryTest)  Time elapsed: 0.104 sec  <<< ERROR!
org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is java.lang.NoSuchMethodError: org.hibernate.Session.getFlushMode()Lorg/hibernate/FlushMode;
    at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:431)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373)
    at org.springframework.test.context.transaction.TransactionContext.startTransaction(TransactionContext.java:98)
...

下面是我的配置文件:

@Configuration
@ComponentScan(basePackages = "com.oreilly")
@PropertySource("classpath:prod.properties")
@EnableTransactionManagement
public class AppConfig {
    @Autowired
    private Environment env;

    @Bean
    public DataSource dataSource() {
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName(env.getProperty("db.driver"));
        dataSource.setUrl(env.getProperty("db.url"));
        dataSource.setUsername(env.getProperty("db.user"));
        dataSource.setPassword(env.getProperty("db.pass"));
        return dataSource;
    }

    @Bean
    public JpaVendorAdapter jpaVendorAdapter() {
        HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
        adapter.setShowSql(true);
        adapter.setGenerateDdl(true);
        adapter.setDatabase(Database.MYSQL);
        return adapter;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(
            DataSource dataSource, JpaVendorAdapter jpaVendorAdapter) {

        Properties props = new Properties();
        props.setProperty("hibernate.format_sql", String.valueOf(true));

        LocalContainerEntityManagerFactoryBean emf =
                new LocalContainerEntityManagerFactoryBean();
        emf.setDataSource(dataSource);
        emf.setPackagesToScan("com.oreilly.entities");
        emf.setJpaVendorAdapter(jpaVendorAdapter);
        emf.setJpaProperties(props);

        return emf;
    }

    @Bean
    public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
        return new JpaTransactionManager(emf);
    }

    @Bean
    public BeanPostProcessor persistenceTranslation() {
        return new PersistenceExceptionTranslationPostProcessor();
    }

}

如果有帮助,很高兴包含更多代码。我可以使用相同的凭据成功登录到我的 mysql 控制台,并且数据库在那里:

$ mysql -uroot -p spring
Enter password: 
...

mysql> show databases;
+-----------------------+
| Database              |
+-----------------------+
| ...                   |
| spring                |
+-----------------------+
10 rows in set (0.00 sec)

我正在关注一个对 JPA 来说非常新的 Safari 书籍视频课程。几乎只是拿走了他们的代码,但仍然出现错误,因此很难知道我应该质疑代码的哪一部分。

更新

这是我正在运行的测试。我现在只运行一项测试,否则我的控制台会被错误淹没。我也会在下面添加存储库代码:

JpaAccountRepositoryTest.java

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class)
@Transactional
public class JpaAccountRepositoryTest {

    @Autowired
    private AccountRepository repository;

    @Test
    public void testGetAccounts() throws Exception {
        List<Account> accounts = repository.getAccounts();
        assertThat(accounts.size(), is(3));
    }

//    @Test
//    public void testGetAccount() throws Exception {
//       ...

JpaAccountRepository.java

@Repository
public class JpaAccountRepository implements AccountRepository {
    private long nextId = 4;

    @PersistenceContext
    private EntityManager entityManager;

    public List<Account> getAccounts() {
        return entityManager.createQuery("select a from Account a", Account.class)
                .getResultList();
    }

    public Account getAccount(Long id) {
        ...

【问题讨论】:

  • 你能提供你的测试代码吗?
  • 当然,已添加。如果有帮助,我还添加了它正在测试的存储库。
  • 能否也包含您的依赖关系图。 (如果你使用的是 maven,则为 pom)

标签: java spring jpa hibernate-entitymanager


【解决方案1】:

这个问题看起来像一个 Jar 冲突。您可以尝试降级到 hibernate-core-5.1.0。 如果没有,请使用 maven-enforcer 插件创建依赖收敛分析,以确保您不会与传递依赖发生冲突。

【讨论】:

    【解决方案2】:

    你为什么在测试类中使用@Transaction。使用可以使用@DataJpaTest@SpringBootTest注解,大多首选@DataJpaTest.

    【讨论】:

      【解决方案3】:

      spring JpaTransactionManager 需要一些其他版本的 Hibernate, 因为 Session.getFlushMode() 似乎不见了。

      根据this 的回答,如果您使用的是旧版本的 Spring,他们建议将 Hibernate 降级为 hibernate-core-5.1.0.Final.jar。

      检查您的依赖关系图,看看是否有东西覆盖了 Hibernate 版本。

      【解决方案4】:

      替换

      @Autowired
      private AccountRepository repository;
      

      @Autowired
      private JpaAccountRepository repository;
      

      在您的 JpaAccountRepositoryTest 类中

      【讨论】:

      • 感谢您的回复。像JpaAccountRepository implements AccountRepository 一样重要吗?无论如何,我试过但仍然给我一个错误:Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 2.407 sec &lt;&lt;&lt; FAILURE! testGetAccounts(com.oreilly.repositories.JpaAccountRepositoryTest) Time elapsed: 0.007 sec &lt;&lt;&lt; ERROR! org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.oreilly.repositories.JpaAccountRepositoryTest': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationExce...
      猜你喜欢
      • 2018-04-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-17
      • 2015-11-19
      • 2020-05-27
      • 2018-03-13
      • 2022-08-22
      相关资源
      最近更新 更多