├── image
└── README.cn
│ ├── 1765353174408.png
│ └── 1765353763090.png
├── etl-engine
├── src
│ └── main
│ │ ├── java
│ │ └── org
│ │ │ └── liuneng
│ │ │ ├── base
│ │ │ ├── LogLevel.java
│ │ │ ├── DataProcessingMetrics.java
│ │ │ ├── InputNode.java
│ │ │ ├── OutputNode.java
│ │ │ ├── monitor
│ │ │ │ └── DataflowMonitor.java
│ │ │ ├── EtlLog.java
│ │ │ ├── Row.java
│ │ │ ├── Node.java
│ │ │ ├── Pipe.java
│ │ │ └── Dataflow.java
│ │ │ ├── exception
│ │ │ ├── DataflowPrestartException.java
│ │ │ ├── DataflowStoppingException.java
│ │ │ ├── NodeException.java
│ │ │ ├── DataflowException.java
│ │ │ ├── EtlEngineException.java
│ │ │ ├── NodePrestartException.java
│ │ │ ├── NodeReadingException.java
│ │ │ └── NodeWritingException.java
│ │ │ ├── node
│ │ │ ├── UpsertTag.java
│ │ │ ├── ValueConvertNode.java
│ │ │ ├── DeleteOutputNode.java
│ │ │ ├── FileOutputNode.java
│ │ │ ├── SqlInputNode.java
│ │ │ ├── InsertOutputNode.java
│ │ │ └── UpsertOutputNode.java
│ │ │ └── util
│ │ │ ├── Tuple2.java
│ │ │ ├── NodeHelper.java
│ │ │ ├── Tuple3.java
│ │ │ ├── StrUtil.java
│ │ │ ├── CsvConverter.java
│ │ │ ├── DBUtil.java
│ │ │ └── DataflowHelper.java
│ │ └── resources
│ │ ├── META-INF
│ │ └── maven
│ │ │ └── archetype.xml
│ │ ├── archetype-resources
│ │ ├── src
│ │ │ ├── main
│ │ │ │ └── java
│ │ │ │ │ └── App.java
│ │ │ └── test
│ │ │ │ └── java
│ │ │ │ └── AppTest.java
│ │ └── pom.xml
│ │ └── log4j2.xml
├── .gitignore
└── pom.xml
├── .gitignore
├── samples
├── src
│ ├── main
│ │ └── java
│ │ │ └── io
│ │ │ └── github
│ │ │ └── add2ws
│ │ │ ├── ValueMappingConverterNode.java
│ │ │ ├── OracleToPG.java
│ │ │ ├── util
│ │ │ └── DataSourceUtil.java
│ │ │ └── SamplesMain.java
│ └── test
│ │ └── java
│ │ └── com
│ │ └── test
│ │ └── TestCase1.java
└── pom.xml
├── README.md.txt
├── LICENSE
├── README.cn.md
├── README.md
└── pom.xml
/image/README.cn/1765353174408.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/add2ws/etl-engine-project/HEAD/image/README.cn/1765353174408.png
--------------------------------------------------------------------------------
/image/README.cn/1765353763090.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/add2ws/etl-engine-project/HEAD/image/README.cn/1765353763090.png
--------------------------------------------------------------------------------
/etl-engine/src/main/java/org/liuneng/base/LogLevel.java:
--------------------------------------------------------------------------------
1 | package org.liuneng.base;
2 |
3 | public enum LogLevel {
4 |
5 | INFO, ERROR
6 | }
7 |
--------------------------------------------------------------------------------
/etl-engine/src/main/java/org/liuneng/exception/DataflowPrestartException.java:
--------------------------------------------------------------------------------
1 | package org.liuneng.exception;
2 |
3 | public class DataflowPrestartException extends DataflowException {
4 | public DataflowPrestartException(String message) {
5 | super(message);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/etl-engine/src/main/java/org/liuneng/exception/DataflowStoppingException.java:
--------------------------------------------------------------------------------
1 | package org.liuneng.exception;
2 |
3 | public class DataflowStoppingException extends DataflowException {
4 | public DataflowStoppingException(String message) {
5 | super(message);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/etl-engine/src/main/resources/META-INF/maven/archetype.xml:
--------------------------------------------------------------------------------
1 |
2 | etl-engine
3 |
4 | src/main/java/App.java
5 |
6 |
7 | src/test/java/AppTest.java
8 |
9 |
10 |
--------------------------------------------------------------------------------
/etl-engine/src/main/resources/archetype-resources/src/main/java/App.java:
--------------------------------------------------------------------------------
1 | package $org.example;
2 |
3 | /**
4 | * Hello world!
5 | *
6 | */
7 | public class App
8 | {
9 | public static void main( String[] args )
10 | {
11 | System.out.println( "Hello World!" );
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/etl-engine/src/main/java/org/liuneng/exception/NodeException.java:
--------------------------------------------------------------------------------
1 | package org.liuneng.exception;
2 |
3 | public class NodeException extends EtlEngineException {
4 | public NodeException(String message) {
5 | super(message);
6 | }
7 |
8 | public NodeException(Throwable cause) {
9 | super(cause);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/etl-engine/src/main/java/org/liuneng/exception/DataflowException.java:
--------------------------------------------------------------------------------
1 | package org.liuneng.exception;
2 |
3 | public class DataflowException extends EtlEngineException {
4 | public DataflowException(String message) {
5 | super(message);
6 | }
7 |
8 | public DataflowException(Throwable cause) {
9 | super(cause);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/etl-engine/src/main/java/org/liuneng/exception/EtlEngineException.java:
--------------------------------------------------------------------------------
1 | package org.liuneng.exception;
2 |
3 | public class EtlEngineException extends RuntimeException {
4 | public EtlEngineException(String message) {
5 | super(message);
6 | }
7 |
8 | public EtlEngineException(Throwable cause) {
9 | super(cause);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/etl-engine/src/main/java/org/liuneng/exception/NodePrestartException.java:
--------------------------------------------------------------------------------
1 | package org.liuneng.exception;
2 |
3 | public class NodePrestartException extends NodeException {
4 | public NodePrestartException(String message) {
5 | super(message);
6 | }
7 |
8 | public NodePrestartException(Throwable cause) {
9 | super(cause);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/etl-engine/src/main/java/org/liuneng/exception/NodeReadingException.java:
--------------------------------------------------------------------------------
1 | package org.liuneng.exception;
2 |
3 | public class NodeReadingException extends NodeException {
4 | public NodeReadingException(String message) {
5 | super(message);
6 | }
7 |
8 | public NodeReadingException(Throwable cause) {
9 | super(cause);
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/etl-engine/src/main/java/org/liuneng/exception/NodeWritingException.java:
--------------------------------------------------------------------------------
1 | package org.liuneng.exception;
2 |
3 | public class NodeWritingException extends NodeException {
4 | public NodeWritingException(String message) {
5 | super(message);
6 | }
7 |
8 | public NodeWritingException(Throwable cause) {
9 | super(cause);
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/etl-engine/src/main/java/org/liuneng/base/DataProcessingMetrics.java:
--------------------------------------------------------------------------------
1 | package org.liuneng.base;
2 |
3 | public interface DataProcessingMetrics {
4 |
5 | String getId();
6 |
7 | long getStartTime();
8 |
9 | long getProcessed();
10 |
11 | long getProcessingRate();
12 |
13 | long getInserted();
14 |
15 | long getInsertingRate();
16 |
17 | long getUpdated();
18 |
19 | long getUpdatingRate();
20 |
21 | long getDeleted();
22 |
23 | long getDeletingRate();
24 |
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/etl-engine/src/main/java/org/liuneng/base/InputNode.java:
--------------------------------------------------------------------------------
1 | package org.liuneng.base;
2 |
3 | import org.liuneng.exception.NodeException;
4 | import org.liuneng.exception.NodeReadingException;
5 |
6 | public interface InputNode {
7 |
8 | long getProcessed();
9 |
10 | long getProcessingRate();
11 |
12 | long getStartTime();
13 |
14 | Row read() throws NodeReadingException;
15 |
16 | String[] getInputColumns() throws NodeException;
17 |
18 | default Node asNode() {
19 | return (Node) this;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/etl-engine/src/main/java/org/liuneng/base/OutputNode.java:
--------------------------------------------------------------------------------
1 | package org.liuneng.base;
2 |
3 | import org.liuneng.exception.NodeException;
4 | import org.liuneng.exception.NodeWritingException;
5 |
6 | public interface OutputNode {
7 |
8 | long getProcessed();
9 |
10 | long getProcessingRate();
11 |
12 | long getStartTime();
13 |
14 | void write(Row row) throws NodeWritingException;
15 |
16 | String[] getOutputColumns() throws NodeException;
17 |
18 | default Node asNode() {
19 | return (Node) this;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/etl-engine/src/main/resources/archetype-resources/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | $org.example
5 | $etl-engine
6 | $1.0-SNAPSHOT
7 |
8 |
9 | junit
10 | junit
11 | 3.8.1
12 | test
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | !.mvn/wrapper/maven-wrapper.jar
3 | !**/src/main/**/target/
4 | !**/src/test/**/target/
5 | .kotlin
6 |
7 | ### IntelliJ IDEA ###
8 | .idea
9 | .idea/modules.xml
10 | .idea/jarRepositories.xml
11 | .idea/compiler.xml
12 | .idea/libraries/
13 | *.iws
14 | *.iml
15 | *.ipr
16 |
17 | ### Eclipse ###
18 | .apt_generated
19 | .classpath
20 | .factorypath
21 | .project
22 | .settings
23 | .springBeans
24 | .sts4-cache
25 |
26 | ### NetBeans ###
27 | /nbproject/private/
28 | /nbbuild/
29 | /dist/
30 | /nbdist/
31 | /.nb-gradle/
32 | build/
33 | !**/src/main/**/build/
34 | !**/src/test/**/build/
35 |
36 | ### VS Code ###
37 | .vscode/
38 |
39 | ### Mac OS ###
40 | .DS_Store
--------------------------------------------------------------------------------
/etl-engine/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | !.mvn/wrapper/maven-wrapper.jar
3 | !**/src/main/**/target/
4 | !**/src/test/**/target/
5 |
6 | ### IntelliJ IDEA ###
7 | .idea/modules.xml
8 | .idea/jarRepositories.xml
9 | .idea/compiler.xml
10 | .idea/libraries/
11 | .idea/
12 | *.iws
13 | *.iml
14 | *.ipr
15 |
16 | ### Eclipse ###
17 | .apt_generated
18 | .classpath
19 | .factorypath
20 | .project
21 | .settings
22 | .springBeans
23 | .sts4-cache
24 |
25 | ### NetBeans ###
26 | /nbproject/private/
27 | /nbbuild/
28 | /dist/
29 | /nbdist/
30 | /.nb-gradle/
31 | build/
32 | !**/src/main/**/build/
33 | !**/src/test/**/build/
34 |
35 | ### VS Code ###
36 | .vscode/
37 |
38 | ### Mac OS ###
39 | .DS_Store
--------------------------------------------------------------------------------
/etl-engine/src/main/resources/log4j2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | %d{yyyy-MM-dd HH:mm:ss} %-5p %c{1} - %m%n
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/etl-engine/src/main/java/org/liuneng/node/UpsertTag.java:
--------------------------------------------------------------------------------
1 | package org.liuneng.node;
2 |
3 |
4 | public enum UpsertTag {
5 |
6 | COMPARE_ONLY(1), //仅比对
7 | UPDATE_ONLY(2), //仅更新
8 | COMPARE_AND_UPDATE(3); //比对且更新
9 |
10 | private final int code;
11 |
12 | UpsertTag(int code) {
13 | this.code = code;
14 | }
15 |
16 | public int getCode() {
17 | return code;
18 | }
19 |
20 | public static UpsertTag fromCode(int code) {
21 | for (UpsertTag upsertTag : UpsertTag.values()) {
22 | if (upsertTag.getCode() == code) {
23 | return upsertTag;
24 | }
25 | }
26 | return null;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/etl-engine/src/main/java/org/liuneng/util/Tuple2.java:
--------------------------------------------------------------------------------
1 | package org.liuneng.util;
2 |
3 | public class Tuple2 {
4 |
5 | private T1 partA;
6 | private T2 partB;
7 |
8 | public Tuple2(T1 partA, T2 partB) {
9 | this.partA = partA;
10 | this.partB = partB;
11 | }
12 |
13 | public T1 getPartA() {
14 | return partA;
15 | }
16 |
17 | public T2 getPartB() {
18 | return partB;
19 | }
20 |
21 | public void setPartA(T1 partA) {
22 | this.partA = partA;
23 | }
24 |
25 | public void setPartB(T2 partB) {
26 | this.partB = partB;
27 | }
28 |
29 | @Override
30 | public String toString() {
31 | return String.format("(%s, %s)", partA, partB);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/etl-engine/src/main/java/org/liuneng/base/monitor/DataflowMonitor.java:
--------------------------------------------------------------------------------
1 | package org.liuneng.base.monitor;
2 |
3 | import org.liuneng.base.Dataflow;
4 |
5 | public class DataflowMonitor {
6 |
7 | private Dataflow dataflowInstance;
8 |
9 | private DataflowMonitor() {
10 |
11 | }
12 |
13 | public static DataflowMonitor watch(Dataflow dataflow) {
14 | DataflowMonitor dataflowMonitor = new DataflowMonitor();
15 | dataflowMonitor.setDataflowInstance(dataflow);
16 |
17 | return dataflowMonitor;
18 | }
19 |
20 |
21 | public Dataflow getDataflowInstance() {
22 | return dataflowInstance;
23 | }
24 |
25 | public void setDataflowInstance(Dataflow dataflowInstance) {
26 | this.dataflowInstance = dataflowInstance;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/etl-engine/src/main/java/org/liuneng/util/NodeHelper.java:
--------------------------------------------------------------------------------
1 | package org.liuneng.util;
2 |
3 | import org.liuneng.base.InputNode;
4 | import org.slf4j.Logger;
5 | import org.slf4j.LoggerFactory;
6 |
7 | import java.util.Arrays;
8 | import java.util.LinkedHashSet;
9 | import java.util.Set;
10 |
11 | public class NodeHelper {
12 |
13 | private final static Logger log = LoggerFactory.getLogger(NodeHelper.class);
14 |
15 | public static String[] getUpstreamColumns(InputNode inputNode) {
16 | Set columns = new LinkedHashSet<>();
17 | InputNode current = inputNode;
18 | do {
19 | columns.addAll(Arrays.asList(current.getInputColumns()));
20 | current = current.asNode().getBeforeNode().orElse(null);
21 | } while (current != null);
22 |
23 | return columns.toArray(new String[0]);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/etl-engine/src/main/java/org/liuneng/util/Tuple3.java:
--------------------------------------------------------------------------------
1 | package org.liuneng.util;
2 |
3 | public class Tuple3 {
4 |
5 | private T1 partA;
6 | private T2 partB;
7 | private T3 partC;
8 |
9 | public Tuple3(T1 partA, T2 partB, T3 partC) {
10 | this.partA = partA;
11 | this.partB = partB;
12 | this.partC = partC;
13 | }
14 |
15 | public T1 getPartA() {
16 | return partA;
17 | }
18 |
19 | public T2 getPartB() {
20 | return partB;
21 | }
22 |
23 | public void setPartA(T1 partA) {
24 | this.partA = partA;
25 | }
26 |
27 | public void setPartB(T2 partB) {
28 | this.partB = partB;
29 | }
30 |
31 | public T3 getPartC() {
32 | return partC;
33 | }
34 |
35 | public void setPartC(T3 partC) {
36 | this.partC = partC;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/etl-engine/src/main/resources/archetype-resources/src/test/java/AppTest.java:
--------------------------------------------------------------------------------
1 | package $org.example;
2 |
3 | import junit.framework.Test;
4 | import junit.framework.TestCase;
5 | import junit.framework.TestSuite;
6 |
7 | /**
8 | * Unit test for simple App.
9 | */
10 | public class AppTest
11 | extends TestCase
12 | {
13 | /**
14 | * Create the test case
15 | *
16 | * @param testName name of the test case
17 | */
18 | public AppTest( String testName )
19 | {
20 | super( testName );
21 | }
22 |
23 | /**
24 | * @return the suite of tests being tested
25 | */
26 | public static Test suite()
27 | {
28 | return new TestSuite( AppTest.class );
29 | }
30 |
31 | /**
32 | * Rigourous Test :-)
33 | */
34 | public void testApp()
35 | {
36 | assertTrue( true );
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/samples/src/main/java/io/github/add2ws/ValueMappingConverterNode.java:
--------------------------------------------------------------------------------
1 | package io.github.add2ws;
2 |
3 | import org.liuneng.base.Row;
4 | import org.liuneng.exception.NodeException;
5 | import org.liuneng.node.ValueConvertNode;
6 |
7 | public class ValueMappingConverterNode extends ValueConvertNode {
8 | @Override
9 | public Row convert(Row row) {
10 |
11 | // row.getData().get("jyzlb")
12 |
13 | return row;
14 | }
15 |
16 | @Override
17 | public long getProcessed() {
18 | return 0;
19 | }
20 |
21 | @Override
22 | public long getProcessingRate() {
23 | return 0;
24 | }
25 |
26 | @Override
27 | public long getStartTime() {
28 | return 0;
29 | }
30 |
31 | @Override
32 | public String[] getOutputColumns() throws NodeException {
33 | return new String[0];
34 | }
35 |
36 | @Override
37 | protected void onDataflowStop() {
38 |
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/etl-engine/src/main/java/org/liuneng/base/EtlLog.java:
--------------------------------------------------------------------------------
1 | package org.liuneng.base;
2 |
3 | import lombok.Data;
4 |
5 | @Data
6 | public class EtlLog {
7 |
8 | private String id;
9 |
10 | private String dataflowID;
11 |
12 | private String nodeID;
13 |
14 | private long inputted;
15 |
16 | private long outputted;
17 |
18 | private long inserted;
19 |
20 | private long updated;
21 |
22 | private int currentBufferSize;
23 |
24 | private long timestamp;
25 |
26 | private LogLevel logLevel;
27 |
28 | private String message;
29 |
30 |
31 | public static EtlLog errorLog(String message) {
32 | EtlLog etlLog = new EtlLog();
33 | etlLog.setLogLevel(LogLevel.ERROR);
34 | etlLog.setMessage(message);
35 | return etlLog;
36 | }
37 |
38 | public static EtlLog infoLog(String message) {
39 | EtlLog etlLog = new EtlLog();
40 | etlLog.setLogLevel(LogLevel.INFO);
41 | etlLog.setMessage(message);
42 | return etlLog;
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/README.md.txt:
--------------------------------------------------------------------------------
1 | 帮我编写一个开源项目的readme.md文档,要求言简意赅,突出数据同步速度快、运行稳健、易扩展3大特性。 文档支持中文和英文:
2 | 项目名称:etl-engine
3 | 项目描述:一个快速、稳健、易扩展的ETL库(对标Kettle),实测200000数据,插入/更新速度是Kettle的2倍
4 | 使用代码示例:
5 | ```sql
6 | //获取数据源
7 | DataSource dataSourceOracle = DataSourceUtil.getOracleDataSource();
8 | DataSource dataSourcePG = DataSourceUtil.getPostgresDataSource();
9 |
10 | //创建表输入节点
11 | SqlInputNode sqlInputNode = new SqlInputNode(dataSourceOracle, "select * from t_resident_info");
12 |
13 | //创建插入/更新节点
14 | UpsertOutputNode upsertOutputNode = new UpsertOutputNode(dataSourcePG, "t_resident_info", 1000);
15 | upsertOutputNode.setIdentityMapping(Arrays.asList(new Tuple2<>("ID", "ID")));
16 |
17 | //创建管道
18 | Pipe pipe = new Pipe(1000);
19 | //连接表输入和输出节点
20 | pipe.connect(sqlInputNode, upsertOutputNode);
21 |
22 | //创建数据流实例
23 | Dataflow dataflow = new Dataflow(sqlInputNode);
24 | //启动数据流
25 | dataflow.syncStart(5, TimeUnit.MINUTES);
26 |
27 | ```
28 |
29 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2025 LiuNeng
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/etl-engine/src/main/java/org/liuneng/util/StrUtil.java:
--------------------------------------------------------------------------------
1 | package org.liuneng.util;
2 |
3 | import java.math.BigDecimal;
4 | import java.util.Date;
5 |
6 | public class StrUtil {
7 |
8 | public static boolean isBlank(String str) {
9 | return str == null || str.trim().isEmpty();
10 | }
11 |
12 | public static boolean isNotBlank(String str) {
13 | return !isBlank(str);
14 | }
15 |
16 | public static String objectToString(Object obj) {
17 | return obj == null ? "" : obj.toString();
18 | }
19 |
20 | public static boolean isEqual(Object obj1, Object obj2) {
21 | if (obj1 instanceof BigDecimal) {
22 | obj1 = ((BigDecimal) obj1).stripTrailingZeros().toPlainString();
23 | }
24 |
25 | if (obj2 instanceof BigDecimal) {
26 | obj2 = ((BigDecimal) obj2).stripTrailingZeros().toPlainString();
27 | }
28 |
29 | if (obj1 instanceof String) {
30 | obj1 = ((String) obj1).trim();
31 | }
32 |
33 | if (obj2 instanceof String) {
34 | obj2 = ((String) obj2).trim();
35 | }
36 |
37 | if (obj1 instanceof Date) {
38 | obj1 = ((Date) obj1).getTime();
39 | }
40 |
41 | if (obj2 instanceof Date) {
42 | obj2 = ((Date) obj2).getTime();
43 | }
44 |
45 | return objectToString(obj1).equals(objectToString(obj2));
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/etl-engine/src/main/java/org/liuneng/base/Row.java:
--------------------------------------------------------------------------------
1 | package org.liuneng.base;
2 |
3 | //import cn.hutool.core.map.CaseInsensitiveLinkedMap;
4 | import cn.hutool.json.JSONUtil;
5 | import org.springframework.util.LinkedCaseInsensitiveMap;
6 |
7 | import java.util.Map;
8 |
9 |
10 | public class Row {
11 |
12 | private boolean end;
13 |
14 | private final Map data = new LinkedCaseInsensitiveMap<>();
15 |
16 | private Row() {}
17 |
18 | public static Row ofEnd() {
19 | Row row = new Row();
20 | row.setEnd(true);
21 | return row;
22 | }
23 |
24 | public static Row fromMap(Map d) {
25 | Row row = new Row();
26 | row.data.putAll(d);
27 | row.end = false;
28 | return row;
29 | }
30 |
31 | public Map getData() {
32 | return data;
33 | }
34 |
35 | public Object get(String key) {
36 | return data.get(key);
37 | }
38 |
39 |
40 | public void put(String key, Object val) {
41 | this.data.put(key, val);
42 | }
43 |
44 | @Override
45 | public String toString() {
46 | return data.toString();
47 | }
48 |
49 | public String toJSONString() {
50 | return JSONUtil.toJsonStr(data);
51 | }
52 |
53 | public boolean isEnd() {
54 | return end;
55 | }
56 |
57 | public void setEnd(boolean end) {
58 | this.end = end;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/etl-engine/src/main/java/org/liuneng/util/CsvConverter.java:
--------------------------------------------------------------------------------
1 | package org.liuneng.util;
2 |
3 | import java.util.Collection;
4 | import java.util.stream.Collectors;
5 |
6 | public class CsvConverter {
7 |
8 | public static String ListToCsvRow(Collection