如何找到 Hibernate + Spring-JPA 的兼容版本对? (无法打开 JPA EntityManager 进行交易)

How to find compatible version pair of Hibernate + Spring-JPA? (Could not open JPA EntityManager for transaction)

SSCCE 在这里:https://github.com/dims12/TrySpringJpaPlusHibernate

我正在尝试 运行 Spring 没有 persistence.xml 的 JPA 并具有以下配置:

@Configuration
@ComponentScan
@ImportResource("classpath:data_source.xml")
@EnableJpaRepositories("org.inthemoon.train.chinese.repositories")
public class BaseConfig {
   @Autowired
   private DataSource dataSource;

   @Bean
   public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
      LocalContainerEntityManagerFactoryBean ans =
         new LocalContainerEntityManagerFactoryBean();
      ans.setDataSource(dataSource);
      ans.setJpaVendorAdapter(jpaVendorAdapter());
      ans.setPackagesToScan("org.inthemoon.train.chinese.data");
      return ans;
   }

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

   @Bean
   public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
      JpaTransactionManager ans = new JpaTransactionManager();
      ans.setEntityManagerFactory(emf);

      return ans;
   }

}

它导致以下异常

Exception in thread "main" org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is java.lang.NoSuchMethodError: org.hibernate.Session.getFlushMode()Lorg/hibernate/FlushMode;
...

P.S。有什么方法可以从第一次尝试配置 IoC 吗?

更新

我正在使用以下库:

compile group: 'org.hibernate', name: 'hibernate-core', version: '5.2.5.Final'

compile group: 'org.springframework.data', name: 'spring-data-jpa', version: '1.10.5.RELEASE'

更新 2

我尝试了 8 个不同版本的 hibernate-core 来构建 spring-jpa of 1.10.5.RELEASE.

5.2.15.2.6 的版本导致了相同的异常

NoSuchMethodError: org.hibernate.Session.getFlushMode()Lorg/hibernate/FlushMode;

版本 5.1.35.0.11 导致

ClassNotFoundException: org.hibernate.ejb.HibernateEntityManagerFactory

唯一导致更复杂的版本是 5.2.0。它导致

SchemaManagementException: Attempt to resolve foreign key metadata from JDBC metadata failed to find column mappings for foreign key named [FKLOK22W31RKBMIIC2J96T9LTCN

出现的问题:

1) 这是否意味着版本 5.2.01.10.5 兼容?

2) 不做实验怎么知道?

3) 这样猜版本正常吗?依赖管理工具的目的不就是为了避免这样的事情吗?如果 spring-data-jpa:1.10.5 依赖于 5.2.0 的休眠,那么为什么 POM 中没有描述?

更新 3

开箱即用示例:https://github.com/dims12/TrySpringJpaPlusHibernate

没用。

通常当你有这个异常时,这意味着你应该 hibernate-entitymanager 到你的 porm。如果你使用的是 Maven,你可以通过将它添加到你的 pom

<dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-entitymanager</artifactId>
   <version>${hibernate.version}</version>
</dependency>

我还使用通过 bean 定义我的数据源我没有像您那样使用自动装配注入它我不知道它是否可以那样工作。我宁愿这样

 @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/gescable");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
        return dataSource;
    }

你需要包括休眠吗? Spring data-jpa 据我所知包括所有必要的休眠组件,所以我不确定您为什么需要添加任何额外的休眠依赖项

我刚刚在我的项目中测试了这个版本:

<hibernate.version>5.2.5.Final</hibernate.version>
<version>1.10.5.RELEASE</version>

它对我有用。

我的配置文件是这样的:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "ge.shemo.repositories")
@EnableJpaAuditing
public class PersistenceConfig {

@Autowired
private Environment env;

@Value("${init-db:false}")
private String initDatabase;


@Bean
public PlatformTransactionManager transactionManager() {
    EntityManagerFactory factory = entityManagerFactory().getObject();
    return new JpaTransactionManager(factory);
}


@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
    LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();

    HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    vendorAdapter.setGenerateDdl(Boolean.FALSE);
    vendorAdapter.setShowSql(Boolean.FALSE);

    factory.setDataSource(dataSource());
    factory.setJpaVendorAdapter(vendorAdapter);
    factory.setPackagesToScan("ge.shemo");

    Properties jpaProperties = getHibernateProperties();
    factory.setJpaProperties(jpaProperties);

    factory.afterPropertiesSet();
    factory.setLoadTimeWeaver(new InstrumentationLoadTimeWeaver());
    return factory;
}

private Properties getHibernateProperties() {
    Properties prop = new Properties();
    /*prop.put("hibernate.format_sql", "true");*/
    /*prop.put("hibernate.hbm2ddl.auto", "update");*/
    //prop.put("hibernate.hbm2ddl.auto", "validate");
    // prop.put("hibernate.hbm2ddl.import_files","sql/import.sql");
    /*prop.put("hibernate.ejb.entitymanager_factory_name", "irakli");*/

    //prop.put("hibernate.show_sql", "true");
    prop.put("hibernate.dialect", "ge.shemo.config.SQLServerUnicodeDialect");
    return prop;
}


@Bean
public HibernateExceptionTranslator hibernateExceptionTranslator() {
    return new HibernateExceptionTranslator();
}


@Bean
public DataSource dataSource() {
    BasicDataSource ds = new BasicDataSource();
    ds.setDriverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver");

    ds.setUrl("jdbc:sqlserver://LinkToDB:1433;useUnicode=true;characterEncoding=UTF-8;DatabaseName=Your_DB");
    ds.setUsername("USER");
    ds.setPassword("PASS");
    return ds;
}




@Bean
public DataSourceInitializer dataSourceInitializer(DataSource dataSource) {

    DataSourceInitializer dataSourceInitializer = new     DataSourceInitializer();
    dataSourceInitializer.setDataSource(dataSource);
    ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator();
    //databasePopulator.addScript(new ClassPathResource("db.sql"));
    dataSourceInitializer.setDatabasePopulator(databasePopulator);
    dataSourceInitializer.setEnabled(Boolean.parseBoolean(initDatabase));
    return dataSourceInitializer;
}


@Bean
public AuditorAware<Long> createAuditorProvider() {
    return new SecurityAuditor();
}

@Bean
public AuditingEntityListener createAuditingListener() {
    return new AuditingEntityListener();
}



}

Spring Data JPA v1.10.6 依赖于 Spring v4.2(准确地说是 v4.2.9),Spring v4.2 不支持 Hibernate v5.2。添加了对 Hibernate v5.2 的支持 only in Spring v4.3。因此,您必须将 Spring 依赖项升级到 v4.3。


将以下依赖项添加到 Gradle 构建文件应该有效:

compile 'org.springframework:spring-beans:4.3.4.RELEASE'
compile 'org.springframework:spring-context:4.3.4.RELEASE'
compile 'org.springframework:spring-context-support:4.3.4.RELEASE'
compile 'org.springframework:spring-core:4.3.4.RELEASE'
compile 'org.springframework:spring-jdbc:4.3.4.RELEASE'
compile 'org.springframework:spring-orm:4.3.4.RELEASE'
compile 'org.springframework:spring-tx:4.3.4.RELEASE'

您修改后的代码available on Github。 运行 Gradle 测试为 gradle test 以验证一切正常。

好的,问题是 Spring Data JPAHibernate 之间的兼容性问题。 @Spring 和叉子@Hibernate 之间似乎缺少同步解释或@least 版本兼容性解释。对我来说,我已经设法让它与以下版本一起工作

Spring Data JPA and Spring v5.0.0
1.10.0.RELEASE

and Hibernate 5.4.12.Final

有时当您忘记设置 setPackagesToScan() property 和您想要在 LocalContainerEntityManagerFactorybean 中扫描的包时会出现问题,但事实并非如此。所以是的,请查看 Spring DataHibernate 版本!干杯