java - 在 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
解决方案
我确实设法让它与在 WildFly 中运行的 Spring 4 Hibernate 5 一起工作,无需自定义OpenSessionInViewFilter
或指定容器特定的属性(如 hibernate.transaction.factory_class
或hibernate.transaction.manager_lookup_class
)。成功的关键是正确使用@Transactional
注释和一点点 tweeking 查询本身。
更重要的是,在我的测试应用程序中启用 JTA 事务属性(如这里规定)会导致副作用,例如运行时异常的错误回滚。这些是我用来启用它的属性:
properties.put("hibernate.transaction.jta.platform", "JBossAS");
properties.put("hibernate.transaction.coordinator_class", "jta");
没有指定这些的相同代码按预期回滚所有中间数据库条目。还不知道为什么会这样,但我们没有充分的理由首先使用 JTA 事务。
推荐阅读
- javascript - 删除显示的项目列表的问题
- python - 格式不显示
- c# - 如何仅过滤和搜索选定字段并排除 ASP.NET MVC 中的空文本框
- mysql - 使用 Intellij 通过 kubernetes pod 连接到 MySQL 服务器
- django - 获取子查询的计数
- django - 需要使我的创建帖子 FBV 不包括当前登录的用户
- c# - 循环通过成员数据的 xunit 测试方法参数
- android - 长时间运行应用程序时使用哪个服务(Android)?
- swift - swift tablecell NSTextAttachment + GIF -> gif 图像不动画
- php - 带有 php 和 mysql 数据库的 Angular 8 跨域请求被阻止: