Clob转String报错SQLRecoverableException: 关闭的连接

news/2025/1/10 11:50:01/文章来源:https://www.cnblogs.com/montaro/p/18663710

背景

接到任务需要做一个数据上传的功能,主要是从20多个视图中查询数据,然后调用接口上传数据。

经过

我把这个功能分成两部分:数据查询、数据上传。

上传数据的接口只有一个,通过指定一个参数来区分不同类型的数据,而查询数据的视图中的数据不需要我们处理,因此决定查询数据时使用map来接收参数。

这么做的原因有几个:

  1. 视图字段与接口参数不完全匹配,有的少了几个字段
  2. 接口参数名是驼峰命名,视图也是驼峰命名但因为是Oracle数据库不区分大小写所以实际是大写
  3. 不能通过SQL写下划线别名,因为添加下划线后别名长度会超过30

因此,我决定直接使用SELECT *查询数据,使用List<Map<String,Object>>来接收数据。

但是还有个问题,接口中有部分数据是存在对象嵌套的,部分字段是List类型。

List类型的数据不是通过关联查询得到的,而是需要另外写一个查询去查。

考虑到以上,我决定mapper层查询数据使用map来接收,然后在service层先查询数据再转换成对象。

数据查询编写了一个DataQueryMapperDataQueryService:

public interface DataQueryMapper {List<Map<String, Object>> getPage(@Param("req") PatientReq req);
}
@Service
@RequiredArgsConstructor
public class DataQueryService implements IDataQueryService {private final DataQueryMapper baseMapper;@Overridepublic List<PageData> getPage(PatientReq req) {return NcBeanUtil.mapToBean(baseMapper.getPage(req), PageData.class);}
}

BeanUtil用于转换对象:

public class NcBeanUtil {private static final Map<Class<?>, Map<String, Field>> CACHE = new HashMap<>();private NcBeanUtil() {}public static <T> T mapToBean(Map<String, Object> map, Class<T> clazz) {if (CollUtil.isEmpty(map)) {return null;}Map<String, Field> fieldMap = getFieldMap(clazz);T instance = ReflectUtil.newInstance(clazz);for (Map.Entry<String, Object> entry : map.entrySet()) {String key = entry.getKey();Object value = entry.getValue();Field field = fieldMap.get(key);if (field == null) {continue;}Class<?> fieldType = field.getType();Object fieldValue = Convert.convert(fieldType, value);ReflectUtil.setFieldValue(instance, field, fieldValue);}return instance;}public static <T> List<T> mapToBean(List<Map<String, Object>> mapList, Class<T> clazz) {if (CollUtil.isEmpty(mapList)) {return Collections.emptyList();}return mapList.stream().map(map -> NcBeanUtil.mapToBean(map, clazz)).collect(Collectors.toList());}private static <T> Map<String, Field> getFieldMap(Class<T> clazz) {if (CACHE.containsKey(clazz)) {return CACHE.get(clazz);}Map<String, Field> fieldMap = new HashMap<>();Field[] fields = ReflectUtil.getFields(clazz);for (Field field : fields) {String name = field.getName();String key = name.toUpperCase(Locale.ROOT);fieldMap.put(key, field);}CACHE.put(clazz, fieldMap);return fieldMap;}}

很巧妙的先使用Bean的field定义转换成大写,与原先的field映射存入map,转换时使用map获取到实际的field并填充转换后的值。

报错

运行以后,效果很好,只是在查询其中几个视图时出现了报错:

SQLRecoverableException: 关闭的连接
cn.hutool.core.convert.ConvertException: SQLRecoverableException: 关闭的连接at cn.hutool.core.convert.impl.StringConverter.clobToStr(StringConverter.java:56)at cn.hutool.core.convert.impl.StringConverter.convertInternal(StringConverter.java:32)at cn.hutool.core.convert.impl.StringConverter.convertInternal(StringConverter.java:22)at cn.hutool.core.convert.AbstractConverter.convert(AbstractConverter.java:58)at cn.hutool.core.convert.ConverterRegistry.convert(ConverterRegistry.java:207)at cn.hutool.core.convert.ConverterRegistry.convert(ConverterRegistry.java:247)at cn.hutool.core.convert.Convert.convertWithCheck(Convert.java:753)at cn.hutool.core.convert.Convert.convert(Convert.java:706)at cn.hutool.core.convert.Convert.convert(Convert.java:677)at cn.hutool.core.convert.Convert.convert(Convert.java:651)at ...mapToBean(NcBeanUtil.java:36)...at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)at ...NcBeanUtil.mapToBean(NcBeanUtil.java:50)...

奇怪的现象发生了,为什么在mapToBean的时候会发生SQL相关的异常?

顺着堆栈,发现是NcBeanUtil在使用hutool转换时发生异常

public static <T> T mapToBean(Map<String, Object> map, Class<T> clazz) {...Object fieldValue = Convert.convert(fieldType, value);...
}

解决

百思不得其解,这种报错也是第一次见,为什么连接会关闭?

上网查询一番,发现都是说数据库连接断开之类的,但是重复实验很多次,只有特定几个查询会发生这种异常。

于是在转换时添加了日志,查看是什么原因导致的

public static <T> T mapToBean(Map<String, Object> map, Class<T> clazz) {...try {Object fieldValue = Convert.convert(fieldType, value);ReflectUtil.setFieldValue(instance, field, fieldValue);} catch (Exception e) {log.error("Convert异常: {}:{} valueType = {}, fieldType = {}", key, value, value == null ? null : value.getClass(), fieldType);throw e;}...
}

结果出来了

Convert异常: NCMARITALHISTORY:oracle.sql.CLOB@6bc2903b valueType = class oracle.sql.CLOB, fieldType = class java.lang.String

valueType是Clob,fieldType是String,异常是在Clob转String时发生的。

private static String clobToStr(Clob clob) {Reader reader = null;try {reader = clob.getCharacterStream();return IoUtil.read(reader);} catch (SQLException e) {throw new ConvertException(e);} finally {IoUtil.close(reader);}
}

继续在网络上检索,看到有这样一个说法

oracle-解析CLOB格式字段转String

SQL CLOB是 内置类型,它将字符大对象(Character Large Object) 存储为数据库表某一行中的一个列值。默认情况下,驱动程序使用 SQL locator(CLOB)实现 Clob 对象,这意味着 CLOB 对象包含一个指向 SQL CLOB 数据的逻辑指针而不是数据本身。Clob 对象在它被创建的事务处理期间有效。

Clob 对象在它被创建的事务处理期间有效

莫非是查询后连接关闭或者没有开启事务,连接先关闭了再把Clob转String导致报错?

尝试添加了@Transaction注解

@Override
@Transactional(rollbackFor = Exception.class)
public List<PageData> get=Page(PatientReq req) {return NcBeanUtil.mapToBean(baseMapper.getPage(req), PageData.class);
}

没想到轻松解决了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/867086.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

详解GaussDB事务和并发控制机制,提升事务并发处理效率

本文着重介绍了GaussDB的事务管理和并发控制机制,GaussDB采用多版本并发控制和两阶段锁相结合的机制。摘要:本文着重介绍了GaussDB的事务管理和并发控制机制,GaussDB采用多版本并发控制和两阶段锁相结合的机制。本文分享自华为云社区《华为云开发者云主机体验【玩转华为云】…

php NFA灾难回溯

php NFA灾难回溯正则分为NFA和DFA两种,而php中使用的是NFA.php通过pcre.backtrack_limit来限制回溯次数,如果超过了这个限制,就会返回false.pcre.backtrack_limit默认值是100万. 因此我们可以通过传入大量的垃圾字符或是触发灾难性回溯来超过限制,从而绕过preg_match. 除此以外…

如何构建适合MCN团队的文档管理系统

一、MCN团队运营中的文档管理痛点 每到年末,MCN团队都会面临一场“信息战”。团队成员需要汇总全年合作数据、内容产出情况、以及运营数据报表。这些繁重的任务中,文档管理是最基础但也最容易被忽视的一环。 痛点包括:文件分布零散:不同项目成员习惯使用不同的存储方式,难…

CDS标准视图:一次性账户的客户行项目 I_ONETIMEACCOUNTCUSTOMER

视图名称:一次性账户的客户行项目 视图类型:基础 视图代码:点击查看代码 @EndUserText.label: One-Time Account Data for Customer Items @Analytics: { dataCategory:#DIMENSION} @Analytics.internalName:#LOCAL @VDM.viewType: #BASIC @AbapCatalog.sqlViewName: IONETI…

学习笔记(五十一):onAreaChange 组件区域变化监听

onAreaChange(event: (oldValue: Area, newValue: Area) => void): T 组件区域变化时触发该回调。仅会响应由布局变化所导致的组件大小、位置发生变化时的回调。 由绘制变化所导致的渲染属性变化不会响应回调,如translate、offset。若组件自身位置由绘制变化决定也不会响应…

mysql-sql统计数据sql整理

一、查询SQLSELECTt1.规则编号 AS 编码,t1.规则描述 AS 名称,SUM( CASE WHEN t3.DATA_SOURCES = 00 THEN 1 ELSE 0 END ) AS 类型01,SUM( CASE WHEN t3.DATA_SOURCES = 01 THEN 1 ELSE 0 END ) AS 类型02,SUM( CASE WHEN t3.DATA_SOURCES = 02 THEN 1 ELSE 0 END ) AS 类型03,S…

优化文档管理,为MCN团队运营赋能

对于MCN团队来说,年末不仅是对全年运营工作的总结,更是为来年布局的重要节点。然而,复杂的运营数据、项目进展和内容产出,常常因文档管理混乱而陷入低效,影响复盘和决策的准确性。一、文档管理对MCN团队的重要性 MCN团队日常涉及的文件繁多:内容策划文档、短视频脚本和拍…

Window只允许程序和指定IP交互

1. 使用防火墙的入站和出站规则 2. 使用火绒工具进行拦截 IP黑名单拦截 qq:505645074

CDS标准视图:应收账龄表 I_ARJrnlEntrItmAgingGrid

视图名称:应收账龄表 I_ARJrnlEntrItmAgingGrid 视图类型:参数 视图代码:点击查看代码 @AbapCatalog.sqlViewName: IARJEITMAGGRID @AbapCatalog.compiler.compareFilter:true @AbapCatalog.preserveKey:true @VDM.viewType: #COMPOSITE @EndUserText.label: Aging Grid of …

软工寒假日报(一)

今天开始简单了解了python爬虫,并安装了相关依赖import requestsfrom bs4 import BeautifulSoupimport pandas as pd# 爬取一个页面的数据def scrape_page(url): headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit…

RapidTable release v1.0.3

引言 经过几日来的不懈努力,RapidTable 库终于迎来了 1.0 系列。 RapidTable 库是专门用来文档类图像的表格结构还原,表格结构模型均属于序列预测方法,结合 RapidOCR,将给定图像中的表格转化对应的 HTML 格式。 效果展示模型列表model_type 模型名称 推理框架 模型大小 推理…

ur3+robotiq ft sensor+robotiq 2f 140配置rviz仿真环境-

原文地址: ur3+robotiq ft sensor+robotiq 2f 140配置rviz仿真环境 ur3+robotiq ft sensor+robotiq 2f 140配置rviz仿真环境搭建环境: ubuntu: 20.04ros: Noneticsensor: robotiq_ft300gripper: robotiq_2f_140_gripperUR: UR3 在安装sensor和gripper之前,先简单配置一下UR机…