Skip to content

Commit e2fc84b

Browse files
committed
Abstracted away QueryStringBuilder from query tree to allow implementing support for other dialects
1 parent fedf906 commit e2fc84b

File tree

13 files changed

+271
-179
lines changed

13 files changed

+271
-179
lines changed

src/main/java/org/javawebstack/orm/Repo.java

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import org.javawebstack.orm.migration.AutoMigrator;
88
import org.javawebstack.orm.query.Query;
99
import org.javawebstack.orm.wrapper.SQL;
10+
import org.javawebstack.orm.wrapper.builder.SQLQueryString;
1011

1112
import java.lang.reflect.Field;
1213
import java.sql.SQLException;
@@ -124,28 +125,14 @@ private void executeCreate(T entry) {
124125
if (field.get(entry) == null)
125126
field.set(entry, UUID.randomUUID());
126127
}
127-
List<Object> params = new ArrayList<>();
128-
StringBuilder sb = new StringBuilder("INSERT INTO `");
129-
sb.append(info.getTableName());
130-
sb.append("` (");
131-
List<String> cols = new ArrayList<>();
132-
List<String> values = new ArrayList<>();
133128
Map<String, Object> map = SQLMapper.map(this, entry);
134129
if (info.isAutoIncrement()) {
135130
String idCol = info.getColumnName(info.getIdField());
136131
if (map.containsKey(idCol) && map.get(idCol) == null)
137132
map.remove(idCol);
138133
}
139-
for (String columnName : map.keySet()) {
140-
cols.add("`" + columnName + "`");
141-
values.add("?");
142-
params.add(map.get(columnName));
143-
}
144-
sb.append(String.join(",", cols));
145-
sb.append(") VALUES (");
146-
sb.append(String.join(",", values));
147-
sb.append(");");
148-
int id = connection.write(sb.toString(), params.toArray());
134+
SQLQueryString qs = getConnection().builder().buildInsert(info, map);
135+
int id = connection.write(qs.getQuery(), qs.getParameters().toArray());
149136
if (info.isAutoIncrement())
150137
info.getField(info.getIdField()).set(entry, id);
151138
entry.setEntryExists(true);

src/main/java/org/javawebstack/orm/query/Query.java

Lines changed: 40 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import org.javawebstack.orm.Repo;
55
import org.javawebstack.orm.SQLMapper;
66
import org.javawebstack.orm.exception.ORMQueryException;
7+
import org.javawebstack.orm.wrapper.builder.SQLQueryString;
78

89
import java.sql.ResultSet;
910
import java.sql.SQLException;
@@ -26,7 +27,6 @@ public class Query<T extends Model> {
2627
private QueryColumn order;
2728
private boolean desc = false;
2829
private boolean withDeleted = false;
29-
private final Map<Class<? extends Model>, QueryCondition> leftJoins = new HashMap<>();
3030

3131
public Query(Class<T> model) {
3232
this(Repo.get(model), model);
@@ -38,13 +38,36 @@ public Query(Repo<T> repo, Class<T> model) {
3838
this.where = new QueryGroup<>();
3939
}
4040

41-
public Class<T> getModel() {
42-
return model;
41+
public boolean isWithDeleted() {
42+
return withDeleted;
4343
}
4444

45-
public Query<T> leftJoin(Class<? extends Model> model, String self, String other) {
46-
leftJoins.put(model, new QueryCondition(new QueryColumn(repo.getInfo().getTableName() + "." + self), "=", new QueryColumn(Repo.get(model).getInfo().getTableName() + "." + other)));
47-
return this;
45+
public QueryGroup<T> getWhereGroup() {
46+
return where;
47+
}
48+
49+
public Integer getLimit() {
50+
return limit;
51+
}
52+
53+
public Integer getOffset() {
54+
return offset;
55+
}
56+
57+
public QueryColumn getOrder() {
58+
return order;
59+
}
60+
61+
public boolean isDescOrder() {
62+
return desc;
63+
}
64+
65+
public Repo<T> getRepo() {
66+
return repo;
67+
}
68+
69+
public Class<T> getModel() {
70+
return model;
4871
}
4972

5073
public Query<T> and(Function<QueryGroup<T>, QueryGroup<T>> group) {
@@ -286,59 +309,10 @@ public Query<T> withDeleted() {
286309
return this;
287310
}
288311

289-
public QueryString getQueryString() {
290-
return getQueryString(false);
291-
}
292-
293-
public QueryString getQueryString(boolean count) {
294-
List<Object> parameters = new ArrayList<>();
295-
StringBuilder sb = new StringBuilder("SELECT ")
296-
.append(count ? "COUNT(*)" : "*")
297-
.append(" FROM `")
298-
.append(repo.getInfo().getTableName())
299-
.append('`');
300-
for (Class<? extends Model> type : leftJoins.keySet()) {
301-
sb.append(" LEFT JOIN `")
302-
.append(Repo.get(type).getInfo().getTableName())
303-
.append("` ON ")
304-
.append(leftJoins.get(type).getQueryString(repo.getInfo()).getQuery());
305-
}
306-
considerSoftDelete();
307-
if (where.getQueryElements().size() > 0) {
308-
QueryString qs = where.getQueryString(repo.getInfo());
309-
sb.append(" WHERE ").append(qs.getQuery());
310-
parameters.addAll(qs.getParameters());
311-
}
312-
if (order != null) {
313-
sb.append(" ORDER BY ").append(order.toString(repo.getInfo()));
314-
if (desc)
315-
sb.append(" DESC");
316-
}
317-
if (offset != null && limit == null)
318-
limit = Integer.MAX_VALUE;
319-
if (limit != null) {
320-
sb.append(" LIMIT ?");
321-
if (offset != null) {
322-
sb.append(",?");
323-
parameters.add(offset);
324-
}
325-
parameters.add(limit);
326-
}
327-
return new QueryString(sb.toString(), SQLMapper.mapParams(repo, parameters));
328-
}
329-
330312
public void finalDelete() {
331-
List<Object> parameters = new ArrayList<>();
332-
StringBuilder sb = new StringBuilder("DELETE FROM `")
333-
.append(repo.getInfo().getTableName())
334-
.append('`');
335-
if (where.getQueryElements().size() > 0) {
336-
QueryString qs = where.getQueryString(repo.getInfo());
337-
sb.append(" WHERE ").append(qs.getQuery());
338-
parameters = qs.getParameters();
339-
}
313+
SQLQueryString qs = repo.getConnection().builder().buildDelete(this);
340314
try {
341-
repo.getConnection().write(sb.toString(), SQLMapper.mapParams(repo, parameters).toArray());
315+
repo.getConnection().write(qs.getQuery(), qs.getParameters().toArray());
342316
} catch (SQLException throwables) {
343317
throw new ORMQueryException(throwables);
344318
}
@@ -364,18 +338,10 @@ public void restore() {
364338
withDeleted().update(values);
365339
}
366340

367-
private void considerSoftDelete() {
368-
if (repo.getInfo().isSoftDelete() && !withDeleted) {
369-
if (where.getQueryElements().size() > 0)
370-
where.getQueryElements().add(0, QueryConjunction.AND);
371-
where.getQueryElements().add(0, new QueryCondition(new QueryColumn(repo.getInfo().getColumnName(repo.getInfo().getSoftDeleteField())), "IS NULL", null));
372-
}
373-
}
374-
375341
public T refresh(T entity) {
376-
QueryString qs = getQueryString(false);
342+
SQLQueryString qs = repo.getConnection().builder().buildQuery(this, false);
377343
try {
378-
ResultSet rs = repo.getConnection().read(qs.getQuery(), SQLMapper.mapParams(repo, SQLMapper.mapParams(repo, qs.getParameters())).toArray());
344+
ResultSet rs = repo.getConnection().read(qs.getQuery(), qs.getParameters().toArray());
379345
SQLMapper.mapBack(repo, rs, entity);
380346
repo.getConnection().close(rs);
381347
return entity;
@@ -389,39 +355,19 @@ public void update(T entity) {
389355
}
390356

391357
public void update(Map<String, Object> values) {
392-
if (repo.getInfo().hasUpdated())
393-
values.put(repo.getInfo().getColumnName(repo.getInfo().getUpdatedField()), Timestamp.from(Instant.now()));
394-
List<Object> parameters = new ArrayList<>();
395-
List<String> sets = new ArrayList<>();
396-
values.forEach((key, value) -> {
397-
sets.add("`" + key + "`=?");
398-
parameters.add(value);
399-
});
400-
StringBuilder sb = new StringBuilder("UPDATE `")
401-
.append(repo.getInfo().getTableName())
402-
.append("` SET ")
403-
.append(String.join(",", sets));
404-
considerSoftDelete();
405-
if (where.getQueryElements().size() > 0) {
406-
QueryString qs = where.getQueryString(repo.getInfo());
407-
sb.append(" WHERE ").append(qs.getQuery());
408-
parameters.addAll(qs.getParameters());
409-
}
410-
sb.append(';');
358+
SQLQueryString queryString = repo.getConnection().builder().buildUpdate(this, values);
411359
try {
412-
repo.getConnection().write(sb.toString(), SQLMapper.mapParams(repo, parameters).toArray());
360+
repo.getConnection().write(queryString.getQuery(), queryString.getParameters().toArray());
413361
} catch (SQLException throwables) {
414362
throw new ORMQueryException(throwables);
415363
}
416364
}
417365

418366
public List<T> all() {
419-
QueryString qs = getQueryString(false);
367+
SQLQueryString qs = repo.getConnection().builder().buildQuery(this, false);
420368
try {
421-
ResultSet rs = repo.getConnection().read(qs.getQuery(), SQLMapper.mapParams(repo, qs.getParameters()).toArray());
422-
List<Class<? extends Model>> joinedModels = new ArrayList<>();
423-
joinedModels.addAll(leftJoins.keySet());
424-
List<T> list = SQLMapper.map(repo, rs, joinedModels);
369+
ResultSet rs = repo.getConnection().read(qs.getQuery(), qs.getParameters().toArray());
370+
List<T> list = SQLMapper.map(repo, rs, new ArrayList<>());
425371
repo.getConnection().close(rs);
426372
return list;
427373
} catch (SQLException throwables) {
@@ -445,9 +391,9 @@ public Stream<T> stream() {
445391
}
446392

447393
public int count() {
448-
QueryString qs = getQueryString(true);
394+
SQLQueryString qs = repo.getConnection().builder().buildQuery(this, true);
449395
try {
450-
ResultSet rs = repo.getConnection().read(qs.getQuery(), SQLMapper.mapParams(repo, qs.getParameters()).toArray());
396+
ResultSet rs = repo.getConnection().read(qs.getQuery(), qs.getParameters().toArray());
451397
int c = 0;
452398
if (rs.next())
453399
c = rs.getInt(1);
Lines changed: 3 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,5 @@
11
package org.javawebstack.orm.query;
22

3-
import org.javawebstack.orm.TableInfo;
4-
5-
import java.util.ArrayList;
6-
import java.util.Arrays;
7-
import java.util.List;
8-
import java.util.stream.Collectors;
9-
import java.util.stream.IntStream;
10-
113
public class QueryCondition implements QueryElement {
124

135
private final Object left;
@@ -38,37 +30,12 @@ public String getOperator() {
3830
return operator;
3931
}
4032

41-
private boolean hasRight() {
33+
public boolean hasRight() {
4234
return !(operator.equalsIgnoreCase("IS NULL") || operator.equalsIgnoreCase("IS NOT NULL"));
4335
}
4436

45-
public QueryString getQueryString(TableInfo info) {
46-
StringBuilder sb = new StringBuilder();
47-
if (not)
48-
sb.append("NOT ");
49-
List<Object> parameters = new ArrayList<>();
50-
if (left instanceof QueryColumn) {
51-
sb.append(((QueryColumn) left).toString(info));
52-
} else {
53-
sb.append('?');
54-
parameters.add(left);
55-
}
56-
sb.append(' ');
57-
sb.append(operator);
58-
if (hasRight()) {
59-
sb.append(' ');
60-
if (operator.endsWith("IN")) {
61-
Object[] values = (Object[]) right;
62-
sb.append("(").append(IntStream.range(0, values.length).mapToObj(i -> "?").collect(Collectors.joining(","))).append(")");
63-
parameters.addAll(Arrays.asList(values));
64-
} else if (right instanceof QueryColumn) {
65-
sb.append(((QueryColumn) right).toString(info));
66-
} else {
67-
sb.append('?');
68-
parameters.add(right);
69-
}
70-
}
71-
return new QueryString(sb.toString(), parameters);
37+
public boolean isNot() {
38+
return not;
7239
}
7340

7441
}
Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
11
package org.javawebstack.orm.query;
22

3-
import org.javawebstack.orm.TableInfo;
4-
53
public enum QueryConjunction implements QueryElement {
64
AND,
75
OR,
8-
XOR;
9-
10-
public QueryString getQueryString(TableInfo info) {
11-
return new QueryString(name());
12-
}
6+
XOR
137
}
Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
package org.javawebstack.orm.query;
22

3-
import org.javawebstack.orm.TableInfo;
4-
53
public interface QueryElement {
64

7-
QueryString getQueryString(TableInfo info);
8-
95
}

src/main/java/org/javawebstack/orm/query/QueryExists.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import org.javawebstack.orm.Model;
44
import org.javawebstack.orm.TableInfo;
5+
import org.javawebstack.orm.wrapper.builder.SQLQueryString;
56

67
public class QueryExists<T extends Model> implements QueryElement {
78

@@ -13,9 +14,12 @@ public QueryExists(Query<T> query, boolean not) {
1314
this.not = not;
1415
}
1516

16-
public QueryString getQueryString(TableInfo info) {
17-
QueryString qs = query.getQueryString();
18-
return new QueryString((not ? "NOT " : "") + "EXISTS (" + qs.getQuery() + ")", qs.getParameters());
17+
public Query<T> getQuery() {
18+
return query;
19+
}
20+
21+
public boolean isNot() {
22+
return not;
1923
}
2024

2125
}

src/main/java/org/javawebstack/orm/query/QueryGroup.java

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import org.javawebstack.orm.Model;
44
import org.javawebstack.orm.Repo;
55
import org.javawebstack.orm.TableInfo;
6+
import org.javawebstack.orm.wrapper.builder.SQLQueryString;
67

78
import java.util.ArrayList;
89
import java.util.Arrays;
@@ -187,18 +188,4 @@ public QueryGroup<T> orWhereNotIn(Object left, Object... values) {
187188
return orWhere(left, "NOT IN", values);
188189
}
189190

190-
public QueryString getQueryString(TableInfo info) {
191-
StringBuilder sb = new StringBuilder("(");
192-
List<Object> parameters = new ArrayList<>();
193-
for (QueryElement element : queryElements) {
194-
if (sb.length() > 1)
195-
sb.append(' ');
196-
QueryString s = element.getQueryString(info);
197-
sb.append(s.getQuery());
198-
parameters.addAll(s.getParameters());
199-
}
200-
sb.append(')');
201-
return new QueryString(sb.toString(), parameters);
202-
}
203-
204191
}

src/main/java/org/javawebstack/orm/wrapper/MySQL.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package org.javawebstack.orm.wrapper;
22

33
import org.javawebstack.orm.exception.ORMQueryException;
4+
import org.javawebstack.orm.wrapper.builder.MySQLQueryStringBuilder;
5+
import org.javawebstack.orm.wrapper.builder.QueryStringBuilder;
46

57
import java.sql.Connection;
68
import java.sql.DriverManager;
@@ -65,6 +67,10 @@ public Connection getConnection() {
6567
return c;
6668
}
6769

70+
public QueryStringBuilder builder() {
71+
return MySQLQueryStringBuilder.INSTANCE;
72+
}
73+
6874

6975
}
7076

0 commit comments

Comments
 (0)