Skip to content

Commit 3024f7b

Browse files
author
Gerald Unterrainer
committedMay 7, 2021
refactoring
1 parent 6ed8b15 commit 3024f7b

File tree

5 files changed

+131
-62
lines changed

5 files changed

+131
-62
lines changed
 

‎src/main/java/info/unterrainer/commons/httpserver/daos/BasicQueryBuilder.java

+35-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package info.unterrainer.commons.httpserver.daos;
22

3+
import java.util.HashMap;
4+
import java.util.Map;
5+
36
import javax.persistence.EntityManager;
47
import javax.persistence.EntityManagerFactory;
58

@@ -20,7 +23,7 @@ public class BasicQueryBuilder<P extends BasicJpa, T, R extends BasicQueryBuilde
2023
protected String orderByClause = "o.id ASC";
2124
protected boolean lockPessimistic = false;
2225

23-
protected ParamMap parameters = ParamMap.builder().build();
26+
protected Map<String, Object> parameters = new HashMap<>();
2427

2528
/**
2629
* Sets a custom {@link EntityManager}.
@@ -135,16 +138,35 @@ public R clearWhere() {
135138
}
136139

137140
/**
138-
* Clears the order-by-clause and resets it to default.
139-
* <p>
140-
* Default is the empty string.
141+
* Clears the order-by-clause and resets it to an empty string, thus effectively
142+
* clearing the order.
141143
*
142144
* @return an instance of this builder to provide a fluent interface
143145
*/
144146
public R clearOrderBy() {
147+
return orderBy("");
148+
}
149+
150+
/**
151+
* Sets the order-by-clause to the standard-order, which is {@code "o.id ASC"}
152+
* and since this is the default as well, this effectively resets it to default.
153+
*
154+
* @return an instance of this builder to provide a fluent interface
155+
*/
156+
public R setStandardOrder() {
145157
return orderBy(null);
146158
}
147159

160+
/**
161+
* Sets the order-by-clause to the reversed standard-order, which is
162+
* {@code "o.id DESC"}.
163+
*
164+
* @return an instance of this builder to provide a fluent interface
165+
*/
166+
public R setReversedStandardOrder() {
167+
return orderBy("o.id DESC");
168+
}
169+
148170
/**
149171
* Clears the parameters and resets them to default.
150172
* <p>
@@ -167,9 +189,9 @@ public R clearParameters() {
167189
*/
168190
@SuppressWarnings("unchecked")
169191
public R parameters(final ParamMap params) {
170-
parameters = params;
192+
parameters = params.getParameters();
171193
if (this.parameters == null)
172-
parameters = ParamMap.builder().build();
194+
parameters = new HashMap<>();
173195
return (R) this;
174196
}
175197

@@ -182,7 +204,7 @@ public R parameters(final ParamMap params) {
182204
*/
183205
@SuppressWarnings("unchecked")
184206
public R addParam(final String paramKey, final Object paramValue) {
185-
parameters.addParameter(paramKey, paramValue);
207+
parameters.put(paramKey, paramValue);
186208
return (R) this;
187209
}
188210

@@ -206,6 +228,9 @@ public R orderBy(final String orderByClause) {
206228

207229
/**
208230
* Adds an ASC-segment to the order-by-clause.
231+
* <p>
232+
* Since the standard-order is {@code "o.id ASC"} it is advised to call
233+
* {@link #clearOrderBy()} first.
209234
*
210235
* @param field the name of the field ("o.id" or "o.createdOn" for example)
211236
* @return an instance of this builder to provide a fluent interface
@@ -222,6 +247,9 @@ public R asc(final String field) {
222247

223248
/**
224249
* Adds an DESC-segment to the order-by-clause.
250+
* <p>
251+
* Since the standard-order is {@code "o.id ASC"} it is advised to call
252+
* {@link #clearOrderBy()} first.
225253
*
226254
* @param field the name of the field ("o.id" or "o.createdOn" for example)
227255
* @return an instance of this builder to provide a fluent interface

‎src/main/java/info/unterrainer/commons/httpserver/daos/JpqlAsyncDao.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ public List<P> internalGetList(final EntityManager em, final long size, final bo
103103
isFirst = false;
104104
} else
105105
sb.append("OR ");
106-
sb.append("state=:state");
106+
sb.append("state = :state");
107107
sb.append(i);
108108
sb.append(" ");
109109
}

‎src/main/java/info/unterrainer/commons/httpserver/daos/JpqlDao.java

+8-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package info.unterrainer.commons.httpserver.daos;
22

33
import java.time.LocalDateTime;
4+
import java.util.Map;
45
import java.util.Map.Entry;
56

67
import javax.persistence.EntityManager;
@@ -39,7 +40,7 @@ public ListJson<P> getList(final EntityManager em, final long offset, final long
3940
.orderBy(orderByClause)
4041
.parameters(params)
4142
.build()
42-
.getList(offset, size);
43+
.getListJson(offset, size);
4344
}
4445

4546
@Override
@@ -120,7 +121,7 @@ public void delete(final EntityManager em, final Long id) {
120121
@Override
121122
public P getById(final EntityManager em, final Long id) {
122123
try {
123-
return query().entityManager(em).where("o.id=:id").addParam("id", id).build().getSingle();
124+
return query().entityManager(em).where("o.id = :id").addParam("id", id).build().getSingle();
124125
} catch (NoResultException e) {
125126
return null;
126127
}
@@ -142,7 +143,7 @@ public CountQueryBuilder<P, P> countQuery() {
142143
}
143144

144145
<T> TypedQuery<T> getQuery(final EntityManager em, final String selectClause, final String joinClause,
145-
final String whereClause, final ParamMap params, final Class<T> type, final String orderBy,
146+
final String whereClause, final Map<String, Object> params, final Class<T> type, final String orderBy,
146147
final boolean lockPessimistic) {
147148
String query = "SELECT ";
148149
if (selectClause == null || selectClause.isBlank())
@@ -162,7 +163,7 @@ <T> TypedQuery<T> getQuery(final EntityManager em, final String selectClause, fi
162163

163164
String msg = query;
164165
if (params != null)
165-
for (Entry<String, Object> p : params.getParameters().entrySet())
166+
for (Entry<String, Object> p : params.entrySet())
166167
msg += "\\n " + p.getKey() + ": " + p.getValue();
167168
log.debug(msg);
168169

@@ -175,21 +176,21 @@ <T> TypedQuery<T> getQuery(final EntityManager em, final String selectClause, fi
175176
if (lockPessimistic)
176177
q.setLockMode(LockModeType.PESSIMISTIC_WRITE);
177178
if (params != null)
178-
for (Entry<String, Object> e : params.getParameters().entrySet())
179+
for (Entry<String, Object> e : params.entrySet())
179180
q.setParameter(e.getKey(), e.getValue());
180181
return q;
181182
}
182183

183184
Query getCountQuery(final EntityManager em, final String selectClause, final String joinClause,
184-
final String whereClause, final ParamMap params) {
185+
final String whereClause, final Map<String, Object> params) {
185186
String query = "SELECT COUNT(" + selectClause + ") FROM %s AS o";
186187
if (joinClause != null && !joinClause.isBlank())
187188
query += " " + joinClause;
188189
if (whereClause != null && !whereClause.isBlank())
189190
query += " WHERE " + whereClause;
190191
Query q = em.createQuery(String.format(query, this.type.getSimpleName()));
191192
if (params != null)
192-
for (Entry<String, Object> e : params.getParameters().entrySet())
193+
for (Entry<String, Object> e : params.entrySet())
193194
q.setParameter(e.getKey(), e.getValue());
194195
return q;
195196
}

‎src/main/java/info/unterrainer/commons/httpserver/daos/Query.java

+72-26
Original file line numberDiff line numberDiff line change
@@ -2,44 +2,62 @@
22

33
import java.util.Collections;
44
import java.util.List;
5+
import java.util.function.Function;
56

7+
import javax.persistence.EntityManager;
8+
import javax.persistence.EntityManagerFactory;
69
import javax.persistence.NoResultException;
10+
import javax.persistence.NonUniqueResultException;
711
import javax.persistence.TypedQuery;
812

913
import info.unterrainer.commons.httpserver.jsons.ListJson;
14+
import info.unterrainer.commons.rdbutils.Transactions;
1015
import info.unterrainer.commons.rdbutils.entities.BasicJpa;
1116
import lombok.AccessLevel;
12-
import lombok.Getter;
1317
import lombok.RequiredArgsConstructor;
1418

1519
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
1620
public class Query<P extends BasicJpa, T> {
1721

18-
protected final JpqlDao<P> dao;
19-
@Getter
20-
protected final TypedQuery<T> typedQuery;
21-
@Getter
22-
protected final javax.persistence.Query countQuery;
22+
protected final EntityManagerFactory emf;
23+
protected final QueryBuilder<P, T> builder;
24+
25+
private <V> V wrap(final Function<EntityManager, V> func) {
26+
if (builder.entityManager == null)
27+
return Transactions.withNewTransactionReturning(emf, em -> func.apply(em));
28+
return func.apply(builder.entityManager);
29+
}
2330

2431
/**
25-
* Gets all the rows specified by offset and size as a list.
32+
* Gets all the rows as a {@link ListJson} as returned by a web-service.
33+
* <p>
34+
* The list contains additional information about the data.
35+
*
36+
* @return a {@link ListJson} containing the rows as specified
37+
*/
38+
public ListJson<T> getListJson() {
39+
return wrap(em -> {
40+
ListJson<T> r = new ListJson<>();
41+
r.setEntries(getList(em));
42+
r.setCount((Long) builder.getCountQuery(em).getSingleResult());
43+
return r;
44+
});
45+
}
46+
47+
/**
48+
* Gets all the rows specified by offset and size as a {@link ListJson} as
49+
* returned by a web-service.
50+
* <p>
51+
* The list contains additional information about the data.
2652
*
2753
* @param offset the row-number to start at
2854
* @param size the number-of-rows to return
2955
* @return a {@link ListJson} containing the rows as specified
3056
*/
31-
public ListJson<T> getList(final long offset, final long size) {
57+
public ListJson<T> getListJson(final long offset, final long size) {
3258
ListJson<T> r = new ListJson<>();
33-
int s = Integer.MAX_VALUE;
34-
if (size < s)
35-
s = (int) size;
36-
int o = Integer.MAX_VALUE;
37-
if (offset < o)
38-
o = (int) offset;
39-
List<T> qResult = typedQuery.getResultList();
40-
Long cqResult = (Long) countQuery.getSingleResult();
41-
r.setEntries(qResult);
42-
r.setCount(cqResult);
59+
r.setEntries(getList(offset, size));
60+
r.setCount((Long) countQuery.getSingleResult());
4361
return r;
4462
}
4563

@@ -49,7 +67,7 @@ public ListJson<T> getList(final long offset, final long size) {
4967
* @return the result-row as a JPA
5068
*/
5169
public T getFirst() {
52-
List<T> r = typedQuery.setMaxResults(1).getResultList();
70+
List<T> r = getList(0, 1);
5371
if (r.size() == 1) {
5472
T jpa = r.get(0);
5573
return jpa;
@@ -59,16 +77,12 @@ public T getFirst() {
5977

6078
/**
6179
* Get the first N rows from this queries' results.
62-
*
80+
*
6381
* @param count the number of rows to get
6482
* @return the list of the first N result-rows as JPAs
6583
*/
6684
public List<T> getN(final long count) {
67-
int s = Integer.MAX_VALUE;
68-
if (count < s)
69-
s = (int) count;
70-
typedQuery.setMaxResults(s);
71-
return typedQuery.getResultList();
85+
return getList(0, count);
7286
}
7387

7488
/**
@@ -89,12 +103,44 @@ public T getSingle() {
89103
* @return the list of result-rows as JPAs
90104
*/
91105
public List<T> getList() {
92-
return typedQuery.getResultList();
106+
return wrap(em -> getList(em));
107+
}
108+
109+
private List<T> getList(final EntityManager em) {
110+
return getList(0, Long.MAX_VALUE);
111+
}
112+
113+
/**
114+
* Gets all the rows specified by offset and size as a list.
115+
*
116+
* @param offset the row-number to start at
117+
* @param size the number-of-rows to return
118+
* @return a list containing the rows as specified
119+
*/
120+
public List<T> getList(final long offset, final long size) {
121+
return wrap(em -> getList(em, offset, size));
122+
}
123+
124+
private List<T> getList(final EntityManager em, final long offset, final long size) {
125+
int s = Integer.MAX_VALUE;
126+
if (size < s)
127+
s = (int) size;
128+
int o = Integer.MAX_VALUE;
129+
if (offset < o)
130+
o = (int) offset;
131+
TypedQuery<T> query = builder.getTypedQuery(em);
132+
query.setFirstResult(o);
133+
query.setMaxResults(s);
134+
return query.getResultList();
93135
}
94136

95137
/**
96138
* Execute a SELECT query that returns multiple result-rows and reverse the
97139
* order of results.
140+
* <p>
141+
* The reversing-process happens after retrieval of the result, since the whole
142+
* list is going to be transferred anyway.<br>
143+
* The list is reversed using {@code Collections.reverse(list)};
98144
*
99145
* @return the reversed list of result-rows as JPAs
100146
*/
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
package info.unterrainer.commons.httpserver.daos;
22

3+
import javax.persistence.EntityManager;
34
import javax.persistence.EntityManagerFactory;
45
import javax.persistence.TypedQuery;
56

6-
import info.unterrainer.commons.rdbutils.Transactions;
77
import info.unterrainer.commons.rdbutils.entities.BasicJpa;
88

99
public class QueryBuilder<P extends BasicJpa, T> extends BasicQueryBuilder<P, T, QueryBuilder<P, T>> {
@@ -16,25 +16,19 @@ public class QueryBuilder<P extends BasicJpa, T> extends BasicQueryBuilder<P, T,
1616
}
1717

1818
public Query<P, T> build() {
19-
TypedQuery<T> q;
20-
if (entityManager != null) {
21-
q = dao.getQuery(entityManager, selectClause, joinClause, whereClause, parameters, resultType,
22-
orderByClause, lockPessimistic);
23-
javax.persistence.Query cq = new CountQueryBuilder<P, T>(emf, dao).entityManager(entityManager)
24-
.select(selectClause)
25-
.join(joinClause)
26-
.where(whereClause)
27-
.build();
28-
return new Query<>(dao, q, cq);
29-
} else {
30-
q = Transactions.withNewTransactionReturning(emf, em -> dao.getQuery(entityManager, selectClause,
31-
joinClause, whereClause, parameters, resultType, orderByClause, lockPessimistic));
32-
javax.persistence.Query cq = new CountQueryBuilder<P, T>(emf, dao).entityManager(entityManager)
33-
.select(selectClause)
34-
.join(joinClause)
35-
.where(whereClause)
36-
.build();
37-
return new Query<>(dao, q, cq);
38-
}
19+
return new Query<>(emf, this);
20+
}
21+
22+
TypedQuery<T> getTypedQuery(final EntityManager em) {
23+
return dao.getQuery(entityManager, selectClause, joinClause, whereClause, parameters, resultType, orderByClause,
24+
lockPessimistic);
25+
}
26+
27+
javax.persistence.Query getCountQuery(final EntityManager em) {
28+
return new CountQueryBuilder<P, T>(emf, dao).entityManager(entityManager)
29+
.select(selectClause)
30+
.join(joinClause)
31+
.where(whereClause)
32+
.build();
3933
}
4034
}

0 commit comments

Comments
 (0)
Please sign in to comment.