initial
This commit is contained in:
commit
6b23c32c6d
29
pom.xml
Normal file
29
pom.xml
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>org.example</groupId>
|
||||||
|
<artifactId>DataMigration_Selfmade</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>mysql</groupId>
|
||||||
|
<artifactId>mysql-connector-java</artifactId>
|
||||||
|
<version>8.0.19</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mariadb.jdbc</groupId>
|
||||||
|
<artifactId>mariadb-java-client</artifactId>
|
||||||
|
<version>2.5.4</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.postgresql</groupId>
|
||||||
|
<artifactId>postgresql</artifactId>
|
||||||
|
<version>42.2.9</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
75
src/main/java/Main.java
Normal file
75
src/main/java/Main.java
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import data.source.PersonSource;
|
||||||
|
import data.target.PersonTarget;
|
||||||
|
import etl.Extractor;
|
||||||
|
import etl.Loader;
|
||||||
|
import etl.Transformer;
|
||||||
|
import utils.*;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.time.Period;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Main
|
||||||
|
{
|
||||||
|
public static void main(final String[] args) throws SQLException
|
||||||
|
{
|
||||||
|
// mysqlDb();
|
||||||
|
// postgresqlDb();
|
||||||
|
// mariaDb();
|
||||||
|
|
||||||
|
var p = testExtract();
|
||||||
|
var pt = testTransform(p);
|
||||||
|
testLoad(pt);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<PersonSource> testExtract() throws SQLException
|
||||||
|
{
|
||||||
|
final var dbInfo = new DatabaseInformation("localhost", "sourcedb1", "test", "test", 5435);
|
||||||
|
final var connection = new ConnectionHelper(DatabaseType.MARIADB, dbInfo).createConnection();
|
||||||
|
|
||||||
|
DataStorer<PersonSource> personSourceDataStorer = (rs) -> {
|
||||||
|
var persons = new ArrayList<PersonSource>();
|
||||||
|
while (rs.next())
|
||||||
|
{
|
||||||
|
persons.add(new PersonSource(rs.getInt("personId"),
|
||||||
|
rs.getString("name"),
|
||||||
|
rs.getBoolean("mortal")));
|
||||||
|
}
|
||||||
|
return persons;
|
||||||
|
};
|
||||||
|
|
||||||
|
var sql = "select * from person;";
|
||||||
|
|
||||||
|
return new Extractor<>(connection, personSourceDataStorer, sql).doExtract();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<PersonTarget> testTransform(List<PersonSource> persons)
|
||||||
|
{
|
||||||
|
DataTransformer<PersonSource, PersonTarget> personTransformer = (personSource) -> {
|
||||||
|
return new PersonTarget(personSource.getPersonId(),
|
||||||
|
personSource.getName(),
|
||||||
|
personSource.isMortal());
|
||||||
|
};
|
||||||
|
|
||||||
|
return new Transformer<>(personTransformer, persons).doTransform();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testLoad(List<PersonTarget> transformedData)
|
||||||
|
{
|
||||||
|
final var dbInfo = new DatabaseInformation("localhost", "targetdb", "test", "test", 5432);
|
||||||
|
final var connection = new ConnectionHelper(DatabaseType.POSTGRESQL, dbInfo).createConnection();
|
||||||
|
|
||||||
|
StatementPreparer<PersonTarget> statementPreparer = (preparedStatement, data) -> {
|
||||||
|
preparedStatement.setInt(1, data.getPersonId());
|
||||||
|
preparedStatement.setString(2, data.getName());
|
||||||
|
preparedStatement.setBoolean(3, data.isMortal());
|
||||||
|
};
|
||||||
|
|
||||||
|
var sql = "insert into person values (?, ?, ?)";
|
||||||
|
|
||||||
|
new Loader<>(connection, statementPreparer, transformedData, sql).doLoad();
|
||||||
|
}
|
||||||
|
}
|
5
src/main/java/data/Dataset.java
Normal file
5
src/main/java/data/Dataset.java
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package data;
|
||||||
|
|
||||||
|
public interface Dataset
|
||||||
|
{
|
||||||
|
}
|
38
src/main/java/data/source/PersonSource.java
Normal file
38
src/main/java/data/source/PersonSource.java
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package data.source;
|
||||||
|
|
||||||
|
import data.Dataset;
|
||||||
|
|
||||||
|
public class PersonSource implements Dataset
|
||||||
|
{
|
||||||
|
private int personId;
|
||||||
|
private String name;
|
||||||
|
private boolean mortal;
|
||||||
|
|
||||||
|
public PersonSource(int personId, String name, boolean mortal)
|
||||||
|
{
|
||||||
|
this.personId = personId;
|
||||||
|
this.name = name;
|
||||||
|
this.mortal = mortal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPersonId()
|
||||||
|
{
|
||||||
|
return personId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMortal()
|
||||||
|
{
|
||||||
|
return mortal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return String.format("Person { %d, %s, %s }", this.personId, this.name, this.mortal);
|
||||||
|
}
|
||||||
|
}
|
38
src/main/java/data/target/PersonTarget.java
Normal file
38
src/main/java/data/target/PersonTarget.java
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package data.target;
|
||||||
|
|
||||||
|
import data.Dataset;
|
||||||
|
|
||||||
|
public class PersonTarget implements Dataset
|
||||||
|
{
|
||||||
|
private int personId;
|
||||||
|
private String name;
|
||||||
|
private boolean mortal;
|
||||||
|
|
||||||
|
public PersonTarget(int personId, String name, boolean mortal)
|
||||||
|
{
|
||||||
|
this.personId = personId;
|
||||||
|
this.name = name;
|
||||||
|
this.mortal = mortal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPersonId()
|
||||||
|
{
|
||||||
|
return personId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMortal()
|
||||||
|
{
|
||||||
|
return mortal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return String.format("Person [ %d, %s, %s ]", this.personId, this.name, this.mortal);
|
||||||
|
}
|
||||||
|
}
|
43
src/main/java/etl/Extractor.java
Normal file
43
src/main/java/etl/Extractor.java
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package etl;
|
||||||
|
|
||||||
|
import data.Dataset;
|
||||||
|
import utils.DataStorer;
|
||||||
|
import utils.StatementPreparer;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Extractor<T extends Dataset>
|
||||||
|
{
|
||||||
|
private Connection sourceDatabase;
|
||||||
|
private DataStorer<T> dataStorer;
|
||||||
|
private ResultSet resultSet;
|
||||||
|
private String sql;
|
||||||
|
|
||||||
|
public Extractor(Connection sourceDatabase, DataStorer<T> dataStorer,
|
||||||
|
String sql)
|
||||||
|
{
|
||||||
|
this.sourceDatabase = sourceDatabase;
|
||||||
|
this.dataStorer = dataStorer;
|
||||||
|
this.sql = sql;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<T> doExtract()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var preparedStatement = this.sourceDatabase.prepareStatement(sql);
|
||||||
|
this.resultSet = preparedStatement.executeQuery();
|
||||||
|
this.sourceDatabase.close();
|
||||||
|
return this.dataStorer.doStore(this.resultSet);
|
||||||
|
}
|
||||||
|
catch (SQLException e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
44
src/main/java/etl/Loader.java
Normal file
44
src/main/java/etl/Loader.java
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package etl;
|
||||||
|
|
||||||
|
import data.Dataset;
|
||||||
|
import utils.StatementPreparer;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Loader<T extends Dataset>
|
||||||
|
{
|
||||||
|
private Connection targetDatabase;
|
||||||
|
private StatementPreparer<T> statementPreparer;
|
||||||
|
private List<T> transformedData;
|
||||||
|
private String sql;
|
||||||
|
|
||||||
|
public Loader(Connection targetDatabase, StatementPreparer<T> statementPreparer, List<T> transformedData,
|
||||||
|
String sql)
|
||||||
|
{
|
||||||
|
this.targetDatabase = targetDatabase;
|
||||||
|
this.statementPreparer = statementPreparer;
|
||||||
|
this.transformedData = transformedData;
|
||||||
|
this.sql = sql;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doLoad()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
for (T transformedDatum : this.transformedData)
|
||||||
|
{
|
||||||
|
var preparedStatement = this.targetDatabase.prepareStatement(this.sql);
|
||||||
|
this.statementPreparer.doPrepare(preparedStatement, transformedDatum);
|
||||||
|
preparedStatement.executeUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.targetDatabase.close();
|
||||||
|
}
|
||||||
|
catch (SQLException e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
30
src/main/java/etl/Transformer.java
Normal file
30
src/main/java/etl/Transformer.java
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package etl;
|
||||||
|
|
||||||
|
import data.Dataset;
|
||||||
|
import utils.DataTransformer;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Transformer<T extends Dataset, E extends Dataset>
|
||||||
|
{
|
||||||
|
|
||||||
|
private DataTransformer<T, E> transformer;
|
||||||
|
private List<T> datasets;
|
||||||
|
|
||||||
|
public Transformer(DataTransformer<T, E> transformer, List<T> datasets)
|
||||||
|
{
|
||||||
|
this.transformer = transformer;
|
||||||
|
this.datasets = datasets;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<E> doTransform()
|
||||||
|
{
|
||||||
|
var transformed = new ArrayList<E>();
|
||||||
|
for (T dataset : this.datasets)
|
||||||
|
{
|
||||||
|
transformed.add(this.transformer.transform(dataset));
|
||||||
|
}
|
||||||
|
return transformed;
|
||||||
|
}
|
||||||
|
}
|
65
src/main/java/utils/ConnectionHelper.java
Normal file
65
src/main/java/utils/ConnectionHelper.java
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
package utils;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.sql.*;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
public class ConnectionHelper
|
||||||
|
{
|
||||||
|
private final DatabaseType databaseType;
|
||||||
|
private final String user;
|
||||||
|
private final String password;
|
||||||
|
private URI uri;
|
||||||
|
|
||||||
|
public ConnectionHelper(final DatabaseType databaseType, final DatabaseInformation databaseInformation)
|
||||||
|
{
|
||||||
|
this.databaseType = databaseType;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.uri = new URI(this.databaseType.getScheme(),
|
||||||
|
null,
|
||||||
|
databaseInformation.getHost(),
|
||||||
|
databaseInformation.getPort(),
|
||||||
|
String.format("/%s", databaseInformation.getDatabaseName()),
|
||||||
|
null,
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
catch (final URISyntaxException e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.user = databaseInformation.getUser();
|
||||||
|
this.password = databaseInformation.getPassword();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Connection createConnection()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Class.forName(this.databaseType.getDriver());
|
||||||
|
}
|
||||||
|
catch (final ClassNotFoundException e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
Connection c = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
c = DriverManager.getConnection(this.uri.toString(), this.user, this.password);
|
||||||
|
}
|
||||||
|
catch (final SQLException e)
|
||||||
|
{
|
||||||
|
System.out.println("SQLException: " + e.getMessage());
|
||||||
|
System.out.println("SQLState: " + e.getSQLState());
|
||||||
|
System.out.println("VendorError: " + e.getErrorCode());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
12
src/main/java/utils/DataStorer.java
Normal file
12
src/main/java/utils/DataStorer.java
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package utils;
|
||||||
|
|
||||||
|
import data.Dataset;
|
||||||
|
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface DataStorer<T extends Dataset>
|
||||||
|
{
|
||||||
|
List<T> doStore(ResultSet resultSet) throws SQLException;
|
||||||
|
}
|
10
src/main/java/utils/DataTransformer.java
Normal file
10
src/main/java/utils/DataTransformer.java
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package utils;
|
||||||
|
|
||||||
|
import data.Dataset;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface DataTransformer<T extends Dataset, E extends Dataset>
|
||||||
|
{
|
||||||
|
E transform(T dataset);
|
||||||
|
}
|
5
src/main/java/utils/DatabaseHelper.java
Normal file
5
src/main/java/utils/DatabaseHelper.java
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package utils;
|
||||||
|
|
||||||
|
public class DatabaseHelper
|
||||||
|
{
|
||||||
|
}
|
51
src/main/java/utils/DatabaseInformation.java
Normal file
51
src/main/java/utils/DatabaseInformation.java
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package utils;
|
||||||
|
|
||||||
|
import com.mysql.cj.exceptions.NumberOutOfRange;
|
||||||
|
|
||||||
|
public class DatabaseInformation
|
||||||
|
{
|
||||||
|
private final String host;
|
||||||
|
private final String databaseName;
|
||||||
|
private final String user;
|
||||||
|
private final String password;
|
||||||
|
|
||||||
|
private int port;
|
||||||
|
|
||||||
|
public DatabaseInformation(final String host, final String databaseName, final String user, final String password, final int port)
|
||||||
|
{
|
||||||
|
this.host = host;
|
||||||
|
this.databaseName = databaseName;
|
||||||
|
this.user = user;
|
||||||
|
this.password = password;
|
||||||
|
|
||||||
|
if (port < 0 || port > 65535)
|
||||||
|
throw new NumberOutOfRange("A port must be between 0 and 65535");
|
||||||
|
else
|
||||||
|
this.port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHost()
|
||||||
|
{
|
||||||
|
return host;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDatabaseName()
|
||||||
|
{
|
||||||
|
return databaseName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUser()
|
||||||
|
{
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassword()
|
||||||
|
{
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPort()
|
||||||
|
{
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
}
|
27
src/main/java/utils/DatabaseType.java
Normal file
27
src/main/java/utils/DatabaseType.java
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package utils;
|
||||||
|
|
||||||
|
public enum DatabaseType
|
||||||
|
{
|
||||||
|
MARIADB("org.mariadb.jdbc.Driver", "jdbc:mariadb"),
|
||||||
|
MYSQL("com.mysql.cj.jdbc.Driver", "jdbc:mysql"),
|
||||||
|
POSTGRESQL("org.postgresql.Driver", "jdbc:postgresql");
|
||||||
|
|
||||||
|
private final String driver;
|
||||||
|
private final String scheme;
|
||||||
|
|
||||||
|
DatabaseType(final String driver, final String scheme)
|
||||||
|
{
|
||||||
|
this.driver = driver;
|
||||||
|
this.scheme = scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDriver()
|
||||||
|
{
|
||||||
|
return driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getScheme()
|
||||||
|
{
|
||||||
|
return scheme;
|
||||||
|
}
|
||||||
|
}
|
11
src/main/java/utils/StatementPreparer.java
Normal file
11
src/main/java/utils/StatementPreparer.java
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package utils;
|
||||||
|
|
||||||
|
import data.Dataset;
|
||||||
|
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
public interface StatementPreparer<T extends Dataset>
|
||||||
|
{
|
||||||
|
void doPrepare(PreparedStatement preparedStatement, T data) throws SQLException;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user