首页 > 解决方案 > 在 Jboss 服务器中将 Hibernate 从 3 升级到 4 (WildFly 18.x)

问题描述

我正在尝试将 hibernate 从 3 升级到 4 并遇到多个问题。这是我们为 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;
   }

在升级依赖版本和类包本身之后,我能够编译和启动应用程序。

但是,在尝试对 DB 执行任何写操作后,我收到以下错误:

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.

在研究了大量信息之后,似乎有多种选择。

选项 1:重写 OpenSessionInViewFilter,如如何使用 Spring 4.0.6 为 Hibernate 4.3.5.Final 全局设置 FlushMode?

虽然它似乎有帮助,但当应用程序行为发生变化时会有多种边缘情况(即 HIbernateTemplate 的方法persist在使用时不会更新实体 id @GeneratedValue(strategy = GenerationType.IDENTITY),因此我们必须使用save方法)。总的来说,担心其他副作用,因为这里似乎没有正确地进行事务管理。

选项 2:正如https://crunchtech.io/blog/migrating-from-hibernate-3-to-4-with/中所建议的那样,JTATransactionFactory我们可以切换到CMTTransactionFactory. 这似乎是我们想要进行的事情,因为我们希望 Spring 容器来管理事务。对应的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

在尝试执行 SQL 查询时,它会失败并显示 org.hibernate.TransactionException: Could not register synchronization for container transaction.

仅供参考,仅此部分从原始配置更改:

    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");

有争议的是,Spring 的错误跟踪器提出了完全相反的方法 - https://github.com/spring-projects/spring-framework/issues/15230

选项 3将使用 AOP 方面,该方面将被执行@Transactional以将数据刷新到 DB 中。

选项 4使用 JPA

恕我直言,3 和 4 的可能性非常低。

互联网上的多个示例表明,从 3 -> 4 迁移 Hibernate 应该对 Tomcat 具有吸引力,并且大多数问题都是在 Jboss/GlassFish 服务器中运行时出现的。不幸的是,我们在 WildFly 中运行我们的应用程序。

在这一点上,我很感激对此的任何意见。从什么是一般使用范例开始,也许这里提到的选项完全关闭,我们需要使用不同的机制。或者我们缺少一些关键的配置。

对应的依赖版本

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

标签: javaspringhibernatetransactionswildfly

解决方案


我确实设法让它与在 WildFly 中运行的 Spring 4 Hibernate 5 一起工作,无需自定义OpenSessionInViewFilter或指定容器特定的属性(如 hibernate.transaction.factory_classhibernate.transaction.manager_lookup_class)。成功的关键是正确使用@Transactional注释和一点点 tweeking 查询本身。

更重要的是,在我的测试应用程序中启用 JTA 事务属性(如这里规定)会导致副作用,例如运行时异常的错误回滚。这些是我用来启用它的属性:

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

没有指定这些的相同代码按预期回滚所有中间数据库条目。还不知道为什么会这样,但我们没有充分的理由首先使用 JTA 事务。


推荐阅读