com.github.lontime.extjooq.batch.JooqBatch Maven / Gradle / Ivy
The newest version!
package com.github.lontime.extjooq.batch;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import com.github.lontime.base.pagination.Page;
import com.github.lontime.base.pagination.PageImpl;
import com.github.lontime.base.pagination.Pageable;
import com.github.lontime.base.commonj.utils.AssertHelper;
import com.github.lontime.base.commonj.utils.CollectionHelper;
import org.jooq.Condition;
import org.jooq.DSLContext;
import org.jooq.Field;
import org.jooq.InsertQuery;
import org.jooq.Record;
import org.jooq.Record1;
import org.jooq.Result;
import org.jooq.Table;
import org.jooq.TableField;
import org.jooq.UpdateQuery;
import org.jooq.impl.DSL;
/**
* JooqBatch.
*
* @author lontime
* @since 1.0
*/
public abstract class JooqBatch implements Batch {
@Override
public Page page(DSLContext context, Table extends Record> table, List fields, Condition condition, Pageable pageable, boolean searchCount) {
AssertHelper.checkNotNull(table, "Table is not null");
AssertHelper.checkNotNull(condition, "Condition is not null");
final List> sorts = pageable.getSort().get().map(c -> table.field(c.getProperty())).filter(Objects::nonNull).collect(Collectors.toList());
final CompletableFuture>> future;
if (searchCount) {
future = context.selectCount().from(table).where(condition).
fetchAsync().toCompletableFuture();
} else {
future = null;
}
final CompletableFuture> future1 = context.select
(CollectionHelper.isEmpty(fields) ? Arrays.asList(table.fields()) : fields)
.from(table).where(condition)
.orderBy(sorts).limit(pageable.getOffset(), pageable.getPageSize())
.fetchAsync().toCompletableFuture();
if (future == null) {
return new PageImpl(future1.join(), pageable, -1);
}
final Result> join = future.join();
final Integer total = join.get(0).value1();
if (total == 0) {
return new PageImpl(Collections.emptyList(), pageable, 0);
}
return new PageImpl(future1.join(), pageable, total);
}
@Override
public CompletableFuture updateAsync(DSLContext context, Table table,
Field keyField, Collection records) {
return Optional.ofNullable(buildUpdateQuery(context, table, keyField, records)).
map(c -> c.executeAsync().toCompletableFuture()).
orElse(CompletableFuture.completedFuture(new Integer(-1)));
}
@Override
public CompletableFuture updateAsync(DSLContext context, Table table,
List> keyField, Collection records) {
return Optional.ofNullable(buildUpdateQuery(context, table, keyField, records)).
map(c -> c.executeAsync().toCompletableFuture()).
orElse(CompletableFuture.completedFuture(new Integer(-1)));
}
@Override
public CompletableFuture insertAsync(DSLContext context, Table table,
Collection records) {
return buildInsertQuery(context, table, records).executeAsync().toCompletableFuture();
}
/**
* get concat.
*
* @return String
*/
abstract protected String getFuncConcat();
private InsertQuery buildInsertQuery(DSLContext context, Table table,
Collection records) {
final InsertQuery query = context.insertQuery(table);
for (R record : records) {
for (int i = 0; i < record.size(); i++) {
query.addValue((Field) record.field(i), record.get(i));
}
query.newRecord();
}
return query;
}
private UpdateQuery buildUpdateQuery(DSLContext context, Table table,
List> keyFields, Collection records) {
final Field>[] allFields = table.fields();
final UpdateQuery query = context.updateQuery(table);
if (keyFields == null || keyFields.isEmpty()) {
return null;
}
final List keyValues = records.stream().map(c -> getValue(keyFields, c)).
filter(Objects::nonNull).filter(c -> c.length() > 0).collect(Collectors.toList());
if (keyValues.isEmpty()) {
return null;
}
final List> newKeyFields = new ArrayList<>(keyFields.size() + 1);
newKeyFields.add(DSL.field("','"));
newKeyFields.addAll(keyFields.stream().collect(Collectors.toList()));
final Field condField = DSL.function(getFuncConcat(), String.class,
Arrays.copyOf(newKeyFields.toArray(), newKeyFields.size(), Field[].class));
boolean found = false;
for (int i = 0; i < allFields.length; i++) {
final Field> field = allFields[i];
if (keyFields.contains(field)) {
continue;
}
final Map map = new HashMap<>();
for (Record record : records) {
final String keyValue = getValue(keyFields, record);
final Object value = record.getValue(field);
if (Objects.isNull(keyValue) || keyValue.length() == 0 || Objects.isNull(value)) {
continue;
}
map.put(keyValue, value);
}
if (!map.isEmpty()) {
query.addValue(field, DSL.choose(condField).mapValues(map).otherwise((Field) field));
found = true;
}
}
if (!found) {
return null;
}
query.addConditions(condField.in(keyValues));
return query;
}
private UpdateQuery buildUpdateQuery(DSLContext context, Table table,
Field keyField, Collection records) {
final Field>[] allFields = table.fields();
final UpdateQuery query = context.updateQuery(table);
if (keyField == null) {
return null;
}
final List keyValues = records.stream().map(c -> c.get(keyField)).
filter(Objects::nonNull).collect(Collectors.toList());
if (keyValues.isEmpty()) {
return null;
}
boolean found = false;
for (int i = 0; i < allFields.length; i++) {
final Field> field = allFields[i];
if (field.equals(keyField)) {
continue;
}
final Map map = new HashMap<>();
for (Record record : records) {
final T keyValue = record.get(keyField);
final Object value = record.getValue(field);
if (Objects.isNull(keyValue) || Objects.isNull(value)) {
continue;
}
map.put(keyValue, value);
}
if (!map.isEmpty()) {
query.addValue(field, DSL.choose(keyField).mapValues(map).otherwise((Field) field));
found = true;
}
}
if (!found) {
return null;
}
query.addConditions(keyField.in(keyValues));
return query;
}
private String getValue(List> fields, Record record) {
return fields.stream().map(s -> record.get(s)).filter(Objects::nonNull).map(s -> s.toString())
.collect(Collectors.joining(","));
}
}