gpt4 book ai didi

java - 在 Spring MVC 中使用 ScrollableResults-backed Stream 作为返回类型时遇到问题

转载 作者:IT老高 更新时间:2023-10-28 13:52:21 26 4
gpt4 key购买 nike


重要提示:这已被接受为 Spring issue目标修复版本为 4.1.2。


我的目标是在从 Hibernate 的 ScrollableResults 生成 HTTP 响应时实现 O(1) 空间复杂度。我想保留标准机制,其中调度 MessageConverter 以处理从 @Controller 返回的对象。我设置了以下内容:

  1. MappingJackson2HttpMessageConverter 丰富了处理 Java 8 Stream;
  2. JsonSerializer
  3. 自定义 ScrollableResultSpliterator 需要将 ScrollableResults 包装到 Stream 中;
  4. OpenSessionInViewInterceptor 需要在 MessageConverter 中保持 Hibernate session 打开;
  5. hibernate.connection.release_mode设置为ON_CLOSE
  6. 确保 JDBC 连接具有必要的 ResultSet 可保持性:con.setHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT)

此外,我需要一个支持这种可保存性的数据库。 PostgreSQL就是这样一个数据库,我对此没有任何问题。

我遇到的最后一个绊脚石是 HibernateTransactionManager 在事务提交时使用的策略:除非底层 session 是“Hibernate-managed”,否则它将 disconnect()它,关闭我的光标以及其他所有内容。这样的策略在一些特殊情况下很有用,特别是“ session 范围的 session ”,这与我的要求相去甚远。

我已经设法用一个糟糕的 hack 来解决这个问题:我不得不用一个实际上是原始复制粘贴的方法覆盖有问题的方法,除了删除的 disconnect() 调用,但它必须借助反射来访问私有(private) API。

public class NoDisconnectHibernateTransactionManager extends HibernateTransactionManager
{
private static final Logger logger = LoggerFactory.getLogger(NoDisconnectHibernateTransactionManager.class);

public NoDisconnectHibernateTransactionManager(SessionFactory sf) { super(sf); }

@Override
protected void doCleanupAfterCompletion(Object transaction) {
final JdbcTransactionObjectSupport txObject = (JdbcTransactionObjectSupport) transaction;
final Class<?> c = txObject.getClass();
try {
// Remove the session holder from the thread.
if ((Boolean)jailBreak(c.getMethod("isNewSessionHolder")).invoke(txObject))
TransactionSynchronizationManager.unbindResource(getSessionFactory());

// Remove the JDBC connection holder from the thread, if exposed.
if (getDataSource() != null)
TransactionSynchronizationManager.unbindResource(getDataSource());

final SessionHolder sessionHolder = (SessionHolder)jailBreak(c.getMethod("getSessionHolder")).invoke(txObject);
final Session session = sessionHolder.getSession();
if ((Boolean)jailBreak(HibernateTransactionManager.class.getDeclaredField("prepareConnection")).get(this)
&& session.isConnected() && isSameConnectionForEntireSession(session))
{
// We're running with connection release mode "on_close": We're able to reset
// the isolation level and/or read-only flag of the JDBC Connection here.
// Else, we need to rely on the connection pool to perform proper cleanup.
try {
final Connection con = ((SessionImplementor) session).connection();
DataSourceUtils.resetConnectionAfterTransaction(con, txObject.getPreviousIsolationLevel());
}
catch (HibernateException ex) {
logger.debug("Could not access JDBC Connection of Hibernate Session", ex);
}
}
if ((Boolean)jailBreak(c.getMethod("isNewSession")).invoke(txObject)) {
logger.debug("Closing Hibernate Session [{}] after transaction", session);
SessionFactoryUtils.closeSession(session);
}
else {
logger.debug("Not closing pre-bound Hibernate Session [{}] after transaction", session);
if (sessionHolder.getPreviousFlushMode() != null)
session.setFlushMode(sessionHolder.getPreviousFlushMode());
}
sessionHolder.clear();
}
catch (ReflectiveOperationException e) { throw new RuntimeException(e); }
}

static <T extends AccessibleObject> T jailBreak(T o) { o.setAccessible(true); return o; }
}

由于我认为我的方法是生成支持 ResultSet 的响应的“正确方法”,并且由于 Streams API 使这种方法非常方便,我想以一种受支持的方式解决这个问题。

有没有办法在没有我的 hack 的情况下获得相同的行为?如果没有,通过 Spring 的 Jira 请求这是一件好事吗?

最佳答案

清理。正如 Marko Topolnik 所说 here

Yes, I missed this part that the holdability setting is only applied when encountering a pre-existing session. This means that my "idea" how it could be done is already the way it is done. It also means that my comment about failures doesn't apply: you either want holdability and skipping the session disconnection — or you don't need either. So if you can't get holdability, there is no reason not to disconnect the session at commit, therefore there's no reason to activate the "allowResultSetAccessAfterCompletion" in that case.

关于java - 在 Spring MVC 中使用 ScrollableResults-backed Stream 作为返回类型时遇到问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26324112/

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