在 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_class
或 hibernate.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 事务。
我正在尝试将 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_class
或 hibernate.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 事务。