Skip to content

Commit 49dc7ad

Browse files
author
Philipp Wagner
committed
Initial Commit
0 parents  commit 49dc7ad

26 files changed

Lines changed: 828 additions & 0 deletions

JSqlServerBulkInsert/.gitignore

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
.gradle
2+
/local.properties
3+
.idea/workspace.xml
4+
.idea/libraries
5+
.DS_Store
6+
/out/production
7+
/out/test
8+
/captures
9+
/target
10+
/out
11+
.idea
12+
.iws
13+
workspace.xml
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
stderr.log
2+
stdout.log
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
:: Copyright (c) Philipp Wagner. All rights reserved.
2+
:: Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
@echo off
5+
6+
echo ---------------------------------------------------
7+
echo - Bundling Artifacts for OSSRH Repository Upload -
8+
echo ---------------------------------------------------
9+
10+
:: Define the Executables, so we don't have to rely on pathes:
11+
set MVN_EXECUTABLE="C:\Program Files (x86)\Maven\apache-maven-3.3.9\bin\mvn.cmd"
12+
set GPG_EXECUTABLE="C:\Program Files (x86)\GNU\GnuPG\pub\gpg.exe"
13+
14+
:: GPG Key ID used for signing:
15+
set GPG_KEY_ID=E4B54CD3
16+
17+
:: Logs to be used:
18+
set STDOUT=stdout.log
19+
set STDERR=stderr.log
20+
21+
:: POM File to use for building the project:
22+
set POM_FILE=..\pom.xml
23+
24+
:: Prompt for Sonatype:
25+
set /p SONATYPE_USER="Sonatype User: "
26+
set /p SONATYPE_PASSWORD="Sonatype Password: "
27+
28+
:: Prompt GPG Passphrase:
29+
set /p GPG_PASSPHRASE="GPG Signing Passphrase: "
30+
31+
1>%STDOUT% 2>%STDERR% (
32+
33+
%MVN_EXECUTABLE% clean deploy -Prelease,docs-and-source --settings deploysettings.xml -DskipTests -Dgpg.keyname=%GPG_KEY_ID% -Dgpg.executable=%GPG_EXECUTABLE% -Dgpg.passphrase=%GPG_PASSPHRASE% -DretryFailedDeploymentCount=3 -f %POM_FILE%
34+
35+
)
36+
37+
pause
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
2+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
4+
http://maven.apache.org/xsd/settings-1.0.0.xsd">
5+
<servers>
6+
<server>
7+
<id>ossrh</id>
8+
<username>${SONATYPE_USER}</username>
9+
<password>${SONATYPE_PASSWORD}</password>
10+
</server>
11+
</servers>
12+
</settings>
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
3+
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8" inherit-compiler-output="false">
4+
<output url="file://$MODULE_DIR$/target/classes" />
5+
<output-test url="file://$MODULE_DIR$/target/test-classes" />
6+
<content url="file://$MODULE_DIR$">
7+
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
8+
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
9+
<excludeFolder url="file://$MODULE_DIR$/target" />
10+
</content>
11+
<orderEntry type="inheritedJdk" />
12+
<orderEntry type="sourceFolder" forTests="false" />
13+
<orderEntry type="library" name="Maven: com.microsoft.sqlserver:mssql-jdbc:6.1.0.jre8" level="project" />
14+
<orderEntry type="library" name="Maven: com.microsoft.azure:azure-keyvault:0.9.3" level="project" />
15+
<orderEntry type="library" name="Maven: com.microsoft.azure:azure-core:0.9.3" level="project" />
16+
<orderEntry type="library" name="Maven: commons-codec:commons-codec:1.10" level="project" />
17+
<orderEntry type="library" name="Maven: commons-lang:commons-lang:2.6" level="project" />
18+
<orderEntry type="library" name="Maven: javax.mail:mail:1.4.5" level="project" />
19+
<orderEntry type="library" name="Maven: javax.activation:activation:1.1" level="project" />
20+
<orderEntry type="library" name="Maven: com.sun.jersey:jersey-client:1.13" level="project" />
21+
<orderEntry type="library" name="Maven: com.sun.jersey:jersey-core:1.13" level="project" />
22+
<orderEntry type="library" name="Maven: com.sun.jersey:jersey-json:1.13" level="project" />
23+
<orderEntry type="library" name="Maven: org.codehaus.jettison:jettison:1.1" level="project" />
24+
<orderEntry type="library" name="Maven: stax:stax-api:1.0.1" level="project" />
25+
<orderEntry type="library" name="Maven: com.sun.xml.bind:jaxb-impl:2.2.3-1" level="project" />
26+
<orderEntry type="library" name="Maven: javax.xml.bind:jaxb-api:2.2.2" level="project" />
27+
<orderEntry type="library" name="Maven: javax.xml.stream:stax-api:1.0-2" level="project" />
28+
<orderEntry type="library" name="Maven: org.codehaus.jackson:jackson-core-asl:1.9.2" level="project" />
29+
<orderEntry type="library" name="Maven: org.codehaus.jackson:jackson-mapper-asl:1.9.2" level="project" />
30+
<orderEntry type="library" name="Maven: org.codehaus.jackson:jackson-jaxrs:1.9.2" level="project" />
31+
<orderEntry type="library" name="Maven: org.codehaus.jackson:jackson-xc:1.9.2" level="project" />
32+
<orderEntry type="library" name="Maven: org.apache.httpcomponents:httpclient:4.3.6" level="project" />
33+
<orderEntry type="library" name="Maven: org.apache.httpcomponents:httpcore:4.3.3" level="project" />
34+
<orderEntry type="library" name="Maven: commons-logging:commons-logging:1.1.3" level="project" />
35+
<orderEntry type="library" name="Maven: javax.inject:javax.inject:1" level="project" />
36+
<orderEntry type="library" name="Maven: com.microsoft.azure:adal4j:1.0.0" level="project" />
37+
<orderEntry type="library" name="Maven: com.nimbusds:oauth2-oidc-sdk:4.5" level="project" />
38+
<orderEntry type="library" name="Maven: net.jcip:jcip-annotations:1.0" level="project" />
39+
<orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.3.1" level="project" />
40+
<orderEntry type="library" name="Maven: net.minidev:json-smart:1.1.1" level="project" />
41+
<orderEntry type="library" name="Maven: com.nimbusds:lang-tag:1.4" level="project" />
42+
<orderEntry type="library" name="Maven: com.nimbusds:nimbus-jose-jwt:3.1.2" level="project" />
43+
<orderEntry type="library" name="Maven: org.bouncycastle:bcprov-jdk15on:1.51" level="project" />
44+
<orderEntry type="library" name="Maven: com.google.code.gson:gson:2.2.4" level="project" />
45+
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.5" level="project" />
46+
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.12" level="project" />
47+
<orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
48+
</component>
49+
</module>

JSqlServerBulkInsert/pom.xml

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
6+
<modelVersion>4.0.0</modelVersion>
7+
8+
<groupId>de.bytefish</groupId>
9+
<artifactId>jsqlserverbulkinsert</artifactId>
10+
<version>1.3</version>
11+
<name>jsqlserverbulkinsert</name>
12+
<description>JSqlServerBulkInsert is a Java library for Bulk Inserts with PostgreSQL.</description>
13+
<url>http://www.github.com/bytefish/JSqlServerBulkInsert</url>
14+
15+
<!-- Define the License -->
16+
<licenses>
17+
<license>
18+
<name>MIT License</name>
19+
<url>https://opensource.org/licenses/MIT</url>
20+
</license>
21+
</licenses>
22+
23+
<!-- Source Management -->
24+
<scm>
25+
<url>https://github.com/bytefish/JSqlServerBulkInsert</url>
26+
<connection>scm:git:git://github.com/bytefish/JSqlServerBulkInsert.git</connection>
27+
<developerConnection>scm:git:git@github.com:bytefish/JSqlServerBulkInsert.git</developerConnection>
28+
</scm>
29+
30+
<!-- Developers -->
31+
<developers>
32+
<developer>
33+
<email>bytefish@gmx.de</email>
34+
<name>Philipp Wagner</name>
35+
<url>http://www.bytefish.de</url>
36+
<id>bytefish</id>
37+
</developer>
38+
</developers>
39+
40+
<!-- Build Information -->
41+
<build>
42+
<plugins>
43+
<plugin>
44+
<groupId>org.apache.maven.plugins</groupId>
45+
<artifactId>maven-compiler-plugin</artifactId>
46+
<configuration>
47+
<source>1.8</source>
48+
<target>1.8</target>
49+
</configuration>
50+
</plugin>
51+
</plugins>
52+
</build>
53+
54+
<properties>
55+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
56+
<sqlserver.version>6.1.0.jre8</sqlserver.version>
57+
</properties>
58+
59+
<dependencies>
60+
61+
<dependency>
62+
<groupId>com.microsoft.sqlserver</groupId>
63+
<artifactId>mssql-jdbc</artifactId>
64+
<version>6.1.0.jre8</version>
65+
</dependency>
66+
67+
68+
<dependency>
69+
<groupId>junit</groupId>
70+
<artifactId>junit</artifactId>
71+
<version>4.12</version>
72+
<scope>test</scope>
73+
</dependency>
74+
75+
</dependencies>
76+
77+
</project>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright (c) Philipp Wagner. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
package de.bytefish.jsqlserverbulkinsert;
5+
6+
import java.sql.Connection;
7+
import java.sql.SQLException;
8+
import java.util.stream.Stream;
9+
10+
public interface ISqlServerBulkInsert<TEntity> {
11+
12+
void saveAll(Connection connection, Stream<TEntity> entities) throws SQLException;
13+
14+
}
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
// Copyright (c) Philipp Wagner. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
package de.bytefish.jsqlserverbulkinsert;
5+
6+
import com.microsoft.sqlserver.jdbc.ISQLServerBulkRecord;
7+
import com.microsoft.sqlserver.jdbc.SQLServerBulkCopy;
8+
import de.bytefish.jsqlserverbulkinsert.functional.Func2;
9+
import de.bytefish.jsqlserverbulkinsert.model.ColumnDefinition;
10+
import de.bytefish.jsqlserverbulkinsert.model.ColumnMetaData;
11+
import de.bytefish.jsqlserverbulkinsert.model.TableDefinition;
12+
import de.bytefish.jsqlserverbulkinsert.sqlserver.converters.IValueConverterProvider;
13+
import de.bytefish.jsqlserverbulkinsert.records.SqlServerRecordBuilder;
14+
15+
import java.math.BigDecimal;
16+
import java.math.BigInteger;
17+
import java.math.RoundingMode;
18+
import java.sql.Connection;
19+
import java.sql.SQLException;
20+
import java.sql.Types;
21+
import java.time.LocalDate;
22+
import java.time.OffsetDateTime;
23+
import java.time.OffsetTime;
24+
import java.util.*;
25+
import java.util.stream.Stream;
26+
27+
public abstract class SqlServerBulkInsert<TEntity> implements ISqlServerBulkInsert<TEntity> {
28+
29+
private TableDefinition table;
30+
31+
private List<ColumnDefinition<TEntity>> columns;
32+
33+
public SqlServerBulkInsert(String schemaName, String tableName)
34+
{
35+
this.table = new TableDefinition(schemaName, tableName);
36+
this.columns = new ArrayList<>();
37+
}
38+
39+
public void saveAll(Connection connection, Stream<TEntity> entities) throws SQLException {
40+
41+
final SqlServerRecordBuilder<TEntity> sqlServerRecordBuilder = new SqlServerRecordBuilder<>(columns);
42+
43+
try (SQLServerBulkCopy sqlServerBulkCopy = new SQLServerBulkCopy(connection)) {
44+
45+
// The Destination Table to write to:
46+
sqlServerBulkCopy.setDestinationTableName(table.GetFullQualifiedTableName());
47+
48+
entities
49+
.map(x -> sqlServerRecordBuilder.build(x))
50+
.forEach(x -> internalWriteToServer(sqlServerBulkCopy, x));
51+
}
52+
}
53+
54+
public void internalWriteToServer(SQLServerBulkCopy sqlServerBulkCopy, ISQLServerBulkRecord record) {
55+
try {
56+
sqlServerBulkCopy.writeToServer(record);
57+
} catch(Exception e) {
58+
throw new RuntimeException(e);
59+
}
60+
}
61+
62+
protected void mapBoolean(String columnName, Func2<TEntity, Boolean> propertyGetter) {
63+
addColumn(columnName, Types.BOOLEAN, propertyGetter);
64+
}
65+
66+
protected void mapNumeric(String columnName, int scale, int precision, Func2<TEntity, BigDecimal> propertyGetter)
67+
{
68+
addColumn(columnName, Types.NUMERIC, precision, scale, false, propertyGetter);
69+
}
70+
71+
protected void mapDecimal(String columnName, int scale, int precision, Func2<TEntity, BigDecimal> propertyGetter)
72+
{
73+
// We need to scale the incoming decimal, before writing it to SQL Server:
74+
final Func2<TEntity, BigDecimal> wrapper = entity -> {
75+
BigDecimal result = propertyGetter.invoke(entity);
76+
77+
return result.setScale(scale, RoundingMode.HALF_UP);
78+
};
79+
80+
addColumn(columnName, Types.DECIMAL, precision, scale, false, wrapper);
81+
}
82+
83+
protected void mapReal(String columnName, Func2<TEntity, Float> propertyGetter)
84+
{
85+
addColumn(columnName, Types.REAL, propertyGetter);
86+
}
87+
88+
protected void mapBigInt(String columnName, Func2<TEntity, BigInteger> propertyGetter) {
89+
90+
// SQL Server expects the Big Integer as a Long Value:
91+
final Func2<TEntity, Long> wrapper = entity -> {
92+
BigInteger resultAsBigInteger = propertyGetter.invoke(entity);
93+
94+
return resultAsBigInteger.longValueExact();
95+
};
96+
97+
addColumn(columnName, Types.BIGINT, wrapper);
98+
}
99+
100+
protected void mapDate(String columnName, Func2<TEntity, LocalDate> propertyGetter) {
101+
addColumn(columnName, Types.DATE, propertyGetter);
102+
}
103+
104+
protected void mapDouble(String columnName, Func2<TEntity, Double> propertyGetter)
105+
{
106+
addColumn(columnName, Types.DOUBLE, propertyGetter);
107+
}
108+
109+
protected void mapSmallInt(String columnName, Func2<TEntity, String> propertyGetter)
110+
{
111+
addColumn(columnName, Types.SMALLINT, propertyGetter);
112+
}
113+
114+
protected void mapTinyInt(String columnName, Func2<TEntity, String> propertyGetter)
115+
{
116+
addColumn(columnName, Types.TINYINT, propertyGetter);
117+
}
118+
119+
protected void mapTimeWithTimeZone(String columnName, Func2<TEntity, OffsetTime> propertyGetter) {
120+
addColumn(columnName, 2013, propertyGetter);
121+
}
122+
123+
protected void mapDateTimeWithTimeZone(String columnName, Func2<TEntity, OffsetDateTime> propertyGetter) {
124+
addColumn(columnName, 2014, propertyGetter);
125+
}
126+
127+
private void addColumn(String name, int type, boolean isAutoIncrement, Func2<TEntity, Object> propertyGetter)
128+
{
129+
// Create the current Column Meta Data:
130+
ColumnMetaData columnMetaData = new ColumnMetaData(name, type, 0, 0, isAutoIncrement);
131+
132+
// Add a new Column with the Meta Data and Property Getter:
133+
addColumn(columnMetaData, propertyGetter);
134+
}
135+
136+
private <TProperty> void addColumn(String name, int type, Func2<TEntity, TProperty> propertyGetter)
137+
{
138+
// Create the current Column Meta Data:
139+
ColumnMetaData columnMetaData = new ColumnMetaData(name, type);
140+
141+
// Add a new Column with the Meta Data and Property Getter:
142+
addColumn(columnMetaData, propertyGetter);
143+
}
144+
145+
private <TProperty> void addColumn(String name, int type, int precision, int scale, boolean isAutoIncrement, Func2<TEntity, TProperty> propertyGetter)
146+
{
147+
// Create the current Column Meta Data:
148+
ColumnMetaData columnMetaData = new ColumnMetaData(name, type, precision, scale, isAutoIncrement);
149+
150+
// Add a new Column with the Meta Data and Property Getter:
151+
152+
addColumn(columnMetaData, propertyGetter);
153+
}
154+
155+
private <TProperty> void addColumn(ColumnMetaData columnMetaData, Func2<TEntity, TProperty> propertyGetter)
156+
{
157+
// Add a new Column with the Meta Data and Property Getter:
158+
columns.add(new ColumnDefinition(columnMetaData, propertyGetter));
159+
}
160+
}

0 commit comments

Comments
 (0)