在 Jboss 服务器中将 Hibernate 从 3 升级到 4 (WildFly 18.x)

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

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

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

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

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: 按照 How can I globally set FlushMode for Hibernate 4.3.5.Final with Spring 4.0.6?

中的建议覆盖 OpenSessionInViewFilter

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

选项 2: 正如 https://crunchtech.io/blog/migrating-from-hibernate-3-to-4-with/ 中建议的那样,我们可以切换到 CMTTransactionFactory 而不是使用 JTATransactionFactory。这似乎是我们想要继续的事情,因为我们希望 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 将使用将在 @Transactional 左右执行的 AOP 方面以将数据刷新到数据库中。

选项 4 使用 JPA

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

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

此时,我将不胜感激任何对此的意见。从什么是一般使用范例的问题开始,也许这里提到的选项完全不存在,我们需要使用不同的机制。或者我们遗漏了一些关键的配置。

对应的依赖版本

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

我确实设法在 WildFly w/o 中使用 Spring 4 Hibernate 5 运行 自定义 OpenSessionInViewFilter 或指定 container-specific 属性(如 hibernate.transaction.factory_classhibernate.transaction.manager_lookup_class)。 成功的关键是正确使用 @Transactional 注释和一点 tweeking 查询本身。

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

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

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