Migration to hibernate core 5.2.1 ava.lang.NoSuchM

2020-04-11 18:25发布

问题:

Using spring version:4.3.1,Spring data:1.10.2,hibernate core: 5.2.1. using postgres Database pg connector version :9.4.1208.jre7 After upgrading from hibernate 5.1.0 to 5.2.1 when i am trying to create an entity getting below exception

    at java.lang.Thread.run(Thread.java:745)
Caused by: 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.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:427)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:276)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:655)
    at com.cando.person.controller.UserController$$EnhancerBySpringCGLIB$$250a315a.createDefaultUser(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:114)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    ... 31 more
Caused by: java.lang.NoSuchMethodError: org.hibernate.Session.getFlushMode()Lorg/hibernate/FlushMode;
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.prepareFlushMode(HibernateJpaDialect.java:187)
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.beginTransaction(HibernateJpaDialect.java:173)
    at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:380)
    ... 51 more

java config

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories( "com.cando.**.repository" )
@PropertySource( "classpath:spring.properties" )
public class SpringDataConfig
{
    @Autowired
    private Environment env;

    // Declare a datasource
    @Bean
    public DataSource dataSource()
    {
        try
        {
            boolean productionProfile = checkProfileIsActive( IConstants.PROFILE_PRODUCTION );
            String driverClassName = productionProfile ? env.getRequiredProperty( "production.app.jdbc.driverClassName" ) : env.getRequiredProperty( "dev.app.jdbc.driverClassName" );
            String url = productionProfile ? env.getRequiredProperty( "production.app.jdbc.url" ) : env.getRequiredProperty( "dev.app.jdbc.url" );
            String username = productionProfile ? env.getRequiredProperty( "production.app.jdbc.username" ) : env.getRequiredProperty( "dev.app.jdbc.username" );
            String password = productionProfile ? env.getRequiredProperty( "production.app.jdbc.password" ) : env.getRequiredProperty( "dev.app.jdbc.password" );

            System.out.println( driverClassName + " " + url + " " + username + " " + password );

            DriverManagerDataSource dataSource = new DriverManagerDataSource();
            dataSource.setDriverClassName( driverClassName );
            dataSource.setUrl( url);
            dataSource.setUsername( username );
            dataSource.setPassword( password );
            return dataSource;
        }
        catch ( Exception e )
        {
            throw new RuntimeException( e );
        }
    }

    // Declare a JPA entityManagerFactory
    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory()
    {

        LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
        entityManagerFactoryBean.setDataSource( dataSource() );
        entityManagerFactoryBean.setPackagesToScan( "com.cando.**.model" );


        Properties properties = new Properties();
        properties.put( "hibernate.dialect", "org.hibernate.dialect.PostgreSQL95Dialect" );
        properties.put( "hibernate.show_sql", false );
        properties.put( "hibernate.format_sql", false );
        //properties.put( "hibernate.hbm2ddl.auto", "update" );
        properties.put( "hibernate.hbm2ddl.auto", "create-drop" );


        entityManagerFactoryBean.setJpaProperties( properties );

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

        entityManagerFactoryBean.setJpaVendorAdapter( vendorAdapter );

        return entityManagerFactoryBean;
    }

    // Declare a transaction manager
    @Bean
    public JpaTransactionManager transactionManager()
    {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory( entityManagerFactory().getObject() );
        return transactionManager;
    }

    private boolean checkProfileIsActive( String profileName )
    {
        for ( String profile : env.getActiveProfiles() )
        {
            if ( StringUtils.equals( profileName, profile ) )
            {
                return true;
            }
        }
        return false;
    }
}

Github code: https://github.com/arun472/spring-data-jpa

回答1:

This looks as a Jar conflict for Spring Framework 4.3.0.RELEASE version which you have chosen. Please downgrade it to hibernate-core-5.1.0.Final.jar.



回答2:

This looks odd as the method signature support for the Hibernate 5.2 API was added in Spring Framework 4.3.0.RELEASE where it specifically looks for getHibernateFlushMode first and is then followed up by getFlushMode.

I'd say chances are you likely have the new Hibernate libraries on your classpath but you may have an older version of Spring Framework in the classpath which isn't compatible.



回答3:

I found that the class ConfigurationHelper which implements the method public static getFlushMode( Object value ) in hibernate-entitymanager-5.0.2.Final.jar in package org.hibernate.jpa.internal.util conflicts with the correct method signature which includes the default value that is implemented in hibernate-core-5.2.12.Final.jar. The wrong implementation was resolved. I removed the dependency hibernate-entitymanager-5.0.2.Final.jar from my gradle.build file which already includes the dependency hibernate-core-5.2.12.Final.jar and that sorted out the method not found exception