SpingBoot解析Excel数据
前言
在最近的工作中,由于导入模板除了前三列(姓名、手机号、实发工资)固定;其余的列不固定,并且可以做到两个模板的数据都能够正常入库进行对应业务处理。
一、数据模板数据展示:
(1)模板一
(2)模板二
二、处理思路
观察两个模板的数据;结合面向对象的编程思想设计;我可以将两模板需要的获取的字段属性归纳为5个属性点:
注意:标题头在以下中不算!!!
索引(index)-- 相当于excel中所在列的下标列索引
列名称(name)-- 相当于excel中所在列的名称
列值(value)-- 相当于excel中所在列的值
是否存在合并单元格(isGrossField)-- 相当于excel中所在列的是否有合并单元格
合并的子元素(child)-- 相当于excel中所在列的是否有合并单元格下所包含的列
三、编程准备
1、实体类创建:
/**
* @project
* @Description
* @Author songwp
* @Date 2022/8/17 9:04
* @Version 1.0.0
**/
@Data
public class TreeExcel implements Serializable { private int index = 0; private String name; private String value; private boolean isGrossField; private List<TreeExcel> childs;
}
2、maven依赖的引入
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.0-beta2</version>
</dependency>
3、文件解析工具类的编写
import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.fastjson.JSONArray;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.LinkedBlockingQueue; /**
* @project
* @Description
* @Author songwp
* @Date 2022/8/17 9:09
* @Version 1.0.0
**/
public class ExcelUtil { private String value = "empty"; private List<ExcelUtil> nodes; public String getValue() {
return value;
} public void setValue(String value) {
this.value = value;
} public void createExcelJson(List<TreeExcel> treeExcelList, int valueQueueSize, Queue<String> linkedValue, boolean firstStorey) {
if (null != nodes && !firstStorey) {
TreeExcel treeExcel = new TreeExcel();
treeExcel.setGrossField(true);
treeExcel.setName(treeExcel.getName());
treeExcel.setIndex(valueQueueSize - linkedValue.size()); List<TreeExcel> listElem = new ArrayList<>();
treeExcel.setChilds(listElem);
for (ExcelUtil tree : nodes) {
tree.createExcelJson(listElem, valueQueueSize, linkedValue, false);
}
treeExcelList.add(treeExcel);
} else {
if (firstStorey) {
for (ExcelUtil tree : nodes) {
tree.createExcelJson(treeExcelList, valueQueueSize, linkedValue, false);
}
return;
}
TreeExcel treeExcel = new TreeExcel();
treeExcel.setIndex(valueQueueSize - linkedValue.size());
treeExcel.setName(treeExcel.getName());
treeExcel.setValue(linkedValue.poll());
treeExcel.setGrossField(false);
treeExcelList.add(treeExcel);
}
} /**
* 获取树状数据结构
*
* @param inputStream
* @return
* @throws Exception
*/
public static JSONArray getExcelParseJSON(InputStream inputStream) throws Exception {
List<Object> read = EasyExcelFactory.read(inputStream, new Sheet(1, 0));
Map<String, Object> data = new HashMap<>();
int startDataLine = 0;
ExcelTreeUtils tree = new ExcelTreeUtils();
Queue<ExcelTreeUtils> queue = new LinkedBlockingQueue<>();
for (int i = 0; i < read.size(); i++) {
Object line = read.get(i);
ArrayList<String> lineList = (ArrayList<String>) line; if (i > 0 && null != lineList.get(0) && startDataLine == 0) {
startDataLine = i;
break;
}
Queue<ExcelTreeUtils> nextQueue = new LinkedBlockingQueue<>();
for (int j = 0; j < lineList.size(); j++) {
String elem = lineList.get(j);
if (null != elem) {
if (i == 0) {
List<ExcelTreeUtils> nodes = tree.getNodes();
if (null == nodes) {
nodes = new ArrayList<>();
tree.setNodes(nodes);
}
ExcelTreeUtils currentTree = new ExcelTreeUtils(elem, j);
nodes.add(currentTree);
queue.add(currentTree);
} else {
ExcelTreeUtils currentQueueTree = queue.peek();
while (j >= queue.peek().getExcelColumnIndex()) {
nextQueue.add(queue.poll());
currentQueueTree = queue.peek();
}
List<ExcelTreeUtils> nodes = currentQueueTree.getNodes();
if (null == nodes) {
nodes = new ArrayList<>();
currentQueueTree.setNodes(nodes);
}
ExcelTreeUtils currentTree = new ExcelTreeUtils(elem, j);
nodes.add(currentTree);
nextQueue.add(currentTree);
}
}
}
if (i > 0) {
queue = nextQueue;
}
Queue<ExcelTreeUtils> newQueue = new LinkedBlockingQueue<>();
while (null != queue.peek()) {
ExcelTreeUtils poll = queue.poll();
if (null != queue.peek()) {
poll.setExcelColumnIndex(queue.peek().getExcelColumnIndex());
} else {
poll.setExcelColumnIndex(i);
}
newQueue.add(poll);
}
queue = newQueue;
}
Queue<String> valueQueue = new LinkedBlockingQueue<>();
JSONArray resultJsonArray = new JSONArray();
for (int i = startDataLine; i < read.size(); i++) {
Object line = read.get(i);
ArrayList<String> lineList = (ArrayList<String>) line;
for (int j = 0; j < lineList.size(); j++) {
String elem = lineList.get(j);
if (null == elem) elem = "";
valueQueue.add(elem);
}
JSONArray jsonArray = new JSONArray();
tree.createStructeddJson(jsonArray, valueQueue.size(), valueQueue, true);
resultJsonArray.add(jsonArray);
}
return resultJsonArray;
}
}
4、测试类的编写
public static void main(String[] args) throws Exception {
InputStream fis = new FileInputStream("C:\\Users\\Lenovo\\Desktop\\工作簿1.xlsx");
JSONArray jsonArray = getExcelParseJSON(fis);
System.out.println(jsonArray);
TreeExcel treeExcel = new TreeExcel();
for (Object salaryObject : jsonArray) {
JSONArray salaryInfo = (JSONArray) salaryObject;
treeExcel.setIndex(Integer.parseInt(((Map) salaryInfo.get(0)).get("index").toString()));
treeExcel.setName(((Map) salaryInfo.get(0)).get("name").toString());
treeExcel.setValue(((Map) salaryInfo.get(0)).get("value").toString());
treeExcel.setGrossField(Boolean.getBoolean(((Map) salaryInfo.get(0)).get("isGrossField").toString()));
}
System.out.println(treeExcel);
}
5、日志输出展示
注意:因为自己的实体在循环外面展示;所以循环里面赋值存在覆盖;所以获取到的是最后一条数据对应信息
(1)模板一:
(2)模板二:
6、返回的json展示:
(1)模板一:
[
[
{
"name":"姓名",
"index":0,
"isGrossField":false,
"value":"张三"
},
{
"name":"手机号",
"index":1,
"isGrossField":false,
"value":"18710000000"
},
{
"name":"实发工资",
"index":2,
"isGrossField":false,
"value":"200000"
},
{
"name":"1高级专家补贴",
"index":3,
"isGrossField":false,
"value":"2000"
},
{
"name":"话费补贴1",
"index":4,
"isGrossField":false,
"value":"300"
},
{
"name":"薪级薪档",
"index":5,
"isGrossField":false,
"value":"五档"
},
{
"name":"考核系数",
"index":6,
"isGrossField":false,
"value":"25%"
},
{
"name":"参与绩效奖金计算的岗位工资",
"index":7,
"isGrossField":false,
"value":"1231"
},
{
"name":"工资说明",
"index":8,
"isGrossField":false,
"value":""
},
{
"name":"温馨提示",
"index":9,
"isGrossField":false,
"value":"无"
}
],
[
{
"name":"姓名",
"index":0,
"isGrossField":false,
"value":"李四"
},
{
"name":"手机号",
"index":1,
"isGrossField":false,
"value":"18710000001"
},
{
"name":"实发工资",
"index":2,
"isGrossField":false,
"value":"200001"
},
{
"name":"1高级专家补贴",
"index":3,
"isGrossField":false,
"value":"2001"
},
{
"name":"话费补贴1",
"index":4,
"isGrossField":false,
"value":"301"
},
{
"name":"薪级薪档",
"index":5,
"isGrossField":false,
"value":"五档"
},
{
"name":"考核系数",
"index":6,
"isGrossField":false,
"value":"125%"
},
{
"name":"参与绩效奖金计算的岗位工资",
"index":7,
"isGrossField":false,
"value":"1232"
},
{
"name":"工资说明",
"index":8,
"isGrossField":false,
"value":"无"
},
{
"name":"温馨提示",
"index":9,
"isGrossField":false,
"value":"无"
}
],
[
{
"name":"姓名",
"index":0,
"isGrossField":false,
"value":"王五"
},
{
"name":"手机号",
"index":1,
"isGrossField":false,
"value":"18710000002"
},
{
"name":"实发工资",
"index":2,
"isGrossField":false,
"value":"200002"
},
{
"name":"1高级专家补贴",
"index":3,
"isGrossField":false,
"value":"2002"
},
{
"name":"话费补贴1",
"index":4,
"isGrossField":false,
"value":"302"
},
{
"name":"薪级薪档",
"index":5,
"isGrossField":false,
"value":"五档"
},
{
"name":"考核系数",
"index":6,
"isGrossField":false,
"value":""
},
{
"name":"参与绩效奖金计算的岗位工资",
"index":7,
"isGrossField":false,
"value":"1233"
},
{
"name":"工资说明",
"index":8,
"isGrossField":false,
"value":"无"
},
{
"name":"温馨提示",
"index":9,
"isGrossField":false,
"value":"无"
}
],
[
{
"name":"姓名",
"index":0,
"isGrossField":false,
"value":"赵老六"
},
{
"name":"手机号",
"index":1,
"isGrossField":false,
"value":"18710000003"
},
{
"name":"实发工资",
"index":2,
"isGrossField":false,
"value":"200003"
},
{
"name":"1高级专家补贴",
"index":3,
"isGrossField":false,
"value":"2003"
},
{
"name":"话费补贴1",
"index":4,
"isGrossField":false,
"value":"303"
},
{
"name":"薪级薪档",
"index":5,
"isGrossField":false,
"value":"五档"
},
{
"name":"考核系数",
"index":6,
"isGrossField":false,
"value":"325%"
},
{
"name":"参与绩效奖金计算的岗位工资",
"index":7,
"isGrossField":false,
"value":"1234"
},
{
"name":"工资说明",
"index":8,
"isGrossField":false,
"value":"无"
},
{
"name":"温馨提示",
"index":9,
"isGrossField":false,
"value":"无"
}
],
[
{
"name":"姓名",
"index":0,
"isGrossField":false,
"value":"小明"
},
{
"name":"手机号",
"index":1,
"isGrossField":false,
"value":"18710000004"
},
{
"name":"实发工资",
"index":2,
"isGrossField":false,
"value":"200004"
},
{
"name":"1高级专家补贴",
"index":3,
"isGrossField":false,
"value":"2004"
},
{
"name":"话费补贴1",
"index":4,
"isGrossField":false,
"value":"304"
},
{
"name":"薪级薪档",
"index":5,
"isGrossField":false,
"value":"五档"
},
{
"name":"考核系数",
"index":6,
"isGrossField":false,
"value":"425%"
},
{
"name":"参与绩效奖金计算的岗位工资",
"index":7,
"isGrossField":false,
"value":"1235"
},
{
"name":"工资说明",
"index":8,
"isGrossField":false,
"value":"无"
},
{
"name":"温馨提示",
"index":9,
"isGrossField":false,
"value":"无"
}
]
]
(2)模板二:
[
[
{
"name":"姓名",
"index":0,
"isGrossField":false,
"value":"张三"
},
{
"name":"手机号",
"index":1,
"isGrossField":false,
"value":"18700000000"
},
{
"name":"实发工资",
"index":2,
"isGrossField":false,
"value":"25000"
},
{
"name":"应发工资",
"isGrossField":true,
"child":[
{
"name":"出勤\n天数",
"index":3,
"isGrossField":false,
"value":"22"
},
{
"name":"岗位工资系数",
"index":4,
"isGrossField":false,
"value":"3500"
},
{
"name":"岗位工\n资标准",
"index":5,
"isGrossField":false,
"value":"13000"
},
{
"name":"岗位工资",
"index":6,
"isGrossField":false,
"value":"3500"
},
{
"name":"绩效系数",
"index":7,
"isGrossField":false,
"value":"150"
},
{
"name":"绩效奖金标准",
"index":8,
"isGrossField":false,
"value":"100"
},
{
"name":"个人绩效分数",
"index":9,
"isGrossField":false,
"value":"100"
},
{
"name":"绩效奖金",
"index":10,
"isGrossField":false,
"value":"1000"
},
{
"name":"工龄补贴",
"index":11,
"isGrossField":false,
"value":"1000"
},
{
"name":"职称津贴",
"index":12,
"isGrossField":false,
"value":""
},
{
"name":"话费补贴",
"index":13,
"isGrossField":false,
"value":"100"
},
{
"name":"证书津贴",
"index":14,
"isGrossField":false,
"value":"1000"
},
{
"name":"保密津贴",
"index":15,
"isGrossField":false,
"value":"100"
},
{
"name":"午餐补贴",
"index":16,
"isGrossField":false,
"value":""
},
{
"name":"医疗补贴",
"index":17,
"isGrossField":false,
"value":"1000"
},
{
"name":"交通补贴",
"index":18,
"isGrossField":false,
"value":"1000"
},
{
"name":"降温费",
"index":19,
"isGrossField":false,
"value":"100"
},
{
"name":"差额",
"index":20,
"isGrossField":false,
"value":"100"
},
{
"name":"小计",
"index":21,
"isGrossField":false,
"value":"1000"
}
]
},
{
"name":"应扣款项",
"isGrossField":true,
"child":[
{
"name":"旷工\n天数",
"index":22,
"isGrossField":false,
"value":"1"
},
{
"name":"旷工扣款",
"index":23,
"isGrossField":false,
"value":"100"
},
{
"name":"事假\n天数",
"index":24,
"isGrossField":false,
"value":"1"
},
{
"name":"事假扣款",
"index":25,
"isGrossField":false,
"value":"100"
},
{
"name":"病假\n天数",
"index":26,
"isGrossField":false,
"value":"1"
},
{
"name":"病假扣款",
"index":27,
"isGrossField":false,
"value":"100"
},
{
"name":"小计",
"index":28,
"isGrossField":false,
"value":"300"
}
]
},
{
"name":"应发合计",
"index":29,
"isGrossField":false,
"value":"40000"
},
{
"name":"07月社保、06月医疗及07月公积金扣款",
"isGrossField":true,
"child":[
{
"name":"月养老保险",
"index":30,
"isGrossField":false,
"value":"500"
},
{
"name":"月医疗保险",
"index":31,
"isGrossField":false,
"value":"600"
},
{
"name":"月大额补充",
"index":32,
"isGrossField":false,
"value":"700"
},
{
"name":"月失业保险",
"index":33,
"isGrossField":false,
"value":"800"
},
{
"name":"社保补缴养老",
"index":34,
"isGrossField":false,
"value":"900"
},
{
"name":"社保补缴大额",
"index":35,
"isGrossField":false,
"value":"100"
},
{
"name":"社保补缴\n医疗",
"index":36,
"isGrossField":false,
"value":"110"
},
{
"name":"公积金",
"index":37,
"isGrossField":false,
"value":"120"
}
]
},
{
"name":"社保公积当月合计",
"index":38,
"isGrossField":false,
"value":"130"
},
{
"name":"六项附加当月",
"index":39,
"isGrossField":false,
"value":"140"
},
{
"name":"个税",
"index":40,
"isGrossField":false,
"value":"150"
},
{
"name":"补偿",
"index":41,
"isGrossField":false,
"value":"1600"
}
],
[
{
"name":"姓名",
"index":0,
"isGrossField":false,
"value":"李四"
},
{
"name":"手机号",
"index":1,
"isGrossField":false,
"value":"18710000000"
},
{
"name":"实发工资",
"index":2,
"isGrossField":false,
"value":"20000"
},
{
"name":"应发工资",
"isGrossField":true,
"child":[
{
"name":"出勤\n天数",
"index":3,
"isGrossField":false,
"value":"21"
},
{
"name":"岗位工资系数",
"index":4,
"isGrossField":false,
"value":"3500"
},
{
"name":"岗位工\n资标准",
"index":5,
"isGrossField":false,
"value":"13000"
},
{
"name":"岗位工资",
"index":6,
"isGrossField":false,
"value":"3500"
},
{
"name":"绩效系数",
"index":7,
"isGrossField":false,
"value":"200"
},
{
"name":"绩效奖金标准",
"index":8,
"isGrossField":false,
"value":"200"
},
{
"name":"个人绩效分数",
"index":9,
"isGrossField":false,
"value":"200"
},
{
"name":"绩效奖金",
"index":10,
"isGrossField":false,
"value":"2000"
},
{
"name":"工龄补贴",
"index":11,
"isGrossField":false,
"value":""
},
{
"name":"职称津贴",
"index":12,
"isGrossField":false,
"value":"2000"
},
{
"name":"话费补贴",
"index":13,
"isGrossField":false,
"value":"200"
},
{
"name":"证书津贴",
"index":14,
"isGrossField":false,
"value":"2000"
},
{
"name":"保密津贴",
"index":15,
"isGrossField":false,
"value":"200"
},
{
"name":"午餐补贴",
"index":16,
"isGrossField":false,
"value":"2000"
},
{
"name":"医疗补贴",
"index":17,
"isGrossField":false,
"value":"2000"
},
{
"name":"交通补贴",
"index":18,
"isGrossField":false,
"value":"2000"
},
{
"name":"降温费",
"index":19,
"isGrossField":false,
"value":"200"
},
{
"name":"差额",
"index":20,
"isGrossField":false,
"value":"200"
},
{
"name":"小计",
"index":21,
"isGrossField":false,
"value":"2000"
}
]
},
{
"name":"应扣款项",
"isGrossField":true,
"child":[
{
"name":"旷工\n天数",
"index":22,
"isGrossField":false,
"value":"2"
},
{
"name":"旷工扣款",
"index":23,
"isGrossField":false,
"value":"200"
},
{
"name":"事假\n天数",
"index":24,
"isGrossField":false,
"value":"2"
},
{
"name":"事假扣款",
"index":25,
"isGrossField":false,
"value":"200"
},
{
"name":"病假\n天数",
"index":26,
"isGrossField":false,
"value":"2"
},
{
"name":"病假扣款",
"index":27,
"isGrossField":false,
"value":"200"
},
{
"name":"小计",
"index":28,
"isGrossField":false,
"value":"400"
}
]
},
{
"name":"应发合计",
"index":29,
"isGrossField":false,
"value":"50000"
},
{
"name":"07月社保、06月医疗及07月公积金扣款",
"isGrossField":true,
"child":[
{
"name":"月养老保险",
"index":30,
"isGrossField":false,
"value":"600"
},
{
"name":"月医疗保险",
"index":31,
"isGrossField":false,
"value":"700"
},
{
"name":"月大额补充",
"index":32,
"isGrossField":false,
"value":"800"
},
{
"name":"月失业保险",
"index":33,
"isGrossField":false,
"value":"900"
},
{
"name":"社保补缴养老",
"index":34,
"isGrossField":false,
"value":"1000"
},
{
"name":"社保补缴大额",
"index":35,
"isGrossField":false,
"value":"110"
},
{
"name":"社保补缴\n医疗",
"index":36,
"isGrossField":false,
"value":"120"
},
{
"name":"公积金",
"index":37,
"isGrossField":false,
"value":"130"
}
]
},
{
"name":"社保公积当月合计",
"index":38,
"isGrossField":false,
"value":"140"
},
{
"name":"六项附加当月",
"index":39,
"isGrossField":false,
"value":"150"
},
{
"name":"个税",
"index":40,
"isGrossField":false,
"value":"160"
},
{
"name":"补偿",
"index":41,
"isGrossField":false,
"value":"1700"
}
]
]
SpingBoot解析Excel数据的更多相关文章
- oracle xmltype导入并解析Excel数据--前言
通常,很多的时候,我们需要导入Excel数据到系统中,但是Excel数据需要我们去各种校验,比如身份证校验,手机号码校验等等. 校验失败的数据,提供Excel导出错误原因,提示给用户. 如此,如果校验 ...
- 解析Excel数据
解析Excel数据常用的方式就是使用POI和JXL工具了,这两种工具使用起来有些类似,这里记录一下使用方式提供个参考 POI使用 File file = new File(filePath); Fil ...
- POI完美解析Excel数据到对象集合中(可用于将EXCEL数据导入到数据库)
实现思路: 1.获取WorkBook对象,在这里使用WorkbookFactory.create(is); // 这种方式解析Excel.2003/2007/2010都没问题: 2.对行数据进行解析 ...
- oracle xmltype导入并解析Excel数据 (四)特别说明
1.Excel导出,此处没有给出 2.错误原因在中间表,T_EXCEL_IMPORT_GENERATION,其中errormsg不为空的数据 3,中间表入库过程: 需要自己实现,为一个存储过程,存储过 ...
- oracle xmltype导入并解析Excel数据 (三)解析Excel数据
包声明 create or replace package PKG_EXCEL_UTILS is -- Author: zkongbai-- Create at: 2016-07-06-- Actio ...
- oracle xmltype导入并解析Excel数据 (一)创建表与序
表说明: T_EXCEL_IMPORT_DATASRC: Excel数据存储表,(使用了xmltype存储Excel数据) 部分字段说明: BUSINESSTYPE: Excel模板类型,一个Exce ...
- 使用python三方库xlrd解析excel数据
excel是平常用的比较多的一种数据格式,而在自动化测试过程中,解析其数据以供脚本使用就是一个重要的工作,幸好已有现存的三方库供使用,而不必重新造轮子. 一.安装xlrd模块 到python官网下载h ...
- oracle xmltype导入并解析Excel数据 (二)规则说明
规则表字段说明如下: 其中RULE_FUNC_CUSTOMIZE表示,用户自己写函数,去判断数据是否合法,存储的是函数的名字 此函数的参数只有一个,该列的值,字段类型是Varchar2, 校验失败的话 ...
- 利用 js-xlsx 实现 Excel 文件导入并解析Excel数据成json格式的数据并且获取其中某列数据
演示效果参考如下:XML转JSON 另一个搭配SQL实现:http://sheetjs.com/sexql/index.html 详细介绍: 1.首先需要导入js <script src=&qu ...
随机推荐
- 使用Rclone将Onedirve挂载到Linux本地
1. centos挂载onedrive时, 需要安装fuse. # 安装fuse yum -y install fuse 2. 安装完fuse后使用rclone进行挂载 #创建挂载目录 mkdir - ...
- Jmeter接口参数化<自动化>(csv文件)管理测试用例以及断言
1.创建相关线程组(不解释) 2.创建相应的请求(在请求中设置变量) 下面截图中①②③④⑤⑥⑦皆可以设置为变量 3.新建CSV文件 将请求中设置的变量为明确了解每个字段的含义(皆可以将变量填写到列表的 ...
- jenkins 流水线自动化部署 手动下载安装插件包
如果有些插件不能通过可选插件安装,可以进行选择高级并上传插件包,插件包链接地址为:http://updates.jenkins-ci.org/download/plugins/ 同时在高级中可以更换下 ...
- vivo 容器集群监控系统架构与实践
vivo 互联网服务器团队-YuanPeng 一.概述 从容器技术的推广以及 Kubernetes成为容器调度管理领域的事实标准开始,云原生的理念和技术架构体系逐渐在生产环境中得到了越来越广泛的应用实 ...
- BUUCTF-数据包中的线索
数据包中的线索 下载看是个流量包,用wireshark打开 有个fenxi.php,里面是个base64编码,尝试解码发现编码不对,那应该就是base64转图片 得到flag
- RPA供应链管制单修改机器人
背景:供应链环节中,研发物料时而因为市场缺货等原因无法采购,资材部需登入系统修改物料管制单. 操作流程:登录PDM系统中读取数据.登录ERP系统中更新数据. 人工操作:每日耗时3.5小时,出现一定比例 ...
- ssh-修改ssh服务端口号
在启动selinux的状态下修改ssh的端口号 0.启动selinux setenforce 1 getenforce 1.修改sshd_config的Port为2234 查看2234 ...
- TypeScript let与var的区别
1.作用域不同 用var声明的变量,只有函数作用域和全局作用域,没有块级作用域.而let可以实现块级作用域,只能在代码块{}内有效,在{}之外不能访问,如下代码所示: { let a = 0; var ...
- 深入理解Apache Hudi异步索引机制
在我们之前的文章中,我们讨论了多模式索引的设计,这是一种用于Lakehouse架构的无服务器和高性能索引子系统,以提高查询和写入性能.在这篇博客中,我们讨论了构建如此强大的索引所需的机制,异步索引机制 ...
- Tapdata Cloud 版本上新!新增ClickHouse,ADB MySQL等5个数据源支持
Tapdata Cloud cloud.tapdata.net Tapdata Cloud 是国内首家异构数据库实时同步云平台,目前支持Oracle.MySQL.PG.SQL Server.Mongo ...