2

I'm using this code to configure Spring with Hibernate:

@SpringBootApplication
@Configuration
@EnableTransactionManagement
public class ContextServer {

    @Bean
    public LocalSessionFactoryBean getSessionFactory() {
        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();

        try {
            sessionFactory.setDataSource(dataSource());
        } catch (NamingException e) {
            e.printStackTrace();
        }
        sessionFactory.setPackagesToScan(new String[] { "org.plugin.database.models" });
        sessionFactory.setHibernateProperties(hibernateProperties());
        // factoryBean.setAnnotatedClasses(User.class, Authorities.class);

        return sessionFactory;
    }

    @Bean
    public DataSource dataSource() throws NamingException {
        return (DataSource) new JndiTemplate().lookup("java:/global/production_gateway");
    }

    private final Properties hibernateProperties() {
        final Properties hibernateProperties = new Properties();
        hibernateProperties.setProperty("hibernate.hbm2ddl.auto", "create-drop");
        hibernateProperties.setProperty("hibernate.dialect", "org.hibernate.dialect.MariaDBDialect");
        hibernateProperties.setProperty("hibernate.show_sql", "true");
        hibernateProperties.setProperty("hibernate.format_sql", "true");

        return hibernateProperties;
    }

    @Bean
    public HibernateTransactionManager getTransactionManager() {
        HibernateTransactionManager transactionManager = new HibernateTransactionManager();
        transactionManager.setSessionFactory(getSessionFactory().getObject());
        return transactionManager;
    }
}

I use the factory this way:

@Component("authorize")
@Transactional
public class AuthorizeService implements MessageProcessor {

    @Autowired
    SessionFactory sessionFactory;


    @Override
    public void processMessage(.....) {     

        Session session = sessionFactory.getCurrentSession();
    }

But I get exception:

java.lang.ClassCastException: 
org.springframework.orm.jpa.EntityManagerHolder cannot be cast to 
org.springframework.orm.hibernate5.SessionHolder

I found these answers: ClassCastException: org.springframework.orm.jpa.EntityManagerHolder cannot be cast to org.springframework.orm.hibernate5.SessionHolder

Spring 4 + Hibernate 5 = org.springframework.orm.jpa.EntityManagerHolder cannot be cast to org.springframework.orm.hibernate5.SessionHolder

Is there any other solution that I can use? Above solutions are quick hacks.

Peter Penzov
  • 1,126
  • 134
  • 430
  • 808
  • Either downgrade hibernate to <5.2 or don't use the `SessionFactory`.. Why do you even need it? – M. Deinum Jul 12 '18 at 06:42
  • @M.Deinum I took this example from tutorial. If I remove session factory how I can make Hibernate queries? Is there any example project? – Peter Penzov Jul 12 '18 at 06:49
  • I used this tutorial http://www.baeldung.com/hibernate-5-spring – Peter Penzov Jul 12 '18 at 06:50
  • Why would you need hibernate queries. Use JPA queries. Hibernate is a JPA implementation, start with that. If you really need hibernate you can always obtain the underlying session, but first start with JPA not plain hibernate. If you really want the `Session` use the `EntityManager` to get it, using `EntityManager.unwrap(Session.class)`. – M. Deinum Jul 12 '18 at 06:51
  • Can you please paste here example code as official answer? – Peter Penzov Jul 12 '18 at 06:53
  • I need to make Hibernate queries. – Peter Penzov Jul 12 '18 at 06:54
  • No you don't... Why do you think you need hibernate queries... – M. Deinum Jul 12 '18 at 06:54
  • Let's keep on the main topic. Following the tutorial that I tried to implement how I can solve the issue with casting? – Peter Penzov Jul 12 '18 at 07:00
  • As stated downgrade hibernate. – M. Deinum Jul 12 '18 at 07:51
  • Ok, but this looks like a Hibernate issue to me. In future versions how this is going to be used if Hibernate developers don't change it? – Peter Penzov Jul 12 '18 at 07:57
  • IN hibernate 5.2 the `Sessionfactory` extends `EntitymanagerFactory` and leading to Spring 5 thinking it uses JPA. This will be fixed in Spring 5.1 but there isn't a solution for 5.0. As stated I highly doubt you need plain hibernate for your use case. I suspect you are equally well off with using the default configured `EntityManagerFactory` with Spring Boot (the tutorial isn't using Spring Boot btw which also changes things!) and just use the `EntityManager` to execute the same queries. – M. Deinum Jul 12 '18 at 07:59
  • Thanks for the additional information. How I can use `EntityManager`? Can you refer some tutorial? – Peter Penzov Jul 12 '18 at 08:03
  • Just remove the session factory and transaction manager. And instead of `@Autowired SessionFactory` use `@PersistenceContext EntityManager entityManager` (which is roughly equivalent to the `Session`). Also your configuration is still not using Spring Boot (as it seems at least there is no `main` method to bootstrap your application). – M. Deinum Jul 12 '18 at 08:05
  • You can see my main method here: https://stackoverflow.com/questions/51242707/nosuchmethodexception-org-springframework-boot-autoconfigure-http-httpmessageco I use WebApplicationInitializer – Peter Penzov Jul 12 '18 at 08:08
  • Using Spring Boot you shouldn't use a plain `WebApplicationInitializer` but the specialized Spring Boot version of that, if you don't you aren't using Spring Boot (which will lead to all sorts of weirdness if you actually expect it to do, and also for people answering your questions as you aren't actually using Spring Boot). – M. Deinum Jul 12 '18 at 08:09
  • ok, I will try to refactor my code. – Peter Penzov Jul 12 '18 at 08:09
  • Can you paste official answer so I can up vote the answer? – Peter Penzov Jul 12 '18 at 08:14

1 Answers1

4

With the release of Hibernate 5.2 the SessionFactory extends the EntityManagerFactory interface. This leads to the SessionFactory also being an EntityManagerFactory.

In previous hibernate releases this wasn't the case.

The easy solution is to downgrade the hibernate version to a version < 5.2 as there is no solution for Spring 5.0 (there will be in Spring 5.1).

Or probably even beter don't use the plain SessionFactory and let Spring Boot autoconfigure the EntityManagerFactory (done by default if hibernate is detected) and use that instead of plain Hibernate.

M. Deinum
  • 115,695
  • 22
  • 220
  • 224
  • I have to downgrade to 1.5, but at this time is there another way to make this configuration? or could I import hibernate in my pom.xml and use it separate from springboot hibernate? – rfcabal Dec 07 '18 at 17:50
  • @rfcabal noone told you to downgrade to such an old version; 1.5 is so old that it will work with barely anything – Pere Jun 17 '21 at 12:07