Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
import java.util.stream.Stream;

import org.jspecify.annotations.Nullable;

import org.springframework.core.annotation.MergedAnnotation;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.support.DefaultConversionService;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
*
* @author Mark Paluch
* @author Diego Krupitza
* @author Artemiy Degtyarev
* @since 2.2
*/
public class JdbcCountQueryCreator extends JdbcQueryCreator {
Expand All @@ -44,8 +45,9 @@ public JdbcCountQueryCreator(PartTree tree, JdbcConverter converter, Dialect dia

JdbcCountQueryCreator(RelationalMappingContext context, PartTree tree, JdbcConverter converter, Dialect dialect,
RelationalEntityMetadata<?> entityMetadata, RelationalParameterAccessor accessor, boolean isSliceQuery,
ReturnedType returnedType, Optional<Lock> lockMode) {
super(context, tree, converter, dialect, entityMetadata, accessor, isSliceQuery, returnedType, lockMode);
ReturnedType returnedType, Optional<Lock> lockMode, boolean isScrollQuery) {
super(context, tree, converter, dialect, entityMetadata, accessor, isSliceQuery, returnedType, lockMode,
isScrollQuery);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import java.util.Optional;

import org.jspecify.annotations.Nullable;

import org.springframework.data.domain.Sort;
import org.springframework.data.jdbc.core.convert.JdbcConverter;
import org.springframework.data.jdbc.core.convert.SqlGeneratorSource;
Expand Down Expand Up @@ -47,6 +46,7 @@
* @author Jens Schauder
* @author Myeonghyeon Lee
* @author Diego Krupitza
* @author Artemiy Degtyarev
* @since 2.0
*/
public class JdbcQueryCreator extends RelationalQueryCreator<ParametrizedQuery> {
Expand All @@ -59,6 +59,7 @@ public class JdbcQueryCreator extends RelationalQueryCreator<ParametrizedQuery>
private final ReturnedType returnedType;
private final Optional<Lock> lockMode;
private final StatementFactory statementFactory;
private final boolean isScrollQuery;

/**
* Creates new instance of this class with the given {@link PartTree}, {@link JdbcConverter}, {@link Dialect},
Expand All @@ -73,15 +74,15 @@ public class JdbcQueryCreator extends RelationalQueryCreator<ParametrizedQuery>
* @param isSliceQuery flag denoting if the query returns a {@link org.springframework.data.domain.Slice}.
* @param returnedType the {@link ReturnedType} to be returned by the query. Must not be {@literal null}.
* @deprecated use
* {@link JdbcQueryCreator#JdbcQueryCreator(RelationalMappingContext, PartTree, JdbcConverter, Dialect, RelationalEntityMetadata, RelationalParameterAccessor, boolean, ReturnedType, Optional, SqlGeneratorSource)}
* {@link JdbcQueryCreator#JdbcQueryCreator(RelationalMappingContext, PartTree, JdbcConverter, Dialect, RelationalEntityMetadata, RelationalParameterAccessor, boolean, ReturnedType, Optional, SqlGeneratorSource, boolean)}
* instead.
*/
@Deprecated(since = "4.0", forRemoval = true)
JdbcQueryCreator(RelationalMappingContext context, PartTree tree, JdbcConverter converter, Dialect dialect,
RelationalEntityMetadata<?> entityMetadata, RelationalParameterAccessor accessor, boolean isSliceQuery,
ReturnedType returnedType, Optional<Lock> lockMode) {
ReturnedType returnedType, Optional<Lock> lockMode, boolean isScrollQuery) {
this(context, tree, converter, dialect, entityMetadata, accessor, isSliceQuery, returnedType, lockMode,
new SqlGeneratorSource(context, converter, dialect));
new SqlGeneratorSource(context, converter, dialect), isScrollQuery);
}

/**
Expand All @@ -99,7 +100,7 @@ public JdbcQueryCreator(PartTree tree, JdbcConverter converter, Dialect dialect,
RelationalParameterAccessor accessor, ReturnedType returnedType) {
this(converter.getMappingContext(), tree, converter, dialect, queryMethod.getEntityInformation(), accessor,
queryMethod.isSliceQuery(), returnedType, queryMethod.lookupLockAnnotation(),
new SqlGeneratorSource(converter, dialect));
new SqlGeneratorSource(converter, dialect), queryMethod.isScrollQuery());
}

/**
Expand All @@ -117,11 +118,13 @@ public JdbcQueryCreator(PartTree tree, JdbcConverter converter, Dialect dialect,
* @param lockMode lock mode to be used for the query.
* @param sqlGeneratorSource the source providing SqlGenerator instances for generating SQL. Must not be
* {@literal null}
* @param isScrollQuery flag denoting if the query returns a {@link org.springframework.data.domain.Window}.
* @since 4.0
*/
public JdbcQueryCreator(RelationalMappingContext context, PartTree tree, JdbcConverter converter, Dialect dialect,
RelationalEntityMetadata<?> entityMetadata, RelationalParameterAccessor accessor, boolean isSliceQuery,
ReturnedType returnedType, Optional<Lock> lockMode, SqlGeneratorSource sqlGeneratorSource) {
ReturnedType returnedType, Optional<Lock> lockMode, SqlGeneratorSource sqlGeneratorSource,
boolean isScrollQuery) {
super(tree, accessor);

Assert.notNull(converter, "JdbcConverter must not be null");
Expand All @@ -139,6 +142,7 @@ public JdbcQueryCreator(RelationalMappingContext context, PartTree tree, JdbcCon
this.returnedType = returnedType;
this.lockMode = lockMode;
this.statementFactory = new StatementFactory(converter, dialect);
this.isScrollQuery = isScrollQuery;
}

StatementFactory getStatementFactory() {
Expand Down Expand Up @@ -203,7 +207,7 @@ protected ParametrizedQuery complete(@Nullable Criteria criteria, Sort sort) {

StatementFactory.SelectionBuilder selection = getSelection(entity);

selection.page(accessor.getPageable()).filter(criteria).orderBy(sort);
selection.page(accessor.getPageable()).filter(criteria).orderBy(sort).scrollPosition(accessor.getScrollPosition());

if (this.lockMode.isPresent()) {
selection.lock(this.lockMode.get().value());
Expand All @@ -225,6 +229,8 @@ StatementFactory.SelectionBuilder getSelection(RelationalPersistentEntity<?> ent

if (isSliceQuery) {
selection = statementFactory.slice(entity);
} else if (isScrollQuery) {
selection = statementFactory.scroll(entity);
} else {
selection = statementFactory.select(entity);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,23 @@
import java.util.function.LongSupplier;
import java.util.function.Supplier;

import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.domain.Limit;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.ScrollPosition;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.SliceImpl;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Window;
import org.springframework.data.jdbc.core.JdbcAggregateOperations;
import org.springframework.data.jdbc.core.convert.JdbcConverter;
import org.springframework.data.jdbc.repository.support.ScrollDelegate;
import org.springframework.data.relational.core.conversion.RelationalConverter;
import org.springframework.data.relational.core.dialect.Dialect;
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
import org.springframework.data.relational.repository.query.RelationalEntityMetadata;
import org.springframework.data.relational.repository.query.RelationalParameterAccessor;
import org.springframework.data.relational.repository.query.RelationalParametersParameterAccessor;
Expand All @@ -61,6 +67,7 @@
* @author Mikhail Polivakha
* @author Yunyoung LEE
* @author Nikita Konev
* @author Artemij Degtyarev
* @since 2.0
*/
public class PartTreeJdbcQuery extends AbstractJdbcQuery {
Expand Down Expand Up @@ -157,7 +164,7 @@ private Sort getDynamicSort(RelationalParameterAccessor accessor) {

@Override
@Nullable
public Object execute(Object[] values) {
public Object execute(@Nullable Object[] values) {

RelationalParametersParameterAccessor accessor = new RelationalParametersParameterAccessor(getQueryMethod(),
values);
Expand Down Expand Up @@ -191,21 +198,29 @@ private JdbcQueryExecution<?> getQueryExecution(ResultProcessor processor,

JdbcQueryExecution<?> queryExecution = getJdbcQueryExecution(extractor, rowMapper);

if (getQueryMethod().isScrollQuery()) {
// noinspection unchecked
return new ScrollQueryExecution<>((JdbcQueryExecution<@NonNull Collection<Object>>) queryExecution,
accessor.getScrollPosition(), tree.getSort(), tree.getResultLimit(),
getQueryMethod().getEntityInformation().getTableEntity());
}

if (getQueryMethod().isSliceQuery()) {
// noinspection unchecked
return new SliceQueryExecution<>((JdbcQueryExecution<Collection<Object>>) queryExecution, accessor.getPageable());
return new SliceQueryExecution<>((JdbcQueryExecution<@NonNull Collection<Object>>) queryExecution, accessor.getPageable());
}

if (getQueryMethod().isPageQuery()) {

// noinspection unchecked
return new PageQueryExecution<>((JdbcQueryExecution<Collection<Object>>) queryExecution, accessor.getPageable(),
return new PageQueryExecution<>((JdbcQueryExecution<@NonNull Collection<Object>>) queryExecution, accessor.getPageable(),
() -> {

RelationalEntityMetadata<?> entityMetadata = getQueryMethod().getEntityInformation();

JdbcCountQueryCreator queryCreator = new JdbcCountQueryCreator(context, tree, converter, dialect,
entityMetadata, accessor, false, processor.getReturnedType(), getQueryMethod().lookupLockAnnotation());
entityMetadata, accessor, false, processor.getReturnedType(), getQueryMethod().lookupLockAnnotation(),
false);

ParametrizedQuery countQuery = queryCreator.createQuery(Sort.unsorted());
Object count = singleObjectQuery(new SingleColumnRowMapper<>(Number.class)).execute(countQuery.getQuery(),
Expand All @@ -223,11 +238,8 @@ private JdbcQueryExecution<?> getQueryExecution(ResultProcessor processor,
}

ParametrizedQuery createQuery(RelationalParametersParameterAccessor accessor, ReturnedType returnedType) {
JdbcQueryCreator queryCreator = new JdbcQueryCreator(tree, converter, dialect, getQueryMethod(), accessor, returnedType);

RelationalEntityMetadata<?> entityMetadata = getQueryMethod().getEntityInformation();

JdbcQueryCreator queryCreator = new JdbcQueryCreator(context, tree, converter, dialect, entityMetadata, accessor,
getQueryMethod().isSliceQuery(), returnedType, this.getQueryMethod().lookupLockAnnotation());
return queryCreator.createQuery(getDynamicSort(accessor));
}

Expand All @@ -243,7 +255,7 @@ private List<ParametrizedQuery> createDeleteQueries(RelationalParametersParamete
private JdbcQueryExecution<?> getJdbcQueryExecution(@Nullable ResultSetExtractor<Boolean> extractor,
Supplier<RowMapper<?>> rowMapper) {

if (getQueryMethod().isPageQuery() || getQueryMethod().isSliceQuery()) {
if (getQueryMethod().isPageQuery() || getQueryMethod().isSliceQuery() || getQueryMethod().isScrollQuery()) {
return collectionQuery(rowMapper.get());
} else {

Expand All @@ -255,6 +267,35 @@ private JdbcQueryExecution<?> getJdbcQueryExecution(@Nullable ResultSetExtractor
}
}

/**
* {@link JdbcQueryExecution} returning a {@link org.springframework.data.domain.Window}
*
* @param <T>
*/
static class ScrollQueryExecution<T> implements JdbcQueryExecution<Window<T>> {
private final JdbcQueryExecution<? extends Collection<T>> delegate;
private final @Nullable ScrollPosition position;
private final Sort sort;
private final Limit limit;
private final RelationalPersistentEntity<?> tableEntity;

ScrollQueryExecution(JdbcQueryExecution<? extends Collection<T>> delegate, @Nullable ScrollPosition position,
Sort sort, Limit limit, RelationalPersistentEntity<?> tableEntity) {
this.delegate = delegate;
this.position = position;
this.sort = sort;
this.limit = limit;
this.tableEntity = tableEntity;
}

@Override
public @Nullable Window<T> execute(String query, SqlParameterSource parameter) {
Collection<T> result = delegate.execute(query, parameter);

return ScrollDelegate.scroll(result, position, limit, sort, tableEntity);
}
}

/**
* {@link JdbcQueryExecution} returning a {@link org.springframework.data.domain.Slice}.
*
Expand Down Expand Up @@ -327,8 +368,7 @@ class CachedRowMapperFactory implements Supplier<RowMapper<?>> {
private final Lazy<RowMapper<?>> rowMapper;
private final Function<ResultProcessor, RowMapper<?>> rowMapperFunction;

public CachedRowMapperFactory(PartTree tree,
RowMapperFactory rowMapperFactory, RelationalConverter converter,
public CachedRowMapperFactory(PartTree tree, RowMapperFactory rowMapperFactory, RelationalConverter converter,
ResultProcessor defaultResultProcessor) {

this.rowMapperFunction = processor -> {
Expand All @@ -338,8 +378,8 @@ public CachedRowMapperFactory(PartTree tree,
}
Converter<Object, Object> resultProcessingConverter = new ResultProcessingConverter(processor,
converter.getMappingContext(), converter.getEntityInstantiators());
return new ConvertingRowMapper(
rowMapperFactory.create(processor.getReturnedType().getDomainType()), resultProcessingConverter);
return new ConvertingRowMapper(rowMapperFactory.create(processor.getReturnedType().getDomainType()),
resultProcessingConverter);
};

this.rowMapper = Lazy.of(() -> this.rowMapperFunction.apply(defaultResultProcessor));
Expand Down
Loading