Skip to content

Commit 780f17c

Browse files
author
Gerald Unterrainer
committed
refactor query() to select() and add the clause as optional parameter
1 parent 73bcdb8 commit 780f17c

File tree

10 files changed

+263
-36
lines changed

10 files changed

+263
-36
lines changed

src/main/java/info/unterrainer/commons/httpserver/daos/BasicJpqlDao.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ else if (!orderBy.isBlank())
262262
return q;
263263
}
264264

265-
private boolean isAllowed(final info.unterrainer.commons.httpserver.daos.QueryBuilder query,
265+
private boolean isAllowed(final info.unterrainer.commons.httpserver.daos.SelectQueryBuilder query,
266266
final EntityManager em) {
267267
String tenantReferenceField = "testId";
268268
String tenantIdField = "tenantId";

src/main/java/info/unterrainer/commons/httpserver/daos/BasicQueryBuilder.java renamed to src/main/java/info/unterrainer/commons/httpserver/daos/BasicSelectQueryBuilder.java

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import lombok.RequiredArgsConstructor;
1212

1313
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
14-
public class BasicQueryBuilder<P extends BasicJpa, T, R extends BasicQueryBuilder<P, T, R>> {
14+
public class BasicSelectQueryBuilder<P extends BasicJpa, T, R extends BasicSelectQueryBuilder<P, T, R>> {
1515

1616
protected final EntityManagerFactory emf;
1717
protected final BasicJpqlDao<P> dao;
@@ -41,22 +41,10 @@ public R entityManager(final EntityManager em) {
4141
return (R) this;
4242
}
4343

44-
/**
45-
* Sets a custom select-clause.
46-
* <p>
47-
* Default is "o"<br>
48-
* To reset it to default, set it to null.<br>
49-
* To completely delete it, set it to an empty string.
50-
*
51-
* @param selectClause the new clause
52-
* @return an instance of this builder to provide a fluent interface
53-
*/
54-
@SuppressWarnings("unchecked")
55-
public R select(final String selectClause) {
44+
void setSelect(final String selectClause) {
5645
this.selectClause = selectClause;
5746
if (this.selectClause == null || this.selectClause.isBlank())
5847
this.selectClause = "o";
59-
return (R) this;
6048
}
6149

6250
/**

src/main/java/info/unterrainer/commons/httpserver/daos/Query.java renamed to src/main/java/info/unterrainer/commons/httpserver/daos/Dml.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import lombok.RequiredArgsConstructor;
1818

1919
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
20-
public class Query<P extends BasicJpa, T> {
20+
public class Dml<P extends BasicJpa, T> {
2121

2222
protected final EntityManagerFactory emf;
2323
protected final QueryInterface<P, T> builder;

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

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,67 @@
66

77
public class JpqlAsyncDao<P extends BasicAsyncJpa> extends BasicJpqlDao<P> {
88

9+
/**
10+
* Generates a DAO that lets you build and execute queries.
11+
*
12+
* @param emf the {@link EntityManagerFactory} to use
13+
* @param type the return-type of the query (the underlying JPA)
14+
*/
915
public JpqlAsyncDao(final EntityManagerFactory emf, final Class<P> type) {
1016
super(emf, type);
1117
}
1218

13-
public QueryAsyncBuilder<P, P> query() {
14-
return new QueryAsyncBuilder<>(emf, this, type);
19+
/**
20+
* Build a SELECT(*)-like query. The result will be of the underlying generic
21+
* type.
22+
*
23+
* @return a query-builder
24+
*/
25+
public SelectAsyncQueryBuilder<P, P> select() {
26+
return new SelectAsyncQueryBuilder<>(emf, this, type);
1527
}
1628

17-
public <T> QueryAsyncBuilder<P, T> query(final Class<T> resultType) {
18-
return new QueryAsyncBuilder<>(emf, this, resultType);
29+
/**
30+
* Build a SELECT(*)-like query. The result will be of the given type (use this
31+
* for a COUNT(*) query, for example).
32+
*
33+
* @param <T> the type the result will be
34+
* @param resultType the type the result will be
35+
* @return a query-builder
36+
*/
37+
public <T> SelectAsyncQueryBuilder<P, T> select(final Class<T> resultType) {
38+
return new SelectAsyncQueryBuilder<>(emf, this, resultType);
39+
}
40+
41+
/**
42+
* Build a SELECT-query with a custom select-clause. The result will be of the
43+
* given type (use this for a COUNT(*) query, for example).
44+
*
45+
* @param <T> the type the result will be
46+
* @param selectClause your custom select-clause (the base-object has the alias
47+
* 'o'. So the default would be "o" internally resulting in
48+
* a "SELECT o")
49+
* @param resultType the type the result will be
50+
* @return a query-builder
51+
*/
52+
public <T> SelectAsyncQueryBuilder<P, T> select(final String selectClause, final Class<T> resultType) {
53+
SelectAsyncQueryBuilder<P, T> b = new SelectAsyncQueryBuilder<>(emf, this, resultType);
54+
b.setSelect(selectClause);
55+
return b;
56+
}
57+
58+
/**
59+
* Build a SELECT-query with a custom select-clause. The result will be of the
60+
* underlying generic type.
61+
*
62+
* @param selectClause your custom select-clause (the base-object has the alias
63+
* 'o'. So the default would be "o" internally resulting in
64+
* a "SELECT o")
65+
* @return a query-builder
66+
*/
67+
public <T> SelectAsyncQueryBuilder<P, P> select(final String selectClause) {
68+
SelectAsyncQueryBuilder<P, P> b = new SelectAsyncQueryBuilder<>(emf, this, type);
69+
b.setSelect(selectClause);
70+
return b;
1971
}
2072
}

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

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,67 @@
77

88
public class JpqlDao<P extends BasicJpa> extends BasicJpqlDao<P> implements BasicDao<P, EntityManager> {
99

10+
/**
11+
* Generates a DAO that lets you build and execute queries.
12+
*
13+
* @param emf the {@link EntityManagerFactory} to use
14+
* @param type the return-type of the query (the underlying JPA)
15+
*/
1016
public JpqlDao(final EntityManagerFactory emf, final Class<P> type) {
1117
super(emf, type);
1218
}
1319

14-
public QueryBuilder<P, P> query() {
15-
return new QueryBuilder<>(emf, this, type);
20+
/**
21+
* Build a SELECT(*)-like query. The result will be of the underlying generic
22+
* type.
23+
*
24+
* @return a query-builder
25+
*/
26+
public SelectQueryBuilder<P, P> select() {
27+
return new SelectQueryBuilder<>(emf, this, type);
1628
}
1729

18-
public <T> QueryBuilder<P, T> query(final Class<T> resultType) {
19-
return new QueryBuilder<>(emf, this, resultType);
30+
/**
31+
* Build a SELECT(*)-like query. The result will be of the given type (use this
32+
* for a COUNT(*) query, for example).
33+
*
34+
* @param <T> the type the result will be
35+
* @param resultType the type the result will be
36+
* @return a query-builder
37+
*/
38+
public <T> SelectQueryBuilder<P, T> select(final Class<T> resultType) {
39+
return new SelectQueryBuilder<>(emf, this, resultType);
40+
}
41+
42+
/**
43+
* Build a SELECT-query with a custom select-clause. The result will be of the
44+
* given type (use this for a COUNT(*) query, for example).
45+
*
46+
* @param <T> the type the result will be
47+
* @param selectClause your custom select-clause (the base-object has the alias
48+
* 'o'. So the default would be "o" internally resulting in
49+
* a "SELECT o")
50+
* @param resultType the type the result will be
51+
* @return a query-builder
52+
*/
53+
public <T> SelectQueryBuilder<P, T> select(final String selectClause, final Class<T> resultType) {
54+
SelectQueryBuilder<P, T> b = new SelectQueryBuilder<>(emf, this, resultType);
55+
b.setSelect(selectClause);
56+
return b;
57+
}
58+
59+
/**
60+
* Build a SELECT-query with a custom select-clause. The result will be of the
61+
* underlying generic type.
62+
*
63+
* @param selectClause your custom select-clause (the base-object has the alias
64+
* 'o'. So the default would be "o" internally resulting in
65+
* a "SELECT o")
66+
* @return a query-builder
67+
*/
68+
public <T> SelectQueryBuilder<P, P> select(final String selectClause) {
69+
SelectQueryBuilder<P, P> b = new SelectQueryBuilder<>(emf, this, type);
70+
b.setSelect(selectClause);
71+
return b;
2072
}
2173
}

src/main/java/info/unterrainer/commons/httpserver/daos/QueryInterface.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ interface QueryInterface<P extends BasicJpa, T> {
1111

1212
BasicJpqlDao<P> getDao();
1313

14-
Query<P, T> build();
14+
SelectQuery<P, T> build();
1515

1616
TypedQuery<T> getTypedQuery(final EntityManager em);
1717

src/main/java/info/unterrainer/commons/httpserver/daos/QueryAsyncBuilder.java renamed to src/main/java/info/unterrainer/commons/httpserver/daos/SelectAsyncQueryBuilder.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,18 @@
1111
import info.unterrainer.commons.rdbutils.entities.BasicAsyncJpa;
1212
import info.unterrainer.commons.rdbutils.enums.AsyncState;
1313

14-
public class QueryAsyncBuilder<P extends BasicAsyncJpa, T> extends BasicQueryBuilder<P, T, QueryAsyncBuilder<P, T>>
14+
public class SelectAsyncQueryBuilder<P extends BasicAsyncJpa, T> extends BasicSelectQueryBuilder<P, T, SelectAsyncQueryBuilder<P, T>>
1515
implements QueryInterface<P, T> {
1616

1717
private Set<AsyncState> asyncStates = new HashSet<>();
1818

19-
QueryAsyncBuilder(final EntityManagerFactory emf, final JpqlAsyncDao<P> dao, final Class<T> resultType) {
19+
SelectAsyncQueryBuilder(final EntityManagerFactory emf, final JpqlAsyncDao<P> dao, final Class<T> resultType) {
2020
super(emf, dao, resultType);
2121
}
2222

2323
@Override
24-
public Query<P, T> build() {
25-
return new Query<>(emf, this);
24+
public SelectQuery<P, T> build() {
25+
return new SelectQuery<>(emf, this);
2626
}
2727

2828
/**
@@ -40,7 +40,7 @@ public Query<P, T> build() {
4040
* @param asyncStates a single or number of AsyncState values
4141
* @return an instance of this builder to provide a fluent interface
4242
*/
43-
public QueryAsyncBuilder<P, T> asyncStateOf(final AsyncState... asyncStates) {
43+
public SelectAsyncQueryBuilder<P, T> asyncStateOf(final AsyncState... asyncStates) {
4444
this.asyncStates.addAll(Arrays.asList(asyncStates));
4545
return this;
4646
}

src/main/java/info/unterrainer/commons/httpserver/daos/CountQueryBuilder.java renamed to src/main/java/info/unterrainer/commons/httpserver/daos/SelectCountQueryBuilder.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
import info.unterrainer.commons.rdbutils.Transactions;
66
import info.unterrainer.commons.rdbutils.entities.BasicJpa;
77

8-
public class CountQueryBuilder<P extends BasicJpa> extends BasicQueryBuilder<P, Long, CountQueryBuilder<P>> {
8+
public class SelectCountQueryBuilder<P extends BasicJpa> extends BasicSelectQueryBuilder<P, Long, SelectCountQueryBuilder<P>> {
99

10-
CountQueryBuilder(final EntityManagerFactory emf, final JpqlDao<P> dao) {
10+
SelectCountQueryBuilder(final EntityManagerFactory emf, final JpqlDao<P> dao) {
1111
super(emf, dao, Long.class);
1212
}
1313

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
package info.unterrainer.commons.httpserver.daos;
2+
3+
import java.util.Collections;
4+
import java.util.List;
5+
import java.util.function.Function;
6+
7+
import javax.persistence.EntityManager;
8+
import javax.persistence.EntityManagerFactory;
9+
import javax.persistence.NoResultException;
10+
import javax.persistence.NonUniqueResultException;
11+
import javax.persistence.TypedQuery;
12+
13+
import info.unterrainer.commons.httpserver.jsons.ListJson;
14+
import info.unterrainer.commons.rdbutils.Transactions;
15+
import info.unterrainer.commons.rdbutils.entities.BasicJpa;
16+
import lombok.AccessLevel;
17+
import lombok.RequiredArgsConstructor;
18+
19+
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
20+
public class SelectQuery<P extends BasicJpa, T> {
21+
22+
protected final EntityManagerFactory emf;
23+
protected final QueryInterface<P, T> builder;
24+
25+
private <V> V withEntityManager(final Function<EntityManager, V> func) {
26+
if (builder.getEntityManager() == null)
27+
return Transactions.withNewTransactionReturning(emf, em -> func.apply(em));
28+
return func.apply(builder.getEntityManager());
29+
}
30+
31+
/**
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 getListJson(0, Long.MAX_VALUE);
40+
}
41+
42+
/**
43+
* Gets all the rows specified by offset and size as a {@link ListJson} as
44+
* returned by a web-service.
45+
* <p>
46+
* The list contains additional information about the data.
47+
*
48+
* @param offset the row-number to start at
49+
* @param size the number-of-rows to return
50+
* @return a {@link ListJson} containing the rows as specified
51+
*/
52+
public ListJson<T> getListJson(final long offset, final long size) {
53+
return withEntityManager(em -> {
54+
ListJson<T> r = new ListJson<>();
55+
r.setEntries(builder.getDao().getList(em, builder.getTypedQuery(em), offset, size));
56+
r.setCount((Long) builder.getCountQuery(em).getSingleResult());
57+
return r;
58+
});
59+
}
60+
61+
/**
62+
* Gets the first row this query returns.
63+
*
64+
* @return the result-row as a JPA
65+
*/
66+
public T getFirst() {
67+
List<T> r = getList(0, 1);
68+
if (r.size() == 1) {
69+
T jpa = r.get(0);
70+
return jpa;
71+
}
72+
return null;
73+
}
74+
75+
/**
76+
* Get the first N rows from this queries' results.
77+
*
78+
* @param count the number of rows to get
79+
* @return the list of the first N result-rows as JPAs
80+
*/
81+
public List<T> getN(final long count) {
82+
return getList(0, count);
83+
}
84+
85+
/**
86+
* Execute a SELECT query that returns a single result-row.
87+
*
88+
* @return the result-row as a JPA
89+
* @throws NoResultException if there is no
90+
* resultNonUniqueResultException
91+
* @throws NonUniqueResultException if more than one result
92+
*/
93+
public T getSingle() {
94+
return withEntityManager(em -> {
95+
TypedQuery<T> typedQuery = builder.getTypedQuery(em);
96+
return typedQuery.getSingleResult();
97+
});
98+
}
99+
100+
/**
101+
* Execute a SELECT query that returns multiple result-rows.
102+
*
103+
* @return the list of result-rows as JPAs
104+
*/
105+
public List<T> getList() {
106+
return withEntityManager(em -> builder.getDao().getList(em, builder.getTypedQuery(em), 0, Long.MAX_VALUE));
107+
}
108+
109+
/**
110+
* Gets all the rows specified by offset and size as a list.
111+
*
112+
* @param offset the row-number to start at
113+
* @param size the number-of-rows to return
114+
* @return a list containing the rows as specified
115+
*/
116+
public List<T> getList(final long offset, final long size) {
117+
return withEntityManager(em -> builder.getDao().getList(em, builder.getTypedQuery(em), offset, size));
118+
}
119+
120+
/**
121+
* Execute a SELECT query that returns multiple result-rows and reverse the
122+
* order of results.
123+
* <p>
124+
* The reversing-process happens after retrieval of the result, since the whole
125+
* list is going to be transferred anyway.<br>
126+
* The list is reversed using {@code Collections.reverse(list)};
127+
*
128+
* @return the reversed list of result-rows as JPAs
129+
*/
130+
public List<T> getListReversed() {
131+
List<T> l = getList();
132+
Collections.reverse(l);
133+
return l;
134+
}
135+
}

0 commit comments

Comments
 (0)