Skip to content

Commit c246bee

Browse files
author
Philipp Wagner
committed
Fix SqlServerBulkInsert
Unit Test Successful
1 parent 47a88c8 commit c246bee

4 files changed

Lines changed: 48 additions & 33 deletions

File tree

JSqlServerBulkInsert/src/main/java/de/bytefish/jsqlserverbulkinsert/SqlServerBulkInsert.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55

66
import com.microsoft.sqlserver.jdbc.ISQLServerBulkRecord;
77
import com.microsoft.sqlserver.jdbc.SQLServerBulkCopy;
8+
import com.microsoft.sqlserver.jdbc.SQLServerBulkCopyOptions;
89
import de.bytefish.jsqlserverbulkinsert.functional.Func2;
910
import de.bytefish.jsqlserverbulkinsert.model.ColumnDefinition;
1011
import de.bytefish.jsqlserverbulkinsert.model.ColumnMetaData;
1112
import de.bytefish.jsqlserverbulkinsert.model.TableDefinition;
13+
import de.bytefish.jsqlserverbulkinsert.records.SqlServerRecord;
1214
import de.bytefish.jsqlserverbulkinsert.records.SqlServerRecordBuilder;
1315

1416
import java.math.BigDecimal;
@@ -36,17 +38,26 @@ public SqlServerBulkInsert(String schemaName, String tableName)
3638
}
3739

3840
public void saveAll(Connection connection, Stream<TEntity> entities) throws SQLException {
41+
saveAll(connection, new SQLServerBulkCopyOptions(), entities);
42+
}
43+
44+
public void saveAll(Connection connection, SQLServerBulkCopyOptions options, Stream<TEntity> entities) throws SQLException {
3945

4046
final SqlServerRecordBuilder<TEntity> sqlServerRecordBuilder = new SqlServerRecordBuilder<>(columns);
4147

4248
try (SQLServerBulkCopy sqlServerBulkCopy = new SQLServerBulkCopy(connection)) {
4349

50+
// Set the Options:
51+
sqlServerBulkCopy.setBulkCopyOptions(options);
52+
4453
// The Destination Table to write to:
4554
sqlServerBulkCopy.setDestinationTableName(table.GetFullQualifiedTableName());
4655

47-
entities
48-
.map(x -> sqlServerRecordBuilder.build(x))
49-
.forEach(x -> internalWriteToServer(sqlServerBulkCopy, x));
56+
// The SQL Records to insert:
57+
ISQLServerBulkRecord record = new SqlServerRecord<TEntity>(columns, entities.iterator());
58+
59+
// Finally start the Bulk Copy Process:
60+
internalWriteToServer(sqlServerBulkCopy, record);
5061
}
5162
}
5263

JSqlServerBulkInsert/src/main/java/de/bytefish/jsqlserverbulkinsert/records/SqlServerRecord.java

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,40 @@
55

66
import com.microsoft.sqlserver.jdbc.ISQLServerBulkRecord;
77
import com.microsoft.sqlserver.jdbc.SQLServerException;
8+
import de.bytefish.jsqlserverbulkinsert.model.ColumnDefinition;
89
import de.bytefish.jsqlserverbulkinsert.model.ColumnMetaData;
910

11+
import java.util.Iterator;
1012
import java.util.List;
1113
import java.util.Set;
1214
import java.util.stream.Collectors;
1315
import java.util.stream.IntStream;
16+
import java.util.stream.Stream;
1417

15-
public class SqlServerRecord implements ISQLServerBulkRecord {
18+
public class SqlServerRecord<TEntity> implements ISQLServerBulkRecord {
19+
20+
private final Iterator<TEntity> entities;
1621

1722
private final List<ColumnMetaData> columnMetaData;
18-
private final Object[] values;
1923

20-
public SqlServerRecord(List<ColumnMetaData> columnMetaData, Object[] values) {
21-
if(columnMetaData == null) {
22-
throw new IllegalArgumentException("columnMetaData");
24+
private final SqlServerRecordBuilder<TEntity> builder;
25+
26+
public SqlServerRecord(List<ColumnDefinition<TEntity>> columnDefinition, Iterator<TEntity> entities) {
27+
if(columnDefinition == null) {
28+
throw new IllegalArgumentException("columnDefinition");
2329
}
24-
if(values == null) {
25-
throw new IllegalArgumentException("values");
30+
if(entities == null) {
31+
throw new IllegalArgumentException("entities");
2632
}
27-
this.columnMetaData = columnMetaData;
28-
this.values = values;
33+
this.entities = entities;
34+
35+
// Cache the Column Meta Data, so we don't calculate it for each Record:
36+
this.columnMetaData = columnDefinition.stream()
37+
.map(x -> x.getColumnMetaData())
38+
.collect(Collectors.toList());
39+
40+
// Cache a Values Builder to populate Records faster:
41+
this.builder = new SqlServerRecordBuilder<TEntity>(columnDefinition);
2942
}
3043

3144
@Override
@@ -64,11 +77,13 @@ public boolean isAutoIncrement(int i) {
6477

6578
@Override
6679
public Object[] getRowData() throws SQLServerException {
67-
return values;
80+
TEntity entity = entities.next();
81+
82+
return builder.build(entity);
6883
}
6984

7085
@Override
7186
public boolean next() throws SQLServerException {
72-
return false;
87+
return entities.hasNext();
7388
}
7489
}

JSqlServerBulkInsert/src/main/java/de/bytefish/jsqlserverbulkinsert/records/SqlServerRecordBuilder.java

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,32 +12,19 @@
1212
public class SqlServerRecordBuilder<TEntity> {
1313

1414
private final List<ColumnDefinition<TEntity>> columns;
15-
private final List<ColumnMetaData> columnMetaData;
1615

1716
public SqlServerRecordBuilder(List<ColumnDefinition<TEntity>> columns) {
1817
if(columns == null) {
1918
throw new IllegalArgumentException("columns");
2019
}
21-
22-
// Holds the Columns:
2320
this.columns = columns;
24-
25-
// Cache the Column Meta Data, so we don't calculate it for each Record:
26-
this.columnMetaData = columns.stream()
27-
.map(x -> x.getColumnMetaData())
28-
.collect(Collectors.toList());
2921
}
3022

31-
public SqlServerRecord build(final TEntity entity) {
32-
23+
public Object[] build(final TEntity entity) {
3324
// Get the Values for each column:
34-
Object[] values = columns.stream()
25+
return columns.stream()
3526
.map(x -> x.getPropertyValue(entity))
3627
.toArray();
37-
38-
// And finally build the SqlServerRecord:
39-
return new SqlServerRecord(columnMetaData, values);
40-
4128
}
4229

4330
}

JSqlServerBulkInsert/src/test/java/de/bytefish/jsqlserverbulkinsert/IntegrationTest.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,16 @@ protected void onSetUpInTransaction() throws Exception {
3333

3434
@Test
3535
public void bulkInsertPersonDataTest() throws SQLException {
36+
// The Number of Entities to insert:
37+
int numEntities = 1000000;
3638
// Create a large list of Persons:
37-
List<Person> persons = getPersonList(100000);
39+
List<Person> persons = getPersonList(numEntities);
3840
// Create the BulkInserter:
3941
PersonBulkInserter personBulkInserter = new PersonBulkInserter();
4042
// Now save all entities of a given stream:
4143
personBulkInserter.saveAll(connection, persons.stream());
4244
// And assert all have been written to the database:
43-
Assert.assertEquals(100000, getRowCount());
45+
Assert.assertEquals(numEntities, getRowCount());
4446
}
4547

4648
private List<Person> getPersonList(int numPersons) {
@@ -77,9 +79,9 @@ private int getRowCount() throws SQLException {
7779

7880
Statement s = connection.createStatement();
7981

80-
ResultSet r = s.executeQuery("SELECT COUNT(*) AS rowcount FROM [dbo].[UnitTest]");
82+
ResultSet r = s.executeQuery("SELECT COUNT(*) AS total FROM [dbo].[UnitTest];");
8183
r.next();
82-
int count = r.getInt("rowcount");
84+
int count = r.getInt("total");
8385
r.close();
8486

8587
return count;

0 commit comments

Comments
 (0)