Skip to content

Commit 93c22db

Browse files
committed
NOPR - NEW: QueryCache support for DTO queries
1 parent c9065a3 commit 93c22db

10 files changed

Lines changed: 134 additions & 46 deletions

File tree

ebean-core/src/main/java/io/ebeaninternal/api/HashQuery.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@ public final class HashQuery {
77

88
private final CQueryPlanKey planHash;
99
private final BindValuesKey bindValuesKey;
10+
private final Class<?> dtoType;
1011

1112
/**
1213
* Create the HashQuery.
1314
*/
14-
public HashQuery(CQueryPlanKey planHash, BindValuesKey bindValuesKey) {
15+
public HashQuery(CQueryPlanKey planHash, BindValuesKey bindValuesKey, Class<?> dtoType) {
1516
this.planHash = planHash;
1617
this.bindValuesKey = bindValuesKey;
18+
this.dtoType = dtoType;
1719
}
1820

1921
@Override
@@ -25,6 +27,7 @@ public String toString() {
2527
public int hashCode() {
2628
int hc = 92821 * planHash.hashCode();
2729
hc = 92821 * hc + bindValuesKey.hashCode();
30+
hc = 92821 * hc + dtoType.hashCode();
2831
return hc;
2932
}
3033

@@ -37,6 +40,6 @@ public boolean equals(Object obj) {
3740
return false;
3841
}
3942
HashQuery e = (HashQuery) obj;
40-
return e.bindValuesKey.equals(bindValuesKey) && e.planHash.equals(planHash);
43+
return e.bindValuesKey.equals(bindValuesKey) && e.planHash.equals(planHash) && e.dtoType.equals(dtoType);
4144
}
4245
}

ebean-core/src/main/java/io/ebeaninternal/api/SpiQuery.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -877,6 +877,11 @@ public static TemporalMode of(SpiQuery<?> query) {
877877
*/
878878
void setManualId();
879879

880+
/**
881+
* Set the DTO type, that should be part of the queryHash.
882+
*/
883+
void setDtoType(Class<?> dtoType);
884+
880885
/**
881886
* Set default select clauses where none have been explicitly defined.
882887
*/

ebean-core/src/main/java/io/ebeaninternal/server/core/AbstractSqlQueryRequest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ private String limitOffset(String sql) {
126126
/**
127127
* Prepare and execute the SQL using the Binder.
128128
*/
129-
public void executeSql(Binder binder, SpiQuery.Type type) throws SQLException {
129+
public void executeSql(Binder binder) throws SQLException {
130130
startNano = System.nanoTime();
131131
executeAsSql(binder);
132132
}

ebean-core/src/main/java/io/ebeaninternal/server/core/DefaultServer.java

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -898,6 +898,7 @@ public <T> DtoQuery<T> createNamedDtoQuery(Class<T> dtoType, String namedQuery)
898898
@Override
899899
public <T> DtoQuery<T> findDto(Class<T> dtoType, SpiQuery<?> ormQuery) {
900900
DtoBeanDescriptor<T> descriptor = dtoBeanManager.descriptor(dtoType);
901+
ormQuery.setDtoType(dtoType);
901902
return new DefaultDtoQuery<>(this, descriptor, ormQuery);
902903
}
903904

@@ -940,6 +941,18 @@ public <T> T find(Class<T> beanType, Object id, @Nullable Transaction transactio
940941
return findId(query);
941942
}
942943

944+
<T> DtoQueryRequest<T> createDtoQueryRequest(Type type, SpiDtoQuery<T> query) {
945+
SpiQuery<?> ormQuery = query.ormQuery();
946+
if (ormQuery != null) {
947+
ormQuery.setType(type);
948+
ormQuery.setManualId();
949+
SpiOrmQueryRequest<?> ormRequest = createQueryRequest(type, ormQuery);
950+
return new DtoQueryRequest<>(this, dtoQueryEngine, query, ormRequest);
951+
} else {
952+
return new DtoQueryRequest<>(this, dtoQueryEngine, query, null);
953+
}
954+
}
955+
943956
<T> SpiOrmQueryRequest<T> createQueryRequest(Type type, SpiQuery<T> query) {
944957
SpiOrmQueryRequest<T> request = buildQueryRequest(type, query);
945958
request.prepareQuery();
@@ -1544,7 +1557,7 @@ public <T> T findSingleAttribute(SpiSqlQuery query, Class<T> cls) {
15441557

15451558
@Override
15461559
public <T> void findDtoEach(SpiDtoQuery<T> query, Consumer<T> consumer) {
1547-
DtoQueryRequest<T> request = new DtoQueryRequest<>(this, dtoQueryEngine, query);
1560+
DtoQueryRequest<T> request = createDtoQueryRequest(Type.ITERATE, query);
15481561
try {
15491562
request.initTransIfRequired();
15501563
request.findEach(consumer);
@@ -1555,7 +1568,7 @@ public <T> void findDtoEach(SpiDtoQuery<T> query, Consumer<T> consumer) {
15551568

15561569
@Override
15571570
public <T> void findDtoEach(SpiDtoQuery<T> query, int batch, Consumer<List<T>> consumer) {
1558-
DtoQueryRequest<T> request = new DtoQueryRequest<>(this, dtoQueryEngine, query);
1571+
DtoQueryRequest<T> request = createDtoQueryRequest(Type.ITERATE, query);
15591572
try {
15601573
request.initTransIfRequired();
15611574
request.findEach(batch, consumer);
@@ -1566,7 +1579,7 @@ public <T> void findDtoEach(SpiDtoQuery<T> query, int batch, Consumer<List<T>> c
15661579

15671580
@Override
15681581
public <T> void findDtoEachWhile(SpiDtoQuery<T> query, Predicate<T> consumer) {
1569-
DtoQueryRequest<T> request = new DtoQueryRequest<>(this, dtoQueryEngine, query);
1582+
DtoQueryRequest<T> request = createDtoQueryRequest(Type.ITERATE, query);
15701583
try {
15711584
request.initTransIfRequired();
15721585
request.findEachWhile(consumer);
@@ -1577,7 +1590,7 @@ public <T> void findDtoEachWhile(SpiDtoQuery<T> query, Predicate<T> consumer) {
15771590

15781591
@Override
15791592
public <T> QueryIterator<T> findDtoIterate(SpiDtoQuery<T> query) {
1580-
DtoQueryRequest<T> request = new DtoQueryRequest<>(this, dtoQueryEngine, query);
1593+
DtoQueryRequest<T> request = createDtoQueryRequest(Type.ITERATE, query);
15811594
try {
15821595
request.initTransIfRequired();
15831596
return request.findIterate();
@@ -1594,7 +1607,11 @@ public <T> Stream<T> findDtoStream(SpiDtoQuery<T> query) {
15941607

15951608
@Override
15961609
public <T> List<T> findDtoList(SpiDtoQuery<T> query) {
1597-
DtoQueryRequest<T> request = new DtoQueryRequest<>(this, dtoQueryEngine, query);
1610+
DtoQueryRequest<T> request = createDtoQueryRequest(Type.LIST, query);
1611+
List<T> ret = request.getFromQueryCache();
1612+
if (ret != null) {
1613+
return ret;
1614+
}
15981615
try {
15991616
request.initTransIfRequired();
16001617
return request.findList();
@@ -1606,13 +1623,7 @@ public <T> List<T> findDtoList(SpiDtoQuery<T> query) {
16061623
@Nullable
16071624
@Override
16081625
public <T> T findDtoOne(SpiDtoQuery<T> query) {
1609-
DtoQueryRequest<T> request = new DtoQueryRequest<>(this, dtoQueryEngine, query);
1610-
try {
1611-
request.initTransIfRequired();
1612-
return extractUnique(request.findList());
1613-
} finally {
1614-
request.endTransIfRequired();
1615-
}
1626+
return extractUnique(findDtoList(query));
16161627
}
16171628

16181629
/**

ebean-core/src/main/java/io/ebeaninternal/server/core/DtoQueryRequest.java

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import io.ebean.core.type.DataReader;
55
import io.ebeaninternal.api.SpiDtoQuery;
66
import io.ebeaninternal.api.SpiEbeanServer;
7-
import io.ebeaninternal.api.SpiQuery;
87
import io.ebeaninternal.server.dto.DtoColumn;
98
import io.ebeaninternal.server.dto.DtoMappingRequest;
109
import io.ebeaninternal.server.dto.DtoQueryPlan;
@@ -31,33 +30,30 @@ public final class DtoQueryRequest<T> extends AbstractSqlQueryRequest {
3130
private final DtoQueryEngine queryEngine;
3231
private DtoQueryPlan plan;
3332
private DataReader dataReader;
33+
private SpiOrmQueryRequest<?> ormRequest;
3434

35-
DtoQueryRequest(SpiEbeanServer server, DtoQueryEngine engine, SpiDtoQuery<T> query) {
35+
DtoQueryRequest(SpiEbeanServer server, DtoQueryEngine engine, SpiDtoQuery<T> query, SpiOrmQueryRequest<?> ormRequest) {
3636
super(server, query);
3737
this.queryEngine = engine;
3838
this.query = query;
39+
this.ormRequest = ormRequest;
3940
query.obtainLocation();
4041
}
4142

4243
/**
4344
* Prepare and execute the SQL using the Binder.
4445
*/
4546
@Override
46-
public void executeSql(Binder binder, SpiQuery.Type type) throws SQLException {
47+
public void executeSql(Binder binder) throws SQLException {
4748
startNano = System.nanoTime();
48-
SpiQuery<?> ormQuery = query.ormQuery();
49-
if (ormQuery != null) {
50-
ormQuery.setType(type);
51-
ormQuery.setManualId();
52-
53-
query.setCancelableQuery(ormQuery);
49+
if (ormRequest != null) {
5450
// execute the underlying ORM query returning the ResultSet
55-
ormQuery.usingTransaction(transaction);
56-
SpiResultSet result = server.findResultSet(ormQuery);
51+
query.setCancelableQuery(query.ormQuery());
52+
ormRequest.transaction(transaction);
53+
SpiResultSet result = ormRequest.findResultSet();
5754
this.pstmt = result.statement();
58-
this.sql = ormQuery.getGeneratedSql();
59-
setResultSet(result.resultSet(), ormQuery.queryPlanKey());
60-
55+
this.sql = ormRequest.query().getGeneratedSql();
56+
setResultSet(result.resultSet(), ormRequest.query().queryPlanKey());
6157
} else {
6258
// native SQL query execution
6359
executeAsSql(binder);
@@ -156,4 +152,18 @@ static String parseColumn(String columnLabel) {
156152
return columnLabel;
157153
}
158154

155+
public List<T> getFromQueryCache() {
156+
if (ormRequest != null) {
157+
return ormRequest.getFromQueryCache();
158+
} else {
159+
return null;
160+
}
161+
}
162+
163+
public void putToQueryCache(List<T> result) {
164+
if (ormRequest != null && ormRequest.isQueryCachePut()) {
165+
ormRequest.putToQueryCache(result);
166+
}
167+
}
168+
159169
}

ebean-core/src/main/java/io/ebeaninternal/server/query/DefaultRelationalQueryEngine.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import io.ebean.meta.MetricVisitor;
99
import io.ebean.metric.MetricFactory;
1010
import io.ebean.metric.TimedMetricMap;
11-
import io.ebeaninternal.api.SpiQuery;
1211
import io.ebeaninternal.server.core.RelationalQueryEngine;
1312
import io.ebeaninternal.server.core.RelationalQueryRequest;
1413
import io.ebeaninternal.server.core.RowReader;
@@ -59,7 +58,7 @@ private String errMsg(String msg, String sql) {
5958
@Override
6059
public void findEach(RelationalQueryRequest request, RowConsumer consumer) {
6160
try {
62-
request.executeSql(binder, SpiQuery.Type.ITERATE);
61+
request.executeSql(binder);
6362
request.mapEach(consumer);
6463
request.logSummary();
6564

@@ -74,7 +73,7 @@ public void findEach(RelationalQueryRequest request, RowConsumer consumer) {
7473
@Override
7574
public <T> void findEach(RelationalQueryRequest request, RowReader<T> reader, Predicate<T> consumer) {
7675
try {
77-
request.executeSql(binder, SpiQuery.Type.ITERATE);
76+
request.executeSql(binder);
7877
while (request.next()) {
7978
if (!consumer.test(reader.read())) {
8079
break;
@@ -93,7 +92,7 @@ public <T> void findEach(RelationalQueryRequest request, RowReader<T> reader, Pr
9392
@Override
9493
public <T> T findOne(RelationalQueryRequest request, RowMapper<T> mapper) {
9594
try {
96-
request.executeSql(binder, SpiQuery.Type.BEAN);
95+
request.executeSql(binder);
9796
T value = request.mapOne(mapper);
9897
request.logSummary();
9998
return value;
@@ -109,7 +108,7 @@ public <T> T findOne(RelationalQueryRequest request, RowMapper<T> mapper) {
109108
@Override
110109
public <T> List<T> findList(RelationalQueryRequest request, RowReader<T> reader) {
111110
try {
112-
request.executeSql(binder, SpiQuery.Type.LIST);
111+
request.executeSql(binder);
113112
List<T> rows = new ArrayList<>();
114113
while (request.next()) {
115114
rows.add(reader.read());
@@ -129,7 +128,7 @@ public <T> List<T> findList(RelationalQueryRequest request, RowReader<T> reader)
129128
public <T> T findSingleAttribute(RelationalQueryRequest request, Class<T> cls) {
130129
ScalarType<T> scalarType = (ScalarType<T>) binder.getScalarType(cls);
131130
try {
132-
request.executeSql(binder, SpiQuery.Type.ATTRIBUTE);
131+
request.executeSql(binder);
133132
final DataReader dataReader = binder.createDataReader(request.resultSet());
134133
T value = null;
135134
if (dataReader.next()) {
@@ -151,7 +150,7 @@ public <T> T findSingleAttribute(RelationalQueryRequest request, Class<T> cls) {
151150
public <T> List<T> findSingleAttributeList(RelationalQueryRequest request, Class<T> cls) {
152151
ScalarType<T> scalarType = (ScalarType<T>) binder.getScalarType(cls);
153152
try {
154-
request.executeSql(binder, SpiQuery.Type.ATTRIBUTE);
153+
request.executeSql(binder);
155154
final DataReader dataReader = binder.createDataReader(request.resultSet());
156155
List<T> rows = new ArrayList<>();
157156
while (dataReader.next()) {
@@ -173,7 +172,7 @@ public <T> List<T> findSingleAttributeList(RelationalQueryRequest request, Class
173172
public <T> void findSingleAttributeEach(RelationalQueryRequest request, Class<T> cls, Consumer<T> consumer) {
174173
ScalarType<T> scalarType = (ScalarType<T>) binder.getScalarType(cls);
175174
try {
176-
request.executeSql(binder, SpiQuery.Type.ATTRIBUTE);
175+
request.executeSql(binder);
177176
final DataReader dataReader = binder.createDataReader(request.resultSet());
178177
while (dataReader.next()) {
179178
consumer.accept(scalarType.read(dataReader));

ebean-core/src/main/java/io/ebeaninternal/server/query/DtoQueryEngine.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,12 @@ public DtoQueryEngine(Binder binder) {
2222

2323
public <T> List<T> findList(DtoQueryRequest<T> request) {
2424
try {
25-
request.executeSql(binder, SpiQuery.Type.LIST);
25+
request.executeSql(binder);
2626
List<T> rows = new ArrayList<>();
2727
while (request.next()) {
2828
rows.add(request.readNextBean());
2929
}
30+
request.putToQueryCache(rows);
3031
return rows;
3132

3233
} catch (SQLException e) {
@@ -38,7 +39,7 @@ public <T> List<T> findList(DtoQueryRequest<T> request) {
3839

3940
public <T> QueryIterator<T> findIterate(DtoQueryRequest<T> request) {
4041
try {
41-
request.executeSql(binder, SpiQuery.Type.ITERATE);
42+
request.executeSql(binder);
4243
return new DtoQueryIterator<>(request);
4344
} catch (SQLException e) {
4445
throw new PersistenceException(errMsg(e.getMessage(), request.getSql()), e);
@@ -47,7 +48,7 @@ public <T> QueryIterator<T> findIterate(DtoQueryRequest<T> request) {
4748

4849
public <T> void findEach(DtoQueryRequest<T> request, Consumer<T> consumer) {
4950
try {
50-
request.executeSql(binder, SpiQuery.Type.ITERATE);
51+
request.executeSql(binder);
5152
while (request.next()) {
5253
consumer.accept(request.readNextBean());
5354
}
@@ -61,7 +62,7 @@ public <T> void findEach(DtoQueryRequest<T> request, Consumer<T> consumer) {
6162
public <T> void findEach(DtoQueryRequest<T> request, int batchSize, Consumer<List<T>> consumer) {
6263
try {
6364
List<T> buffer = new ArrayList<>();
64-
request.executeSql(binder, SpiQuery.Type.ITERATE);
65+
request.executeSql(binder);
6566
while (request.next()) {
6667
buffer.add(request.readNextBean());
6768
if (buffer.size() >= batchSize) {
@@ -82,7 +83,7 @@ public <T> void findEach(DtoQueryRequest<T> request, int batchSize, Consumer<Lis
8283

8384
public <T> void findEachWhile(DtoQueryRequest<T> request, Predicate<T> consumer) {
8485
try {
85-
request.executeSql(binder, SpiQuery.Type.ITERATE);
86+
request.executeSql(binder);
8687
while (request.next()) {
8788
if (!consumer.test(request.readNextBean())) {
8889
break;

ebean-core/src/main/java/io/ebeaninternal/server/querydefn/DefaultOrmQuery.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
163163
private String nativeSql;
164164
private boolean orderById;
165165
private ProfileLocation profileLocation;
166+
private Class<?> dtoType = Object.class; // default: Object saves some null-checks.
166167

167168
public DefaultOrmQuery(BeanDescriptor<T> desc, SpiEbeanServer server, ExpressionFactory expressionFactory) {
168169
this.beanDescriptor = desc;
@@ -1240,7 +1241,7 @@ public final HashQuery queryHash() {
12401241
// so queryPlanHash is calculated well before this method is called
12411242
BindValuesKey bindKey = new BindValuesKey();
12421243
queryBindKey(bindKey);
1243-
return new HashQuery(queryPlanKey, bindKey);
1244+
return new HashQuery(queryPlanKey, bindKey, dtoType);
12441245
}
12451246

12461247
@Override
@@ -1726,6 +1727,11 @@ public final void setManualId() {
17261727
}
17271728
}
17281729

1730+
@Override
1731+
public void setDtoType(Class<?> dtoType) {
1732+
this.dtoType = dtoType;
1733+
}
1734+
17291735
/**
17301736
* return true if user specified to use SQL DISTINCT (effectively excludes id property).
17311737
*/

0 commit comments

Comments
 (0)