#1407 - ENH: Add SqlQuery RowMapper and RowConsumer ... for raw JDBC ResultSet mapping and consuming

This commit is contained in:
rob bygrave
2018-06-08 02:04:38 +12:00
parent fb32cfa170
commit 7cbae758fc
11 changed files with 421 additions and 13 deletions
@@ -4,6 +4,8 @@ import io.ebean.DtoQuery;
import io.ebean.EbeanServer;
import io.ebean.PersistenceContextScope;
import io.ebean.Query;
import io.ebean.RowConsumer;
import io.ebean.RowMapper;
import io.ebean.Transaction;
import io.ebean.TxScope;
import io.ebean.bean.BeanCollectionLoader;
@@ -244,6 +246,21 @@ public interface SpiEbeanServer extends EbeanServer, BeanLoader, BeanCollectionL
*/
<T> List<T> findSingleAttributeList(SpiSqlQuery query, Class<T> cls);
/**
* SqlQuery find one with mapper.
*/
<T> T findOneMapper(SpiSqlQuery query, RowMapper<T> mapper);
/**
* SqlQuery find list with mapper.
*/
<T> List<T> findListMapper(SpiSqlQuery query, RowMapper<T> mapper);
/**
* SqlQuery find each with consumer.
*/
void findEachRow(SpiSqlQuery query, RowConsumer consumer);
/**
* DTO findList query.
*/
@@ -19,6 +19,8 @@ import io.ebean.PersistenceContextScope;
import io.ebean.ProfileLocation;
import io.ebean.Query;
import io.ebean.QueryIterator;
import io.ebean.RowConsumer;
import io.ebean.RowMapper;
import io.ebean.SqlQuery;
import io.ebean.SqlRow;
import io.ebean.SqlUpdate;
@@ -1586,29 +1588,39 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
}
}
@Override
public <T> List<T> findSingleAttributeList(SpiSqlQuery query, Class<T> cls) {
private <P> P executeSqlQuery(Function<RelationalQueryRequest, P> fun, SpiSqlQuery query) {
RelationalQueryRequest request = new RelationalQueryRequest(this, relationalQueryEngine, query, null);
try {
request.initTransIfRequired();
return request.findSingleAttributeList(cls);
return fun.apply(request);
} finally {
request.endTransIfRequired();
}
}
@Override
public void findEachRow(SpiSqlQuery query, RowConsumer consumer) {
executeSqlQuery((req) -> req.findEachRow(consumer), query);
}
@Override
public <T> List<T> findListMapper(SpiSqlQuery query, RowMapper<T> mapper) {
return executeSqlQuery((req) -> req.findListMapper(mapper), query);
}
@Override
public <T> T findOneMapper(SpiSqlQuery query, RowMapper<T> mapper) {
return executeSqlQuery((req) -> req.findOneMapper(mapper), query);
}
@Override
public <T> List<T> findSingleAttributeList(SpiSqlQuery query, Class<T> cls) {
return executeSqlQuery((req) -> req.findSingleAttributeList(cls), query);
}
@Override
public <T> T findSingleAttribute(SpiSqlQuery query, Class<T> cls) {
RelationalQueryRequest request = new RelationalQueryRequest(this, relationalQueryEngine, query, null);
try {
request.initTransIfRequired();
return request.findSingleAttribute(cls);
} finally {
request.endTransIfRequired();
}
return executeSqlQuery((req) -> req.findSingleAttribute(cls), query);
}
@Override
@@ -1,6 +1,8 @@
package io.ebeaninternal.server.core;
import io.ebean.RowConsumer;
import io.ebean.RowMapper;
import io.ebean.SqlRow;
import io.ebean.meta.MetricVisitor;
@@ -40,6 +42,21 @@ public interface RelationalQueryEngine {
*/
<T> List<T> findSingleAttributeList(RelationalQueryRequest request, Class<T> cls);
/**
* Find one via mapper.
*/
<T> T findOneMapper(RelationalQueryRequest request, RowMapper<T> mapper);
/**
* Find list via mapper.
*/
<T> List<T> findListMapper(RelationalQueryRequest request, RowMapper<T> mapper);
/**
* Find each via raw consumer.
*/
void findEachRow(RelationalQueryRequest request, RowConsumer mapper);
/**
* Collect SQL query execution statistics.
*/
@@ -1,5 +1,7 @@
package io.ebeaninternal.server.core;
import io.ebean.RowConsumer;
import io.ebean.RowMapper;
import io.ebean.SqlQuery;
import io.ebean.SqlRow;
import io.ebean.Transaction;
@@ -53,6 +55,19 @@ public final class RelationalQueryRequest extends AbstractSqlQueryRequest {
}
}
boolean findEachRow(RowConsumer mapper) {
queryEngine.findEachRow(this, mapper);
return true;
}
<T> List<T> findListMapper(RowMapper<T> mapper) {
return queryEngine.findListMapper(this, mapper);
}
<T> T findOneMapper(RowMapper<T> mapper) {
return queryEngine.findOneMapper(this, mapper);
}
public <T> List<T> findSingleAttributeList(Class<T> cls) {
return queryEngine.findSingleAttributeList(this, cls);
}
@@ -119,4 +134,28 @@ public final class RelationalQueryRequest extends AbstractSqlQueryRequest {
public void incrementRows() {
rows++;
}
public <T> List<T> mapList(RowMapper<T> mapper) throws SQLException {
List<T> list = new ArrayList<>();
while (next()) {
list.add(mapper.map(resultSet, rows++));
}
return list;
}
public <T> T mapOne(RowMapper<T> mapper) throws SQLException {
if (!next()) {
return null;
} else {
return mapper.map(resultSet, rows++);
}
}
public void mapEach(RowConsumer consumer) throws SQLException {
while (next()) {
consumer.accept(resultSet, rows++);
}
}
}
@@ -1,5 +1,7 @@
package io.ebeaninternal.server.query;
import io.ebean.RowConsumer;
import io.ebean.RowMapper;
import io.ebean.SqlRow;
import io.ebean.meta.MetricType;
import io.ebean.meta.MetricVisitor;
@@ -92,6 +94,53 @@ public class DefaultRelationalQueryEngine implements RelationalQueryEngine {
}
}
@Override
public <T> T findOneMapper(RelationalQueryRequest request, RowMapper<T> mapper) {
try {
request.executeSql(binder, SpiQuery.Type.BEAN);
T value = request.mapOne(mapper);
request.logSummary();
return value;
} catch (Exception e) {
throw new PersistenceException(Message.msg("fetch.error", e.getMessage(), request.getSql()), e);
} finally {
request.close();
}
}
@Override
public <T> List<T> findListMapper(RelationalQueryRequest request, RowMapper<T> mapper) {
try {
request.executeSql(binder, SpiQuery.Type.LIST);
List<T> list = request.mapList(mapper);
request.logSummary();
return list;
} catch (Exception e) {
throw new PersistenceException(Message.msg("fetch.error", e.getMessage(), request.getSql()), e);
} finally {
request.close();
}
}
@Override
public void findEachRow(RelationalQueryRequest request, RowConsumer consumer) {
try {
request.executeSql(binder, SpiQuery.Type.LIST);
request.mapEach(consumer);
request.logSummary();
} catch (Exception e) {
throw new PersistenceException(Message.msg("fetch.error", e.getMessage(), request.getSql()), e);
} finally {
request.close();
}
}
@SuppressWarnings("unchecked")
@Override
public <T> List<T> findSingleAttributeList(RelationalQueryRequest request, Class<T> cls) {
@@ -1,5 +1,7 @@
package io.ebeaninternal.server.querydefn;
import io.ebean.RowConsumer;
import io.ebean.RowMapper;
import io.ebean.SqlRow;
import io.ebeaninternal.api.BindParams;
import io.ebeaninternal.api.SpiEbeanServer;
@@ -69,6 +71,21 @@ public class DefaultRelationalQuery implements SpiSqlQuery {
return server.findSingleAttributeList(this, cls);
}
@Override
public <T> T findOne(RowMapper<T> mapper) {
return server.findOneMapper(this, mapper);
}
@Override
public <T> List<T> findList(RowMapper<T> mapper) {
return server.findListMapper(this, mapper);
}
@Override
public void findEachRow(RowConsumer consumer) {
server.findEachRow(this, consumer);
}
@Override
public SqlRow findOne() {
return server.findOne(this, null);