简体   繁体   中英

Upgrade Hibernate from 3 to 4 inside Jboss server (WildFly 18.x)

I'm trying to upgrade hibernate from 3 to 4 and running into multiple issues. Here is a configuration we had for v3.

  @Bean
  public LocalSessionFactoryBean sessionFactory(DataSource datasource) {
    LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
    sessionFactory.setDataSource(datasource);
    sessionFactory.setPackagesToScan("com.company.hs.service");
    sessionFactory.setHibernateProperties(hibernateProperties());
    return sessionFactory;
  }

  @Bean
  public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {
    HibernateTransactionManager transactionManager = new HibernateTransactionManager();
    transactionManager.setSessionFactory(sessionFactory);
    return transactionManager;
  }


  private Properties hibernateProperties() {
    Properties properties = new Properties();
    properties.put("hibernate.dialect", "com.company.hs.service.hibernate.MySQL5InnoDBIndexDialect");
    properties.put("hibernate.show_sql", Boolean.TRUE.toString());
    properties.put("hibernate.generate_statistics", Boolean.FALSE.toString());

    properties.put("transaction.factory_class", "org.hibernate.transaction.JTATransactionFactory");
    properties.put("transaction.manager_lookup_class", "org.hibernate.transaction.JBossTransactionManagerLookup");

    properties.put("hibernate.cache.use_query_cache", Boolean.TRUE.toString());
    properties.put("hibernate.cache.use_second_level_cache", Boolean.TRUE.toString());

    return properties;
   }

After upgrading dependency version and class packages itself, I was able to compile and start application.

But then, after trying to execute any write operation against DB I'm getting following error:

org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.MANUAL): Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.

After researching ton of information, there seems to be multiple options to go about it.

Option 1 : Override OpenSessionInViewFilter like suggested in How can I globally set FlushMode for Hibernate 4.3.5.Final with Spring 4.0.6?

Though it seems to help, there are multiple edge cases when app behavior changed (ie HIbernateTemplate's method persist does not update entity id in place while using @GeneratedValue(strategy = GenerationType.IDENTITY) , so instead we have to use save method). And in general, concerned about other side effects since it seems that transaction management is not properly engaged here.

Option 2 : As it was suggested in https://crunchtech.io/blog/migrating-from-hibernate-3-to-4-with/ instead of using JTATransactionFactory we can switch to CMTTransactionFactory . Which is seems like something we want to proceed since we want Spring container to manage transactions. Corresponding spring javadocs - https://docs.spring.io/spring-framework/docs/3.2.0.M1_to_3.2.0.M2/changes/docdiffs_org.springframework.orm.hibernate4.html

While trying to execute SQL query it fails with org.hibernate.TransactionException: Could not register synchronization for container transaction .

For reference, only this piece changed from original configuration:

    properties.put("hibernate.transaction.factory_class", "org.hibernate.transaction.CMTTransactionFactory");
    properties.put("hibernate.transaction.manager_lookup_class", "org.hibernate.transaction.JBossTransactionManagerLookup");
    properties.put("hibernate.transaction.jta.platform", "org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform");

Controversially, Spring's bug tracker suggests completelly opposite approach - https://github.com/spring-projects/spring-framework/issues/15230

Option 3 would be using AOP aspect that will be executed around @Transactional for flushing data into DB.

Option 4 Use JPA

IMHO likellyhood of 3 and 4 is very low.

Multiple examples in internet suggest that migration of Hibernate from 3 -> 4 should work as a charm for Tomcat and most of the issues come when running in Jboss/GlassFish server. Unfortunately, we run our application inside WildFly.

At this point, I'd appreciate any input on this. Starting with the question what is a general usage paradigm, maybe options mentioned here are completely off and we need to use different mechanism. Or we are missing some crucial piece of configuration.

Corresponding dependency versions

Spring - 4.0.5.RELEASE
Hibernate - 4.2.12.Final
WildFly - 18.0.1

I did manage to get it working with Spring 4 Hibernate 5 running within WildFly w/o customizing OpenSessionInViewFilter or specifying container-specific properies (like hibernate.transaction.factory_class or hibernate.transaction.manager_lookup_class ). Key to success was proper usage of @Transactional annotation and little bit of tweeking queries itself.

Even more to that, in my test app enabling JTA transactions properties (like prescribed here ) caused side effects like incorrect rollback on runtime exceptions. These are the properties I was using to enable it:

properties.put("hibernate.transaction.jta.platform", "JBossAS");
properties.put("hibernate.transaction.coordinator_class", "jta");

Same code w/o these being specified rollbacks all intermediate DB entries as expected. Didn't known why is that yet, but there is no good reason for us to use JTA transactions in the first place.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM