Skip to content

Commit 5edfc95

Browse files
committed
Improve the saving part.
1 parent 8c50bac commit 5edfc95

3 files changed

Lines changed: 93 additions & 53 deletions

File tree

Database/src/main/java/org/broken/arrow/library/database/construct/query/builder/UpdateBuilder.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public class UpdateBuilder {
2222
private final Map<Integer, Object> values = new LinkedHashMap<>();
2323
private final Selector<ColumnBuilder<Column, Void>,Column> selector;
2424
private int columnIndex = 1;
25-
25+
private boolean built;
2626
/**
2727
* Constructs an UpdateBuilder for the given QueryBuilder context.
2828
*
@@ -51,6 +51,7 @@ public UpdateBuilder put(final String column, final Object value) {
5151
* @return this UpdateBuilder instance for chaining
5252
*/
5353
public UpdateBuilder put(final Column column, final Object value) {
54+
if (built) return this;
5455
updateData.put(column.getColumnName(), value);
5556
values.put(columnIndex++, value);
5657
return this;
@@ -63,6 +64,7 @@ public UpdateBuilder put(final Column column, final Object value) {
6364
* @return this UpdateBuilder instance for chaining
6465
*/
6566
public UpdateBuilder putAll(Map<Column, Object> map) {
67+
if (built) return this;
6668
map.forEach(this::put);
6769
return this;
6870
}
@@ -73,6 +75,7 @@ public UpdateBuilder putAll(Map<Column, Object> map) {
7375
* @return selector instance
7476
*/
7577
public Selector<ColumnBuilder<Column, Void>,Column> getSelector() {
78+
if (built) return null;
7679
return selector;
7780
}
7881

@@ -82,7 +85,9 @@ public Selector<ColumnBuilder<Column, Void>,Column> getSelector() {
8285
* @return map of column names to values
8386
*/
8487
public Map<String, Object> build() {
85-
processWhereValues();
88+
if (!built)
89+
processWhereValues();
90+
built = true;
8691
return updateData;
8792
}
8893

Database/src/main/java/org/broken/arrow/library/database/core/Database.java

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -668,19 +668,35 @@ private void preparePrimaryKeyMigration(final Connection connection, final SqlQu
668668

669669
Validate.checkBoolean(!primaryWrapper.isSet() && !primaryWrapper.isUnique(), "Your new primary columns is set as primary key and you lack the values that must be set before set constraint to primary, it could set it to unique if set this to true setUnique.");
670670

671+
final List<QueryBuilder> saveQueryList = new ArrayList<>();
672+
final List<Column> primaryColumns = queryTable.getPrimaryColumns();
673+
for (DataWrapper.PrimaryWrapper primary : primaryWrapper.getPrimaryWrappers()) {
674+
final QueryBuilder saveBuilder = new QueryBuilder();
675+
saveBuilder.update(queryTable.getTableName()).putAll(primaryWrapper.convert(primary.getPrimaryKeys())).getSelector().where(whereBuilder -> {
676+
if (primary.getWhereClause() == null)
677+
return null;
678+
return primary.getWhereClause().apply(whereBuilder);
679+
});
680+
saveQueryList.add(saveBuilder);
681+
}
671682

672-
List<Column> primaryColumns = queryTable.getPrimaryColumns();
673-
boolean primaryValuesComplete = true;
674-
for (final String column : newPrimaryKeys) {
675-
if (primaryWrapper.getPrimaryValue(column) == null) {
676-
primaryValuesComplete = false;
677-
break;
683+
for (QueryBuilder saveQuery : saveQueryList) {
684+
try (final PreparedStatement preparedStatement = connection.prepareStatement(saveQuery.build())) {
685+
for (Entry<Integer, Object> entry : saveQuery.getValues().entrySet()) {
686+
preparedStatement.setObject(entry.getKey(), entry.getValue());
687+
}
688+
preparedStatement.addBatch();
689+
preparedStatement.executeBatch();
690+
} catch (final SQLException throwable) {
691+
log.log(throwable, () -> "Could not save the columns with query '" + saveQuery + "'. From this table '" + queryTable.getTableName() + "'");
678692
}
679693
}
694+
695+
boolean primaryValuesComplete = primaryWrapper.allPrimaryValuesPresent(newPrimaryKeys);
680696
Validate.checkBoolean(!primaryValuesComplete && !primaryWrapper.isUnique(), "Your new primary columns is set as primary key, one or several you want to set primary key is not set in the consumer cache.");
681697

682-
List<Column> nextPrimaryColumns = new ArrayList<>();
683-
List<Column> fallbackUniqueColumns = new ArrayList<>();
698+
final List<Column> nextPrimaryColumns = new ArrayList<>();
699+
final List<Column> fallbackUniqueColumns = new ArrayList<>();
684700
for (final Column column : primaryColumns) {
685701
if (primaryWrapper.isSet() && primaryValuesComplete) {
686702
nextPrimaryColumns.add(column);
Lines changed: 62 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.broken.arrow.library.database.utility;
22

3+
import org.broken.arrow.library.database.builders.DataWrapper;
34
import org.broken.arrow.library.database.builders.LoadDataWrapper;
45
import org.broken.arrow.library.database.builders.tables.SqlQueryTable;
56
import org.broken.arrow.library.database.construct.query.builder.CreateTableHandler;
@@ -9,9 +10,7 @@
910

1011
import javax.annotation.Nonnull;
1112
import javax.annotation.Nullable;
12-
import java.util.HashMap;
13-
import java.util.List;
14-
import java.util.Map;
13+
import java.util.*;
1514
import java.util.function.Consumer;
1615

1716

@@ -25,11 +24,11 @@
2524
* </p>
2625
*/
2726
public class PrimaryConstraintWrapper {
28-
final Map<String, Object> primaryKeys = new HashMap<>();
27+
private final List<DataWrapper.PrimaryWrapper> primaryWrappers = new ArrayList<>();
2928
private final Database database;
3029
private final SqlQueryTable queryTable;
3130
private Consumer<Map<String, Object>> loadMapFromDB;
32-
private WhereClauseFunction whereClause;
31+
3332
private boolean unique;
3433

3534

@@ -39,54 +38,40 @@ public PrimaryConstraintWrapper(final Database database, final SqlQueryTable que
3938
}
4039

4140
/**
42-
* Adds a primary key column and its associated value.
43-
*
44-
* @param key primary key column name
45-
* @param value primary key value
46-
*/
47-
public void putPrimary(@Nonnull final String key, @Nonnull final Object value) {
48-
primaryKeys.put(key, value);
49-
}
50-
51-
/**
52-
* Set where it shall update data or get data from database.
41+
* Adds a primary key column and its associated WhereClause.
5342
*
54-
* @param whereClause where constructor to create your clause.
43+
* @param primaryColumnsData the {@link DataWrapper.PrimaryWrapper} instance with the where clause and the map with the values that need to be updated.
5544
*/
56-
public void setWhereClause(final WhereClauseFunction whereClause) {
57-
this.whereClause = whereClause;
45+
public void addQueryData(@Nonnull final DataWrapper.PrimaryWrapper primaryColumnsData) {
46+
primaryWrappers.add(primaryColumnsData);
5847
}
5948

6049
/**
6150
* Returns the primary key column-value mappings.
6251
*
63-
* @return map of primary keys
52+
* @return List of primary data wrapper.
6453
*/
6554
@Nonnull
66-
public Map<String, Object> getPrimaryKeys() {
67-
return primaryKeys;
55+
public List<DataWrapper.PrimaryWrapper> getPrimaryWrappers() {
56+
return primaryWrappers;
6857
}
6958

7059
/**
7160
* Returns the primary key column-value mappings.
7261
*
73-
* @param key primary key column name
74-
* @return the value to your primary key or {@code null} if not exist.
62+
* @return Returns {@code true} if the column is set.
7563
*/
76-
@Nullable
77-
public Object getPrimaryValue(@Nonnull final String key) {
78-
return primaryKeys.get(key);
64+
public boolean allPrimaryValuesPresent(@Nonnull final Set<String> keys) {
65+
for (DataWrapper.PrimaryWrapper wrapper : primaryWrappers) {
66+
for (String key : keys) {
67+
if (wrapper.getPrimaryValue(key) == null) {
68+
return false;
69+
}
70+
}
71+
}
72+
return true;
7973
}
8074

81-
/**
82-
* Returns the custom WHERE clause applier, if present.
83-
*
84-
* @return WHERE clause applier or {@code null}
85-
*/
86-
@Nullable
87-
public WhereClauseFunction getWhereClause() {
88-
return whereClause;
89-
}
9075

9176
/**
9277
* If it shall replace the primary key with unique if you not provide
@@ -113,15 +98,17 @@ public void setUnique(final boolean unique) {
11398
* @return Returns {true} if at least one value added and the whereClause is not null
11499
*/
115100
public boolean isSet() {
116-
return !(primaryKeys.isEmpty() && whereClause == null);
117-
}
118-
119-
public void loadMap(Map<String, Object> dataFromDB) {
120-
if (this.loadMapFromDB == null) return;
121-
122-
this.loadMapFromDB.accept(dataFromDB);
101+
return !(primaryWrappers.isEmpty());
123102
}
124103

104+
/**
105+
* Retrieve the loaded data from the database. It will go through every row, and you can use {@link #addQueryData(DataWrapper.PrimaryWrapper)}
106+
* to set the new primary key value or if you have several, this columns name and value will be updated to the database.
107+
*
108+
* @param loadedData the callback when loading the data set in the database.
109+
* @param clazz the class to resolve.
110+
* @param <T> the generic type for that class that implements ConfigurationSerializable.
111+
*/
125112
public <T extends ConfigurationSerializable> void forEachLoadedData(Consumer<LoadDataWrapper<T>> loadedData, Class<T> clazz) {
126113
final CreateTableHandler tableHandler = this.queryTable.getTable();
127114
this.loadMapFromDB = (dataFromDB) -> {
@@ -138,8 +125,40 @@ public <T extends ConfigurationSerializable> void forEachLoadedData(Consumer<Loa
138125
};
139126
}
140127

128+
129+
/**
130+
* Retrieve the loaded data from the database. It will go through every row, and you can use {@link #addQueryData(DataWrapper.PrimaryWrapper)}
131+
* to set the new primary key value or if you have several, this columns name and value will be updated to the database.
132+
* <p>
133+
* You will get it as raw data from the database insted of {@link #forEachLoadedData(Consumer, Class)} that gives you a consumer
134+
* with the raw map with all columns and values set in the database.
135+
*
136+
* @param loadedData the callback when loading the data set in the database.
137+
*/
141138
public void forEachLoadedData(Consumer<Map<String, Object>> loadedData) {
142139
this.loadMapFromDB = loadedData;
143140
}
144141

142+
/**
143+
* Used internally only this method.
144+
*
145+
* @param dataFromDB the map of raw values from the database.
146+
*/
147+
public void loadMap(Map<String, Object> dataFromDB) {
148+
if (this.loadMapFromDB == null) return;
149+
150+
this.loadMapFromDB.accept(dataFromDB);
151+
}
152+
153+
/**
154+
* Used internally only this method.
155+
*
156+
* @param primaryKeys the list of primary column and the key to convert to
157+
* @return the map converted to a column and the object/value.
158+
*/
159+
public Map<Column, Object> convert(final Map<String, Object> primaryKeys) {
160+
final Map<Column, Object> map = new HashMap<>();
161+
primaryKeys.forEach((key, value) -> map.put(new Column(key, ""), value));
162+
return map;
163+
}
145164
}

0 commit comments

Comments
 (0)