我正在使用mssql-jdbc-12.2.0.jre8.jar
和HikariCP-4.0.3.jar
连接到 Microsoft SQL Server 数据库
SQL Server 版本是:Microsoft SQL Server 2012 - 11.0.5548.0 (X64) Sep 6 2014 17:19:28 Copyright (c) Microsoft Corporation Enterprise Edition (64-bit) on Windows NT 6.3 <X64> (Build 9600: ) (Hypervisor)
hibernate 版本:hibernate-core-5.6.11.Final
JRE版本:jre1.8.0_281
Apache Tomcat 版本:9.0.71
Springboot版本:2.7.4
Spring 数据源配置:
spring.datasource.url=jdbc:sqlserver://mydatabaseServer:51803;databaseName=mydatabaseName;encrypt=false;trustServerCertificate=true;socketTimeout=60000
spring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.datasource.password = mypassword
spring.datasource.testWhileIdle = true
spring.datasource.test-on-borrow=true
spring.datasource.validationQuery = SELECT 1
spring.datasource.sql-script-encoding=UTF-8
spring.datasource.username = myusername
spring.datasource.hikari.pool-name=myPool
spring.datasource.hikari.maximum-pool-size=300
spring.datasource.hikari.connectionTimeout=80000
spring.datasource.hikari.max-lifetime=300000
spring.datasource.hikari.idle-timeout=60000
spring.datasource.hikari.leakDetectionThreshold=300000
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.SQLServer2012Dialect
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
spring.jpa.open-in-view=false
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
导致问题的查询返回最多 10 行,如下所示:
@Repository
@Transactional(readOnly = true)
@Log4j2
public class SearchService {
@PersistenceContext
private EntityManager entityManager;
public List<Request> searchRequests(SearchModel searchModel, int pageNumber) {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Request> criteriaQuery = criteriaBuilder.createQuery(Request.class);
Root<Request> requestRoot = criteriaQuery.from(Request.class);
requestRoot.alias("r");
Predicate predicate = createConditions(requestRoot, criteriaBuilder, searchModel);
criteriaQuery.select(requestRoot);
Order orderBy = criteriaBuilder.desc(requestRoot.get("id"));
String orderByProperty = searchModel.getOrderBy();
criteriaQuery.where(predicate).orderBy(orderBy);
// pageSize is 10
// searchModel.getMaxResult() = 10
// for pageNumber 1 startFrom will be 0 and maxResult will be 10
int startFrom = (pageNumber - 1) * searchModel.getPageSize();
List<Request> result = entityManager.createQuery(criteriaQuery).setMaxResults(searchModel.getMaxResult())
.setFirstResult(startFrom).getResultList();
return result;
}
}
上面的设置长期以来工作正常,但最近有时我会遇到很多以下异常:com.microsoft.sqlserver.jdbc.sqlserverexception: the stream is closed
上线:
entityManager.createQuery(criteriaQuery).setMaxResults(searchModel.getMaxResult())
.setFirstResult(startFrom).getResultList();
这被翻译为:
SELECT * FROM request ORDER BY id OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;
直接从 SQL Server 执行此查询时需要 10 毫秒 当流关闭时发生问题时,在监视工具中我可以看到它在此查询中多次关闭!
注意:我从中选择的请求实体/表没有 Eager 关系并且没有二进制列但是它有两个 varchar(MAX) 列并且达到的最大长度为 5368
什么可能导致此问题?可能是应用程序相关或数据库/Windows 服务器问题?
最佳答案
“流已关闭”异常......相当模糊。
假设没有网络问题,并且 SQL Server 日志没有显示任何其他更详细的错误消息,或者服务器本身没有 CPU/内存/磁盘空间问题,您可能会考虑:
查看您的HikariCP connection pool settings 。您可能需要调整
max-lifetime
、idle-timeout
和leakDetectionThreshold
设置,以确保连接不会过早关闭或保持太久。太长了。优化您的查询:虽然直接在 SQL Server 上执行时查询本身似乎表现良好,但您仍然可以通过向
Request
添加适当的索引来尝试进一步优化查询表或使用更有效的方法进行分页,例如使用基于键集的分页。
还 try catch 更多详细信息的异常,例如(来自“How to catch Hibernate SQL EXCEPTIONS IN SPRING ”):
import javax.persistence.PersistenceException;
import org.hibernate.exception.JDBCConnectionException;
import org.springframework.dao.DataAccessException;
@Repository
@Transactional(readOnly = true)
@Log4j2
public class SearchService {
@PersistenceContext
private EntityManager entityManager;
public List<Request> searchRequests(SearchModel searchModel, int pageNumber) {
List<Request> result = new ArrayList<>();
try {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Request> criteriaQuery = criteriaBuilder.createQuery(Request.class);
Root<Request> requestRoot = criteriaQuery.from(Request.class);
requestRoot.alias("r");
Predicate predicate = createConditions(requestRoot, criteriaBuilder, searchModel);
criteriaQuery.select(requestRoot);
Order orderBy = criteriaBuilder.desc(requestRoot.get("id"));
String orderByProperty = searchModel.getOrderBy();
criteriaQuery.where(predicate).orderBy(orderBy);
int startFrom = (pageNumber - 1) * searchModel.getPageSize();
result = entityManager.createQuery(criteriaQuery).setMaxResults(searchModel.getMaxResult())
.setFirstResult(startFrom).getResultList();
} catch (PersistenceException | DataAccessException e) {
if (e.getCause() instanceof JDBCConnectionException) {
log.error("JDBC connection exception occurred: {}", e.getMessage(), e);
} else {
log.error("An exception occurred while executing the search query: {}", e.getMessage(), e);
}
} catch (Exception e) {
log.error("An unexpected exception occurred while executing the search query: {}", e.getMessage(), e);
}
return result;
}
}
我已将查询执行包装在 try-catch block 中,以捕获任何 PersistenceException
、DataAccessException
或其他常规异常。如果发生JDBCConnectionException
,则会记录一条特定消息。对于其他异常,将记录更通用的错误消息。
这应该可以帮助您识别和诊断查询执行期间可能发生的任何问题。
关于spring-boot - com.microsoft.sqlserver.jdbc.sqlserver异常 : the stream is closed,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76411787/