依据查问后果数据条数大小进行调整:
1、流式查问
长处:大数据量时不会有 OOM 问题。
毛病:占用数据库工夫更长,导致网络拥塞的可能性较大。
// 连贯数据库(简略)Class.forName("驱动");
Connection connection = DriverManager.getConnection(url,user,password)
List<Map<String, Object>> result = new ArrayList<>();
//ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_READ_ONLY 开启流式查问
PreparedStatement ps = connection.prepareStatement(sql,ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_READ_ONLY);
long l1 = System.currentTimeMillis();
// 设计每次查问的大小
ps.setFetchSize(1000);
long l2 = System.currentTimeMillis();
LOG.info("查问工夫 1000 大小:"+(l2-l1));
ResultSet rs = ps.executeQuery();// 返回一个后果集对象
// 利用 sql 查问获取后果集
// 利用反射创立实体类的对象
// 获取后果街的别名 Stud_id 获取 JDBC 的元数据
// 获取后果集每一列的值,联合上一步失去一个 Map 键值对
// 键:列的别名 值:列的值
// 在利用反射对实体类对象的属性赋值
// 属性为 Map 的键 值为 Map 的值
// 获取元数据
ResultSetMetaData rsmd = rs.getMetaData();
Map<String, Object> mapMetaData = new HashMap<>();
// 打印一列的列名
while (rs.next()) {
// 获取数据表中满足要求的一行数据,并放入 Map 中
for (int i = 0; i < rsmd.getColumnCount(); i++) {String columnLabel = rsmd.getColumnLabel(i + 1);
Object columnValue = rs.getObject(columnLabel);
// 获取数据库类型为 Blob 时
//Blob columnValue = rs.getBlob(columnLabel);
//InputStream ins = columnValue.getBinaryStream();
mapMetaData.put(columnLabel, columnValue);
}
// 将 Map 中的数据通过反射初始化 T 类型对象
Map<String, Object> map = new HashMap<>();
if (mapMetaData.size() > 0) {for (Map.Entry<String, Object> entry : mapMetaData.entrySet()) {String fieldkey = entry.getKey();// 字段名
Object fieldvalue = entry.getValue();// 对应的值
// 判断附件属性
// map "fileData": "fileData"
if (CollectionUtil.isNotEmpty(fileDataMap) && StringUtil.isNotEmpty(blobFile) && fieldkey.equals(fileDataMap.get(EfmConfigConstant.FILE_DATA)) && null != fieldvalue) {File file1 = new File(blobFile);
if (!file1.getParentFile().exists()) {boolean mkdirs = file1.mkdirs();
if (!mkdirs) {LOG.error("建设文件失败");
}
}
// 建设输入流
Blob blob = rs.getBlob(fieldkey);
try (InputStream in = blob.getBinaryStream(); FileOutputStream file = new FileOutputStream(file1.getPath() + File.separator + mapMetaData.get(EfmConfigConstant.FILE_NAME))) {int len = (int) blob.length();
byte[] buffer = new byte[len]; // 建设缓冲区
while ((len = in.read(buffer)) != -1) {file.write(buffer, 0, len);
}
}
}
map.put(fieldkey, fieldvalue);
}
}
result.add(map);
2、一般查问
长处:利用代码简略,数据量较小时操作速度快。
毛病:数据量大时会呈现 OOM 问题。
// 连贯数据库(简略)Class.forName("驱动");
Connection connection = DriverManager.getConnection(url,user,password)
List<Map<String, Object>> result = new ArrayList<>();
PreparedStatement ps = connection.prepareStatement(sql);
long l1 = System.currentTimeMillis();
// 设计客户端期待超时工夫(s)
ps.setQueryTimeout(360);
long l2 = System.currentTimeMillis();
LOG.info("查问工夫 1000 大小:"+(l2-l1));
ResultSet rs = ps.executeQuery();// 返回一个后果集对象
// 利用 sql 查问获取后果集
// 利用反射创立实体类的对象
// 获取后果街的别名 Stud_id 获取 JDBC 的元数据
// 获取后果集每一列的值,联合上一步失去一个 Map 键值对
// 键:列的别名 值:列的值
// 在利用反射对实体类对象的属性赋值
// 属性为 Map 的键 值为 Map 的值
// 获取元数据
ResultSetMetaData rsmd = rs.getMetaData();
Map<String, Object> mapMetaData = new HashMap<>();
// 打印一列的列名
while (rs.next()) {
// 获取数据表中满足要求的一行数据,并放入 Map 中
for (int i = 0; i < rsmd.getColumnCount(); i++) {String columnLabel = rsmd.getColumnLabel(i + 1);
Object columnValue = rs.getObject(columnLabel);
// 获取数据库类型为 Blob 时
//Blob columnValue = rs.getBlob(columnLabel);
//InputStream ins = columnValue.getBinaryStream();
mapMetaData.put(columnLabel, columnValue);
}
// 将 Map 中的数据通过反射初始化 T 类型对象
Map<String, Object> map = new HashMap<>();
if (mapMetaData.size() > 0) {for (Map.Entry<String, Object> entry : mapMetaData.entrySet()) {String fieldkey = entry.getKey();// 字段名
Object fieldvalue = entry.getValue();// 对应的值
// 判断附件属性
// map "fileData": "fileData"
if (CollectionUtil.isNotEmpty(fileDataMap) && StringUtil.isNotEmpty(blobFile) && fieldkey.equals(fileDataMap.get(EfmConfigConstant.FILE_DATA)) && null != fieldvalue) {File file1 = new File(blobFile);
if (!file1.getParentFile().exists()) {boolean mkdirs = file1.mkdirs();
if (!mkdirs) {LOG.error("建设文件失败");
}
}
// 建设输入流
Blob blob = rs.getBlob(fieldkey);
try (InputStream in = blob.getBinaryStream(); FileOutputStream file = new FileOutputStream(file1.getPath() + File.separator + mapMetaData.get(EfmConfigConstant.FILE_NAME))) {int len = (int) blob.length();
byte[] buffer = new byte[len]; // 建设缓冲区
while ((len = in.read(buffer)) != -1) {file.write(buffer, 0, len);
}
}
}
map.put(fieldkey, fieldvalue);
}
}
result.add(map);
读取 Blob 类型的数据为压缩包格局解决成文件读成 byte 数组:
//errorFile 为自定义文件生成门路
//jdbc 查问获取 Blob,生成压缩包文件
String columnLabel = rsmd.getColumnLabel(1);
Blob columnValue = rs.getBlob(columnLabel);
InputStream ins = columnValue.getBinaryStream();
File file = new File(errorFile, "cs.zip");
FileUtils.copyInputStreamToFile(ins, file);
ZipFile zipFile = new ZipFile(file, Charset.defaultCharset());
Stream<? extends ZipEntry> signStream = zipFile.stream();
Stream<? extends ZipEntry> zipStream = zipFile.stream();
// 断言
Predicate<ZipEntry> signTxt = ze -> ze.getName().contains("sign,txt");
Predicate<ZipEntry> zipTxt = ze -> ze.getName().endsWith(".zip");
// 过滤
Optional<ZipEntry> signInfo = (Optional<ZipEntry>) signStream.filter(signTxt).findFirst();
Optional<ZipEntry> zipInfo = (Optional<ZipEntry>) zipStream.filter(zipTxt).findFirst();
ins.close();
zipFile.close();
// 获取文件名称
String fileName = rsmd.getColumnLabel(2);
Object fileNames = rs.getObject(fileName);
// 解压 zip 文件
String name = ZipUtils.unzip(file.getPath(), errorFile+File.separator);
// 删除文件
file.delete();
// 读成 byte 数组
byte[] bytes = FileUtil.readFile2Bytes(new File(errorFile + File.separator + name), true);