@Override public <A> A performTransaction(Function<DatastoreOperations, A> operations) { if (!(getDatastoreReadWriter() instanceof Datastore)) { throw new DatastoreDataException( "This DatastoreReadWriter cannot be used to run transactions. A full Datastore service" + " object is required to run functions as transactions. Ensure that this method " + "was not called in an ongoing transaction."); } return ((Datastore) getDatastoreReadWriter()) .runInTransaction( (DatastoreReaderWriter readerWriter) -> operations.apply(new DatastoreTemplate(readerWriter, DatastoreTemplate.this.datastoreEntityConverter, DatastoreTemplate.this.datastoreMappingContext, DatastoreTemplate.this.objectToKeyFactory))); }
@Override public <T> Iterable<T> query(Query<? extends BaseEntity> query, Class<T> entityClass) { return convertEntitiesForRead(getDatastoreReadWriter().run(query), entityClass); }
@Override public <T> T save(T instance, Key... ancestors) { getDatastoreReadWriter().put(convertToEntityForSave(instance, ancestors)); return instance; }
@Override public <T> Collection<T> findAllById(Iterable<?> ids, Class<T> entityClass) { List<Key> keysToFind = getKeysFromIds(ids, entityClass); return convertEntitiesForRead( getDatastoreReadWriter().get( keysToFind.toArray(new Key[keysToFind.size()])), entityClass); }
@Override public <T> Collection<T> findAll(Class<T> entityClass, DatastoreQueryOptions queryOptions) { DatastorePersistentEntity<?> persistentEntity = this.datastoreMappingContext.getPersistentEntity(entityClass); EntityQuery.Builder builder = Query.newEntityQueryBuilder() .setKind(persistentEntity.kindName()); applyQueryOptions(builder, queryOptions, persistentEntity); return convertEntitiesForRead(getDatastoreReadWriter().run(builder.build()), entityClass); }
private void deleteFoundEntities(boolean returnedTypeIsNumber, Iterable rawResults) { if (returnedTypeIsNumber) { getDatastoreTemplate().deleteAllById(rawResults, this.entityType); } else { getDatastoreTemplate().deleteAll(rawResults); } }
private Slice executeSliceQuery(Object[] parameters) { EntityQuery.Builder builder = StructuredQuery.newEntityQueryBuilder() .setKind(this.datastorePersistentEntity.kindName()); StructuredQuery query = applyQueryBody(parameters, builder, false); List items = this.datastoreTemplate.query((query), (x) -> x); Integer limit = (query.getLimit() == null) ? null : query.getLimit() - 1; boolean exceedsLimit = false; if (limit != null) { //for slice queries we retrieve one additional item to check if the next slice exists //the additional item will not be converted on read exceedsLimit = items.size() > limit; if (exceedsLimit) { items = items.subList(0, limit); } } ParameterAccessor paramAccessor = new ParametersParameterAccessor(getQueryMethod().getParameters(), parameters); Pageable pageable = paramAccessor.getPageable(); List entities = (List) this.datastoreTemplate .convertEntitiesForRead(items.iterator(), this.entityType).stream() .map((o) -> this.processRawObjectForProjection((T) o)).collect(Collectors.toList()); return new SliceImpl(entities, pageable, exceedsLimit); }
@Bean @ConditionalOnMissingBean public DatastoreTemplate datastoreTemplate(Datastore datastore, DatastoreMappingContext datastoreMappingContext, DatastoreEntityConverter datastoreEntityConverter, ObjectToKeyFactory objectToKeyFactory) { return new DatastoreTemplate(datastore, datastoreEntityConverter, datastoreMappingContext, objectToKeyFactory); } }
@Override public <T> Iterable<T> queryByExample(Example<T> example, DatastoreQueryOptions queryOptions) { return query(exampleToQuery(example, queryOptions, false), example.getProbeType()); }
private <T> StructuredQuery exampleToQuery(Example<T> example, DatastoreQueryOptions queryOptions, boolean keyQuery) { validateExample(example); applyQueryOptions(builder, queryOptions, persistentEntity); return builder.build();
@Override public <T> Collection<T> findAll(Class<T> entityClass) { return findAll(entityClass, null); }
public static void applyQueryOptions(StructuredQuery.Builder builder, DatastoreQueryOptions queryOptions, DatastorePersistentEntity<?> persistentEntity) { if (queryOptions == null) { return; } if (queryOptions.getLimit() != null) { builder.setLimit(queryOptions.getLimit()); } if (queryOptions.getOffset() != null) { builder.setOffset(queryOptions.getOffset()); } if (queryOptions.getSort() != null && persistentEntity != null) { queryOptions.getSort().stream() .map((order) -> createOrderBy(persistentEntity, order)) .forEachOrdered((orderBy) -> builder.addOrderBy(orderBy)); } }
/** * Convert Datastore entities to objects of a specified type. * @param entities the Datastore entities * @param entityClass the type the entities should be converted to. * @param <T> the type the entities should be converted to. * @return a list of converted entities */ public <T> List<T> convertEntitiesForRead(Iterator<? extends BaseEntity> entities, Class<T> entityClass) { List<T> results = new ArrayList<>(); if (entities == null) { return results; } DatastorePersistentEntity datastorePersistentEntity = this.datastoreMappingContext .getPersistentEntity(entityClass); entities.forEachRemaining((entity) -> convertEntityResolveDescendantsAndReferences( entityClass, results, datastorePersistentEntity, entity)); return results; }
private StructuredQuery applyQueryBody(Object[] parameters, StructuredQuery.Builder builder, boolean total) { ParameterAccessor paramAccessor = new ParametersParameterAccessor(getQueryMethod().getParameters(), parameters); if (this.tree.hasPredicate()) { applySelectWithFilter(parameters, builder); } Integer limit = null; Integer offset = null; if (this.tree.isExistsProjection()) { limit = 1; } else if (this.tree.isLimiting()) { limit = this.tree.getMaxResults(); } Sort sort = this.tree.getSort(); if (getQueryMethod().getParameters().hasPageableParameter()) { sort = sort.and(paramAccessor.getPageable().getSort()); } if (getQueryMethod().getParameters().hasSortParameter()) { sort = sort.and(paramAccessor.getSort()); } if (paramAccessor.getPageable().isPaged() && !total) { //for slice queries we retrieve one additional item to check if the next slice exists limit = paramAccessor.getPageable().getPageSize() + (isSliceQuery() ? 1 : 0); offset = (int) paramAccessor.getPageable().getOffset(); } DatastoreTemplate.applyQueryOptions( builder, new DatastoreQueryOptions(limit, offset, sort), this.datastorePersistentEntity); return builder.build(); }
@Override public <T> Iterable<Key> keyQueryByExample(Example<T> example, DatastoreQueryOptions queryOptions) { QueryResults results = this.datastore.run(exampleToQuery(example, queryOptions, true)); return () -> results; }
@Override public <T> Collection<T> findAllById(Iterable<?> ids, Class<T> entityClass) { List<Key> keysToFind = getKeysFromIds(ids, entityClass); return convertEntitiesForRead( getDatastoreReadWriter().get( keysToFind.toArray(new Key[keysToFind.size()])), entityClass); }
@Override public <T> Collection<T> findAll(Class<T> entityClass, DatastoreQueryOptions queryOptions) { DatastorePersistentEntity<?> persistentEntity = this.datastoreMappingContext.getPersistentEntity(entityClass); EntityQuery.Builder builder = Query.newEntityQueryBuilder() .setKind(persistentEntity.kindName()); applyQueryOptions(builder, queryOptions, persistentEntity); return convertEntitiesForRead(getDatastoreReadWriter().run(builder.build()), entityClass); }
private void deleteFoundEntities(boolean returnedTypeIsNumber, Iterable rawResults) { if (returnedTypeIsNumber) { getDatastoreTemplate().deleteAllById(rawResults, this.entityType); } else { getDatastoreTemplate().deleteAll(rawResults); } }
private Slice executeSliceQuery(Object[] parameters) { EntityQuery.Builder builder = StructuredQuery.newEntityQueryBuilder() .setKind(this.datastorePersistentEntity.kindName()); StructuredQuery query = applyQueryBody(parameters, builder, false); List items = this.datastoreTemplate.query((query), (x) -> x); Integer limit = (query.getLimit() == null) ? null : query.getLimit() - 1; boolean exceedsLimit = false; if (limit != null) { //for slice queries we retrieve one additional item to check if the next slice exists //the additional item will not be converted on read exceedsLimit = items.size() > limit; if (exceedsLimit) { items = items.subList(0, limit); } } ParameterAccessor paramAccessor = new ParametersParameterAccessor(getQueryMethod().getParameters(), parameters); Pageable pageable = paramAccessor.getPageable(); List entities = (List) this.datastoreTemplate .convertEntitiesForRead(items.iterator(), this.entityType).stream() .map((o) -> this.processRawObjectForProjection((T) o)).collect(Collectors.toList()); return new SliceImpl(entities, pageable, exceedsLimit); }
@Override public <T> Collection<T> findAll(Class<T> entityClass) { return findAll(entityClass, null); }