依据查问后果数据条数大小进行调整:
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);