gpt4 book ai didi

java - Hibernate StatelessSession 以及 Oracle 和 SQL Server 上的奇怪行为

转载 作者:太空宇宙 更新时间:2023-11-04 06:22:48 25 4
gpt4 key购买 nike

我正在使用 Hibernate 的 StatelessSession 批量插入和更新行。不确定 jdbc.batch_size 是否与问题相关,但无论如何在我的应用程序中,我根本不配置 hibernate.jdbc.batch_size 参数。

我向 session 提供一个连接对象,该对象已经线程绑定(bind)到现有事务(由 Spring 管理)。这是通过 Spring 的 DataSourceUtils 完成的。因此,当我处理完数据后,我不会关闭无状态 session ,因为在事务完成之前我仍然需要打开连接来执行其他一些操作。

基本上是这样的:

statelessSession = sessionFactory.openStatelessSession(DataSourceUtils.getConnection(...));
// repeat many times
try {
statelessSession.insert(entity);
}
catch (ConstraintViolationException e) {
statelessSession.update(entity);
}
// some more actions
// close transaction

在 SQL Server 上,一切都按预期运行。每个 session.insert(...) 调用都会运行 SQL,如果我尝试插入现有行,则可能会因唯一约束而失败。当我最终提交交易时,一切都按我的预期进行。

但是在 Oracle 上,什么也没有发生。 Hibernate 日志打印 SQL,但它根本不运行。此外,插入不会在应该失败的时候失败。

调试Hibernate代码后,我发现它与JDBC批处理行为有关。我决定使用 managedFlush() 方法显式刷新 statelessSession。即便如此,我发现我必须在每个命令后刷新它,否则它不会表现出我想要的快速失败行为。

statelessSession = sessionFactory.openStatelessSession(DataSourceUtils.getConnection(...));
// repeat many times
try {
statelessSession.insert(entity);
((Context) session).managedFlush()
}
catch (ConstraintViolationException e) {
statelessSession.update(entity);
((Context) session).managedFlush()
}
// some more actions not related to statelessSession
// close transaction

虽然这有效,但当我分析我的代码时,我发现它现在运行得更慢。即使在 SQL Server 上,大概与 managementFlush() 方法无关。

知道发生了什么吗?是否有任何隐藏配置可以调整以实现所需的行为 - 例如“自动刷新”(但当然没有自动提交)?

最佳答案

首先,一旦出现异常,您应该关闭 session ,因为持久性上下文可能会处于不一致的状态。

所以您不应该更新任何异常。

引用Session JavaDoc :

If the Session throws an exception, the transaction must be rolled back and the session discarded. The internal state of the Session might not be consistent with the database after the exception occurs.

在您的示例中,您可以简单地调用合并,因为它适用于服务/更新:

statelessSession.merge(entity);

更新

由于您使用的是 MS SQL,因此您可能正在使用 IDENTITY 生成器,其中 disables JDBC batching 。最新的 MS SQL 版本添加了对 Seqeuneces 的支持,无论如何,它对批处理更加友好。

您需要启用Hibernate batching support ,例如:

hibernate.jdbc.batch_size=30

如果不设置此属性,则默认值为 0,因此没有默认的 JDBC 批处理。

关于java - Hibernate StatelessSession 以及 Oracle 和 SQL Server 上的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27212600/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com