Skip to content

refactor: 重构builder,正确使用构建者模式 #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/main/java/cn/icuter/jsql/builder/AbstractBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public abstract class AbstractBuilder implements Builder {
private String buildSql;
protected BuilderContext builderContext;

SQLStringBuilder sqlStringBuilder = new SQLStringBuilder();
protected SQLStringBuilder sqlStringBuilder = new SQLStringBuilder();
protected List<Condition> conditionList = new LinkedList<>();
private List<Object> preparedValueList;
private int offset;
Expand Down Expand Up @@ -214,7 +214,7 @@ public Builder build() {
return this;
}

private void addPreparedValue(List<Object> list, Object condValue) {
protected void addPreparedValue(List<Object> list, Object condValue) {
if (condValue == null) {
list.add(null);
} else if (condValue.getClass().isArray() && !(condValue instanceof byte[])) {
Expand Down
20 changes: 20 additions & 0 deletions src/main/java/cn/icuter/jsql/executor/DefaultJdbcExecutor.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import cn.icuter.jsql.exception.JSQLException;
import cn.icuter.jsql.log.JSQLLogger;
import cn.icuter.jsql.log.Logs;
import cn.icuter.jsql.operation.Operation;
import cn.icuter.jsql.orm.ORMapper;

import java.lang.reflect.Field;
Expand All @@ -28,6 +29,7 @@
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
* @author edward
Expand Down Expand Up @@ -283,4 +285,22 @@ interface QueryExecutor<T> {
T doExec(ResultSet rs, ResultSetMetaData meta) throws Exception;
}

public <T> T execQuery(Operation dmlOperation, QueryExecutor<T> queryExecutor) throws JSQLException {
if (dmlOperation.getOperationType() != Operation.DML) {
throw new JSQLException("invalid operation");
}
try (PreparedStatement ps = connection.prepareStatement(dmlOperation.getWildcardSql())) {
List<Object> preparedValues = dmlOperation.getPreparedValueList();
for (int i = 0, len = preparedValues.size(); i < len; i++) {
ps.setObject(i + 1, preparedValues.get(i));
}
ResultSet rs = ps.executeQuery();
ResultSetMetaData meta = rs.getMetaData();
return queryExecutor.doExec(rs, meta);
} catch (Exception e) {
e.printStackTrace();
throw new ExecutionException("executing query error, builder detail: " + dmlOperation, e);
}
}

}
4 changes: 4 additions & 0 deletions src/main/java/cn/icuter/jsql/operation/Delete.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package cn.icuter.jsql.operation;

public class Delete extends Operation{
}
107 changes: 107 additions & 0 deletions src/main/java/cn/icuter/jsql/operation/Insert.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package cn.icuter.jsql.operation;

import cn.icuter.jsql.builder.AbstractBuilder;
import cn.icuter.jsql.builder.FieldInterceptor;
import cn.icuter.jsql.condition.Cond;
import cn.icuter.jsql.condition.Condition;
import cn.icuter.jsql.condition.Eq;
import cn.icuter.jsql.condition.PrepareType;
import cn.icuter.jsql.dialect.Dialect;
import cn.icuter.jsql.orm.ORMapper;

import java.util.*;
import java.util.stream.Collectors;

public class Insert extends Operation {

public Insert() {
}

public Insert(Dialect dialect) {
this.dialect = dialect;
}

public static class Builder extends AbstractBuilder {

public Builder() {
}

@Override
public Builder insert(String tableName) {
sqlStringBuilder.append("insert into").append(tableName);
return this;
}

@Override
public Builder values(Eq... values) {
if (values == null || values.length <= 0) {
throw new IllegalArgumentException("values must not be null or empty! ");
}
sqlStringBuilder
.append("(" + Arrays.stream(values).map(Condition::getField).collect(Collectors.joining(",")) + ")")
.append("values(" + createPlaceHolder(values.length) + ")");
addCondition(values);
return this;
}

private String createPlaceHolder(int placeHolderCnt) {
return Arrays.stream(new String[placeHolderCnt])
.map(nvl -> "?")
.collect(Collectors.joining(","));
}

@SuppressWarnings("unchecked")
@Override
public Builder values(Object values) {
Objects.requireNonNull(values, "values must not be null");

if (values instanceof Map) {
Map<Object, Object> attrs = (Map<Object, Object>) values;
List<Eq> conditionList = attrs.entrySet().stream()
.map(e -> Cond.eq(e.getKey().toString(), e.getValue()))
.collect(LinkedList::new, LinkedList::add, LinkedList::addAll);
return values(conditionList.toArray(new Eq[conditionList.size()]));
} else if (values instanceof Collection) {
Collection<Eq> eqs = (Collection<Eq>) values;
return values(eqs.toArray(new Eq[eqs.size()]));
} else if (values instanceof Eq) {
return values(new Eq[]{(Eq) values});
} else {
Map<String, Object> attrs = ORMapper.of(values).toMapIgnoreNullValue();
return valuesMap(attrs);
}
}

@Override
public <T> Builder values(T value, FieldInterceptor<T> interceptor) {
Map<String, Object> attrs = ORMapper.of(value).toMap(interceptor);
return valuesMap(attrs);
}

private Builder valuesMap(Map<String, Object> attrs) {
List<Eq> eqList = attrs.entrySet().stream()
.map(e -> Cond.eq(e.getKey(), e.getValue()))
.collect(LinkedList::new, LinkedList::add, LinkedList::addAll);
return values(eqList.toArray(new Eq[eqList.size()]));
}

public Insert builds() {
Insert insert = new Insert();
return initInsert(insert);
}

public Insert buildWithDialect(Dialect dialect) {
Insert insert = new Insert(dialect);
return initInsert(insert);
}

private Insert initInsert(Insert insert) {
insert.buildSql = sqlStringBuilder.serialize();
insert.preparedValueList = conditionList.stream()
.filter(condition -> condition.prepareType() == PrepareType.PLACEHOLDER.getType())
.map(Condition::getValue)
.collect(LinkedList::new, this::addPreparedValue, LinkedList::addAll);
return insert;
}
}
}
33 changes: 33 additions & 0 deletions src/main/java/cn/icuter/jsql/operation/Operation.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package cn.icuter.jsql.operation;

import cn.icuter.jsql.dialect.Dialect;

import java.util.List;

public class Operation {

public static final int DML = 0;
public static final int DQL = 1;
String buildSql;
List<Object> preparedValueList;
Dialect dialect;
int type;

public String getWildcardSql() {
return buildSql;
}

public String getOriginSql() {
//TODO 没有通配的原始sql,会有sql注入的危险
return "";
}

public List<Object> getPreparedValueList() {
return preparedValueList;
}

public int getOperationType() {
return type;
}

}
4 changes: 4 additions & 0 deletions src/main/java/cn/icuter/jsql/operation/Select.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package cn.icuter.jsql.operation;

public class Select {
}
4 changes: 4 additions & 0 deletions src/main/java/cn/icuter/jsql/operation/Update.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package cn.icuter.jsql.operation;

public class Update {
}