#1297 - ENH: Add DtoQuery ... such that we can map native SQL queries automatically into "DTO beans"

This commit is contained in:
Rob Bygrave
2018-03-02 23:32:01 +13:00
parent 5801f7620d
commit aad5b33db2
47 changed files with 2293 additions and 273 deletions
@@ -1,6 +1,8 @@
package io.ebeaninternal.server.profile;
import io.ebeaninternal.metric.MetricFactory;
import io.ebeaninternal.metric.QueryPlanCollector;
import io.ebeaninternal.metric.QueryPlanMetric;
import io.ebeaninternal.metric.TimedMetric;
import io.ebeaninternal.metric.TimedMetricMap;
@@ -18,4 +20,14 @@ public class DMetricFactory implements MetricFactory {
public TimedMetric createTimedMetric(String name) {
return new DTimedMetric(name);
}
@Override
public QueryPlanMetric createQueryPlanMetric(Class<?> type, String label, String sql) {
return new DQueryPlanMetric(new DQueryPlanMeta(type, label, sql), createTimedMetric(label));
}
@Override
public QueryPlanCollector createCollector(boolean reset) {
return new DQueryPlanCollector(reset);
}
}
@@ -0,0 +1,33 @@
package io.ebeaninternal.server.profile;
import io.ebean.meta.MetaQueryMetric;
import io.ebeaninternal.metric.QueryPlanCollector;
import java.util.ArrayList;
import java.util.List;
class DQueryPlanCollector implements QueryPlanCollector {
private final boolean reset;
private final List<MetaQueryMetric> list = new ArrayList<>();
DQueryPlanCollector(boolean reset) {
this.reset = reset;
}
@Override
public boolean isReset() {
return reset;
}
@Override
public void add(MetaQueryMetric stats) {
list.add(stats);
}
@Override
public List<MetaQueryMetric> complete() {
return list;
}
}
@@ -0,0 +1,31 @@
package io.ebeaninternal.server.profile;
class DQueryPlanMeta {
private final Class<?> type;
private final String label;
private final String sql;
DQueryPlanMeta(Class<?> type, String label, String sql) {
this.type = type;
this.label = label;
this.sql = sql;
}
public Class<?> getType() {
return type;
}
public String getLabel() {
return label;
}
public String getSql() {
return sql;
}
@Override
public String toString() {
return "type:" + type + " label:" + label;
}
}
@@ -0,0 +1,102 @@
package io.ebeaninternal.server.profile;
import io.ebean.meta.MetaQueryMetric;
import io.ebeaninternal.metric.QueryPlanCollector;
import io.ebeaninternal.metric.QueryPlanMetric;
import io.ebeaninternal.metric.TimedMetric;
import io.ebeaninternal.metric.TimedMetricStats;
class DQueryPlanMetric implements QueryPlanMetric {
private final DQueryPlanMeta meta;
private final TimedMetric metric;
DQueryPlanMetric(DQueryPlanMeta meta, TimedMetric metric) {
this.meta = meta;
this.metric = metric;
}
@Override
public void collect(QueryPlanCollector collector) {
TimedMetricStats stats = metric.collect(collector.isReset());
if (stats != null) {
collector.add(new Stats(meta, stats));
}
}
@Override
public TimedMetric getMetric() {
return metric;
}
private static class Stats implements MetaQueryMetric {
private final DQueryPlanMeta meta;
private final TimedMetricStats stats;
private Stats(DQueryPlanMeta meta, TimedMetricStats stats) {
this.meta = meta;
this.stats = stats;
}
@Override
public String toString() {
return meta +" "+ stats;
}
@Override
public Class<?> getType() {
return meta.getType();
}
@Override
public String getLabel() {
return meta.getLabel();
}
@Override
public String getSql() {
return meta.getSql();
}
@Override
public String getName() {
return stats.getName();
}
@Override
public String getLocation() {
return stats.getLocation();
}
@Override
public long getStartTime() {
return stats.getStartTime();
}
@Override
public long getCount() {
return stats.getCount();
}
@Override
public long getTotal() {
return stats.getTotal();
}
@Override
public long getMax() {
return stats.getMax();
}
@Override
public long getMean() {
return stats.getMean();
}
@Override
public long getBeanCount() {
return stats.getBeanCount();
}
}
}
@@ -19,7 +19,9 @@ class DTimeMetricStats implements TimedMetricStats {
private final long max;
DTimeMetricStats(String name, long collectionStart, long count, long total, long max) {
private final long beanCount;
DTimeMetricStats(String name, long collectionStart, long count, long total, long max, long beanCount) {
this.name = name;
this.startTime = collectionStart;
this.count = count;
@@ -27,6 +29,7 @@ class DTimeMetricStats implements TimedMetricStats {
// collection is racy so sanitize the max value if it has not been set
// this most likely would happen when count = 1 so max = mean
this.max = max != Long.MIN_VALUE ? max : (count < 1 ? 0 : Math.round(total / count));
this.beanCount = beanCount;
}
@Override
@@ -40,7 +43,8 @@ class DTimeMetricStats implements TimedMetricStats {
}
sb.append("count:").append(count)
.append(" total:").append(total)
.append(" max:").append(max);
.append(" max:").append(max)
.append(" beanCount:").append(beanCount);
return sb.toString();
}
@@ -99,4 +103,8 @@ class DTimeMetricStats implements TimedMetricStats {
return (count < 1) ? 0L : Math.round((double)(total / count));
}
@Override
public long getBeanCount() {
return beanCount;
}
}
@@ -16,15 +16,17 @@ import java.util.concurrent.atomic.LongAdder;
*/
class DTimedMetric implements TimedMetric {
protected final String name;
private final String name;
protected final LongAdder count = new LongAdder();
private final LongAdder beanCount = new LongAdder();
protected final LongAdder total = new LongAdder();
private final LongAdder count = new LongAdder();
protected final LongAccumulator max = new LongAccumulator(Math::max, Long.MIN_VALUE);
private final LongAdder total = new LongAdder();
protected final AtomicLong startTime = new AtomicLong(System.currentTimeMillis());
private final LongAccumulator max = new LongAccumulator(Math::max, Long.MIN_VALUE);
private final AtomicLong startTime = new AtomicLong(System.currentTimeMillis());
DTimedMetric(String name) {
this.name = name;
@@ -41,6 +43,12 @@ class DTimedMetric implements TimedMetric {
max.accumulate(value);
}
@Override
public void add(long micros, long beans) {
add(micros);
beanCount.add(beans);
}
@Override
public boolean isEmpty() {
return count.sum() == 0;
@@ -75,14 +83,15 @@ class DTimedMetric implements TimedMetric {
if (reset) {
// Note these values are not guaranteed to be consistent wrt each other
// but should be reasonably consistent (small time between count and total)
final long beans = beanCount.sumThenReset();
final long maxVal = max.getThenReset();
final long totalVal = total.sumThenReset();
final long countVal = count.sumThenReset();
final long startTimeVal = startTime.getAndSet(System.currentTimeMillis());
return new DTimeMetricStats(name, startTimeVal, countVal, totalVal, maxVal);
return new DTimeMetricStats(name, startTimeVal, countVal, totalVal, maxVal, beans);
} else {
return new DTimeMetricStats(name, startTime.get(), count.sum(), total.sum(), max.get());
return new DTimeMetricStats(name, startTime.get(), count.sum(), total.sum(), max.get(), beanCount.sum());
}
}
@@ -96,32 +105,4 @@ class DTimedMetric implements TimedMetric {
total.reset();
}
/**
* Return the start time.
*/
public long getStartTime() {
return startTime.get();
}
/**
* Return the count of values.
*/
public long getCount() {
return count.sum();
}
/**
* Return the total of values.
*/
public long getTotal() {
return total.sum();
}
/**
* Return the max value.
*/
public long getMax() {
return max.get();
}
}