use of com.peterphi.std.NotImplementedException in project stdlib by petergeneric.
the class JPAQueryBuilder method forIDs.
public void forIDs(final WebQuery original, final List<?> ids) {
this.params.clear();
this.generated = criteriaBuilder.createQuery();
this.generated.distinct(false);
if (original != null) {
addFrom(original.constraints.subclass);
// Re-state the order (so intra-page order is still correct, since otherwise it'll be whatever order the database decides to return)
addOrders(original.orderings);
// Make sure we eagerly fetch what's requested
addExpandAndFetches(original);
// Don't set an offset or limit when selecting specific IDs
this.offset = null;
this.limit = null;
} else {
addFrom(null);
}
if (root.getModel().hasSingleIdAttribute()) {
final Class idClass = root.getModel().getIdType().getJavaType();
final Path id = root.get(root.getModel().getId(idClass));
generated.where(id.in(param(ids)));
} else {
throw new NotImplementedException("Cannot handle query by IDs with IdClass!");
}
}
use of com.peterphi.std.NotImplementedException in project stdlib by petergeneric.
the class JPAQueryBuilder method createSelectIDs.
public Query createSelectIDs() {
this.generated.distinct(true);
// Make sure we return the results in the correct order
generated.orderBy(orders);
List<Selection<?>> selects = new ArrayList<>();
if (root.getModel().hasSingleIdAttribute()) {
selects.add(root.get(root.getModel().getId(root.getModel().getIdType().getJavaType())));
} else
throw new NotImplementedException("Cannot handle ID selection with IdClass!");
for (Order order : orders) {
selects.add(order.getExpression());
}
if (selects.size() == 1)
generated.select(selects.get(0));
else
generated.multiselect(selects);
final Query query = session.createQuery(generated);
if (offset != null)
query.getQueryOptions().setFirstRow(offset);
if (limit != null)
query.getQueryOptions().setMaxRows(limit);
// Set all the parameters
for (Map.Entry<ParameterExpression, Object> entry : this.params.entrySet()) {
query.setParameter(entry.getKey(), entry.getValue());
}
return query;
}
use of com.peterphi.std.NotImplementedException in project stdlib by petergeneric.
the class JPASearchExecutor method find.
/**
* Execute a search, returning a ConstrainedResultSet populated with the desired data (ID or Entity) with each piece of data
* optionally serialised using the supplied serialiser
*
* @param query
* the query to execute (including options like offset/limit, )
* @param strategy
* @param serialiser
* @param <T>
*
* @return
*/
public <T> ConstrainedResultSet<T> find(final QEntity entity, final WebQuery query, JPASearchStrategy strategy, Function<?, ?> serialiser) {
final String traceOperationId = Tracing.log("WebQuery:exec", () -> query.toString());
final HibernateSQLLogger statementLog;
if (query.isLogSQL())
statementLog = hibernateObserver.startSQLLogger(traceOperationId);
else
statementLog = null;
try {
// Build a view of the query based on
JPAQueryBuilder builder = new JPAQueryBuilder(sessionFactory.getCurrentSession(), entity);
builder.forWebQuery(query);
// First, compute the total size if requested
final Long total;
if (ALWAYS_COMPUTE_SIZE || query.isComputeSize()) {
JPAQueryBuilder countBuilder = new JPAQueryBuilder(sessionFactory.getCurrentSession(), entity);
countBuilder.forWebQuery(query);
total = countBuilder.selectCount();
} else {
total = null;
}
// If the auto strategy is in play, take into account what's being fetched back as well as whether there are any explicit collection joins or fetches
if (strategy == null || strategy == JPASearchStrategy.AUTO) {
if (StringUtils.equals(query.getFetch(), "id")) {
strategy = JPASearchStrategy.ENTITY_WRAPPED_ID;
} else {
// This is necessary for correct pagination because the SQL resultset will have more than one row per entity, and our offset/limit is based on entity
if ((query.getLimit() > 0 || query.getOffset() > 0) && (builder.hasCollectionJoin() || builder.hasCollectionFetch())) {
strategy = JPASearchStrategy.ID_THEN_QUERY_ENTITY;
} else {
strategy = JPASearchStrategy.ENTITY;
}
}
}
List list;
switch(strategy) {
case ID:
{
list = builder.selectIDs();
break;
}
case ENTITY_WRAPPED_ID:
{
list = builder.selectIDs();
// Transform the IDs into entity objects with the ID field populated
list = (List) list.stream().map(entity::newInstanceWithId).collect(Collectors.toList());
break;
}
case ENTITY:
{
// TODO could we use ScrollableResults if there are collection joins? pagination would be tricky
list = builder.selectEntity();
break;
}
case ID_THEN_QUERY_ENTITY:
{
// First, query for the IDs (and the total results if desired)
list = builder.selectIDs();
// Now re-query to retrieve the entities
builder = new JPAQueryBuilder(sessionFactory.getCurrentSession(), entity);
builder.forIDs(query, list);
if (!list.isEmpty())
list = builder.selectEntity();
break;
}
default:
throw new NotImplementedException("Search Strategy " + strategy + " not yet implemented");
}
// If a serialiser has been supplied,
if (serialiser != null)
list = (List) list.stream().map(serialiser).collect(Collectors.toList());
ConstrainedResultSet resultset = new ConstrainedResultSet<>(query, list);
if (statementLog != null && query.isLogSQL())
resultset.setSql(statementLog.getAllStatements());
if (total != null)
resultset.setTotal(total);
Tracing.logOngoing(traceOperationId, "WebQuery:exec:result", () -> "size=" + resultset.getList().size() + ", total=" + total);
return (ConstrainedResultSet<T>) resultset;
} finally {
if (statementLog != null)
statementLog.close();
}
}
Aggregations