diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index d90e1bdf..3b16a233 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -63,6 +63,31 @@ jobs:
# path: "**/jacoco-unit.exec"
# retention-days: 1
+ tests-spring-data-41:
+ runs-on: ubuntu-22.04
+ timeout-minutes: 40
+ steps:
+ - uses: actions/checkout@v6
+
+ - name: Set up JDK 17
+ uses: actions/setup-java@v5
+ with:
+ distribution: 'temurin'
+ java-version: '17'
+ cache: 'maven'
+
+ # the reactor installs testcontainers-autogen before the testcontainers module
+ # loads it as a jsonschema2pojo plugin dependency
+ - name: Build dependencies
+ run: >
+ ./mvnw -B -pl tarantool-spring-data/tarantool-spring-data-4 -am install -DskipTests
+ -Dspring.boot.version=4.1.2 -Dspring-data-keyvalue.version=4.1.2
+
+ - name: Run Spring Data tests against Spring Boot 4.1.x
+ run: >
+ ./mvnw -B -pl tarantool-spring-data/tarantool-spring-data-4 test
+ -Dspring.boot.version=4.1.2 -Dspring-data-keyvalue.version=4.1.2
+
tests-box-integration:
runs-on: ubuntu-22.04
strategy:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 716d7705..7c872229 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,16 @@
exit code, stdout and stderr are logged and included in the error. Before, the error carried
only the empty stdout ("Failed to change the app topology via cartridge CLI: ").
+### Spring Data
+
+- **Breaking:** only Spring Boot 4.x is supported. The `tarantool-spring-data-27`,
+ `tarantool-spring-data-31`, `-32`, `-33`, `-34` and `-35` modules are removed.
+ `tarantool-spring-data-40` is renamed to `tarantool-spring-data-4`, now the single artifact.
+- **Breaking:** packages are renamed from `io.tarantool.spring.data40.*` to
+ `io.tarantool.spring4.data.*`. Update imports after upgrading.
+- `tarantool-spring-data-4` is built against Spring Boot 4.0.x and unit-tested with 4.0.x and 4.1.x.
+- Users staying on Spring Boot 2.7.x or 3.x should keep using tarantool-spring-data 1.7.x.
+
## [1.7.3] - 2026-10-30
### Pool
diff --git a/CONTRIBUTE.md b/CONTRIBUTE.md
index 9956fe6b..bf779433 100644
--- a/CONTRIBUTE.md
+++ b/CONTRIBUTE.md
@@ -79,10 +79,8 @@ tarantool-java-sdk (parent POM)
├── tarantool-balancer
├── tarantool-schema
├── tarantool-spring-data
- ├── tarantool-spring-data-core
- ├── tarantool-spring-data-27
- ├── ...
- ├── tarantool-spring-data-35
+ ├── tarantool-spring-data-core
+ └── tarantool-spring-data-4
├── testcontainers
└── jacoco-coverage-aggregate-report
```
diff --git a/documentation/doc-src/pages/spring-data/configuration.en.md b/documentation/doc-src/pages/spring-data/configuration.en.md
index c982dec8..f8ec616c 100644
--- a/documentation/doc-src/pages/spring-data/configuration.en.md
+++ b/documentation/doc-src/pages/spring-data/configuration.en.md
@@ -20,7 +20,7 @@ necessary settings:
```java
import io.tarantool.client.factory.TarantoolCrudClientBuilder;
import io.tarantool.client.factory.TarantoolFactory;
-import io.tarantool.spring.data.repository.config.EnableTarantoolRepositories;
+import io.tarantool.spring4.data.repository.config.EnableTarantoolRepositories;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -53,7 +53,7 @@ To configure the client through a configuration file (for example, via
```java
- import io.tarantool.spring.data.repository.config.EnableTarantoolRepositories;
+ import io.tarantool.spring4.data.repository.config.EnableTarantoolRepositories;
import org.springframework.context.annotation.Configuration;
@Configuration
diff --git a/documentation/doc-src/pages/spring-data/configuration.md b/documentation/doc-src/pages/spring-data/configuration.md
index 8b9df428..b241b73d 100644
--- a/documentation/doc-src/pages/spring-data/configuration.md
+++ b/documentation/doc-src/pages/spring-data/configuration.md
@@ -20,7 +20,7 @@ title: Конфигурация клиентов
```java
import io.tarantool.client.factory.TarantoolCrudClientBuilder;
import io.tarantool.client.factory.TarantoolFactory;
-import io.tarantool.spring.data.repository.config.EnableTarantoolRepositories;
+import io.tarantool.spring4.data.repository.config.EnableTarantoolRepositories;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -53,7 +53,7 @@ public class Config {
```java
- import io.tarantool.spring.data.repository.config.EnableTarantoolRepositories;
+ import io.tarantool.spring4.data.repository.config.EnableTarantoolRepositories;
import org.springframework.context.annotation.Configuration;
@Configuration
diff --git a/documentation/doc-src/pages/spring-data/index.en.md b/documentation/doc-src/pages/spring-data/index.en.md
index 58206855..ee2c753e 100644
--- a/documentation/doc-src/pages/spring-data/index.en.md
+++ b/documentation/doc-src/pages/spring-data/index.en.md
@@ -28,20 +28,15 @@ using [Tarantool](https://www.tarantool.io) as a data store.
| 1.5.x | 1.5.x | 2.7.18 / 3.1.12 / 3.2.12 / 3.3.13 / 3.4.11 |
| 1.6.x | 1.6.x | 2.7.18 / 3.1.12 / 3.2.12 / 3.3.13 / 3.4.13 / 3.5.8 |
| 1.7.x | 1.7.x | 2.7.18 / 3.1.12 / 3.2.12 / 3.3.13 / 3.4.13 / 3.5.16 / 4.0.9 |
+| 2.0.x | 2.0.x | 4.0.x / 4.1.x |
-Choose the module by the Spring Boot minor line of your application. The table above lists the
-Spring Boot versions each module is built and tested with; other patch versions of the same line are
-not tested in CI, and newer minor lines are not tested at all.
+The `tarantool-spring-data-4` module supports Spring Boot 4.x. CI builds it against 4.0.x and
+runs unit tests with 4.0.x and 4.1.x. Its packages carry the Spring major version
+(`io.tarantool.spring4.data`), so future Spring Data majors can be supported alongside.
-| Spring Boot line | Module |
-|:----------------:|:---------------------------:|
-| 2.7.x | `tarantool-spring-data-27` |
-| 3.1.x | `tarantool-spring-data-31` |
-| 3.2.x | `tarantool-spring-data-32` |
-| 3.3.x | `tarantool-spring-data-33` |
-| 3.4.x | `tarantool-spring-data-34` |
-| 3.5.x | `tarantool-spring-data-35` |
-| 4.0.x | `tarantool-spring-data-40` |
+| Spring Boot line | Module |
+|:----------------:|:--------------------------:|
+| 4.0.x / 4.1.x | `tarantool-spring-data-4` |
### Tarantool Version and Supported Client Modules
@@ -119,7 +114,7 @@ Include the module in your project as follows:
io.tarantool
- tarantool-spring-data-40
+ tarantool-spring-data-4${tarantool-spring-data.version}
diff --git a/documentation/doc-src/pages/spring-data/index.md b/documentation/doc-src/pages/spring-data/index.md
index a05016d6..64119ced 100644
--- a/documentation/doc-src/pages/spring-data/index.md
+++ b/documentation/doc-src/pages/spring-data/index.md
@@ -28,20 +28,16 @@ hide:
| 1.5.x | 1.5.x | 2.7.18 / 3.1.12 / 3.2.12 / 3.3.13 / 3.4.11 |
| 1.6.x | 1.6.x | 2.7.18 / 3.1.12 / 3.2.12 / 3.3.13 / 3.4.13 / 3.5.8 |
| 1.7.x | 1.7.x | 2.7.18 / 3.1.12 / 3.2.12 / 3.3.13 / 3.4.13 / 3.5.16 / 4.0.9 |
+| 2.0.x | 2.0.x | 4.0.x / 4.1.x |
-Модуль выбирается по минорной линии Spring Boot приложения. В таблице выше — версии Spring Boot, с
-которыми модули собраны и протестированы; другие патч-версии той же линии в CI не проверяются, более
-новые минорные линии не проверяются вовсе.
+Модуль `tarantool-spring-data-4` поддерживает Spring Boot 4.x. В CI он собирается против 4.0.x и
+прогоняет unit-тесты с 4.0.x и 4.1.x. Пакеты содержат мажорную версию Spring
+(`io.tarantool.spring4.data`), поэтому будущие мажорные версии Spring Data можно поддерживать
+параллельно.
| Линия Spring Boot | Модуль |
|:-----------------:|:---------------------------:|
-| 2.7.x | `tarantool-spring-data-27` |
-| 3.1.x | `tarantool-spring-data-31` |
-| 3.2.x | `tarantool-spring-data-32` |
-| 3.3.x | `tarantool-spring-data-33` |
-| 3.4.x | `tarantool-spring-data-34` |
-| 3.5.x | `tarantool-spring-data-35` |
-| 4.0.x | `tarantool-spring-data-40` |
+| 4.0.x / 4.1.x | `tarantool-spring-data-4` |
### Версия Tarantool и поддерживаемые модули-клиенты
@@ -119,7 +115,7 @@ Tarantool можно найти
io.tarantool
- tarantool-spring-data-40
+ tarantool-spring-data-4${tarantool-spring-data.version}
diff --git a/tarantool-java-sdk-bom/pom.xml b/tarantool-java-sdk-bom/pom.xml
index 171f1827..4bd7e1db 100644
--- a/tarantool-java-sdk-bom/pom.xml
+++ b/tarantool-java-sdk-bom/pom.xml
@@ -117,6 +117,11 @@
tarantool-spring-data-core${project.version}
+
+ io.tarantool
+ tarantool-spring-data-4
+ ${project.version}
+ io.tarantooltestcontainers
diff --git a/tarantool-spring-data/README.md b/tarantool-spring-data/README.md
index 50842bf3..68895a78 100644
--- a/tarantool-spring-data/README.md
+++ b/tarantool-spring-data/README.md
@@ -30,20 +30,13 @@ data storage.
| 1.5.x | 1.5.x | 2.7.18 / 3.1.12 / 3.2.12 / 3.3.13 / 3.4.11 |
| 1.6.x | 1.6.x | 2.7.18 / 3.1.12 / 3.2.12 / 3.3.13 / 3.4.13 / 3.5.8 |
| 1.7.x | 1.7.x | 2.7.18 / 3.1.12 / 3.2.12 / 3.3.13 / 3.4.13 / 3.5.16 / 4.0.9 |
+| 2.0.x | 2.0.x | 4.0.x / 4.1.x |
-Choose the module by the Spring Boot minor line of your application. The table above lists the
-Spring Boot versions each module is built and tested with; other patch versions of the same line are
-not tested in CI, and newer minor lines are not tested at all.
+The `tarantool-spring-data-4` module supports Spring Boot 4.x.
-| Spring Boot line | Module |
-|:----------------:|:---------------------------:|
-| 2.7.x | `tarantool-spring-data-27` |
-| 3.1.x | `tarantool-spring-data-31` |
-| 3.2.x | `tarantool-spring-data-32` |
-| 3.3.x | `tarantool-spring-data-33` |
-| 3.4.x | `tarantool-spring-data-34` |
-| 3.5.x | `tarantool-spring-data-35` |
-| 4.0.x | `tarantool-spring-data-40` |
+| Spring Boot line | Module |
+|:----------------:|:--------------------------:|
+| 4.0.x / 4.1.x | `tarantool-spring-data-4` |
### Tarantool Version and Supported Client Modules
@@ -96,11 +89,12 @@ CRUD operations of the
> which are not available in TDG. Using a `Repository` with a TDG connection fails with
> `BoxError{code=33, message='Procedure 'crud.select' is not defined'}`.
-> [!IMPORTANT]
-> #### Spring Data 3.4.x
-> Verified operation of
-> [repository fragments SPI](https://github.com/spring-projects/spring-data-commons/wiki/Spring-Data-2024.1-Release-Notes#repository-fragments-spi).
-> Additional information [here](https://github.com/spring-projects/spring-data-commons/pull/3093).
+> [!IMPORTANT]
+> #### Repository fragments
+> The
+> [repository fragments SPI](https://github.com/spring-projects/spring-data-commons/wiki/Spring-Data-2024.1-Release-Notes#repository-fragments-spi)
+> is supported. Additional information
+> [here](https://github.com/spring-projects/spring-data-commons/pull/3093).
## Getting Started with Spring Data Tarantool
diff --git a/tarantool-spring-data/pom.xml b/tarantool-spring-data/pom.xml
index e7aee152..f76a19ba 100644
--- a/tarantool-spring-data/pom.xml
+++ b/tarantool-spring-data/pom.xml
@@ -18,13 +18,7 @@
tarantool-spring-data-core
- tarantool-spring-data-27
- tarantool-spring-data-31
- tarantool-spring-data-32
- tarantool-spring-data-33
- tarantool-spring-data-34
- tarantool-spring-data-35
- tarantool-spring-data-40
+ tarantool-spring-data-4
@@ -32,8 +26,10 @@
2.0.201.5.325.14.4
-
- 2.7.18
+
+ 4.0.9
+ 4.0.8${project.parent.basedir}/LICENSE_HEADER.txt
@@ -74,7 +70,7 @@
org.springframework.dataspring-data-keyvalue
- ${spring.boot.version}
+ ${spring-data-keyvalue.version}
diff --git a/tarantool-spring-data/tarantool-spring-data-27/pom.xml b/tarantool-spring-data/tarantool-spring-data-27/pom.xml
deleted file mode 100644
index 2f4dfd8b..00000000
--- a/tarantool-spring-data/tarantool-spring-data-27/pom.xml
+++ /dev/null
@@ -1,55 +0,0 @@
-
-
- 4.0.0
-
- tarantool-spring-data-27
- Minimalistic java connector for Tarantool versions 2.11+ based on Netty framework
- https://tarantool.io
-
-
- io.tarantool
- tarantool-spring-data
- 2.0.0-SNAPSHOT
-
-
- tarantool-spring-data-27
- 2.0.0-SNAPSHOT
- jar
-
-
- ${project.parent.parent.basedir}/tarantool-shared-resources/
- ${project.parent.parent.basedir}/LICENSE_HEADER.txt
- 2.7.18
-
- 1.2.13
-
- 1.7.36
-
-
-
-
-
- org.slf4j
- slf4j-api
- ${slf4j.api.version}
-
-
- ch.qos.logback
- logback-classic
- ${logback.version}
- test
-
-
- io.tarantool
- tarantool-spring-data-core
-
-
-
-
- com.fasterxml.jackson.dataformat
- jackson-dataformat-yaml
- 2.13.5
- test
-
-
-
diff --git a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/TarantoolBoxKeyValueAdapter.java b/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/TarantoolBoxKeyValueAdapter.java
deleted file mode 100644
index a4814582..00000000
--- a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/TarantoolBoxKeyValueAdapter.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2026 VK DIGITAL TECHNOLOGIES LIMITED LIABILITY COMPANY
- * All Rights Reserved.
- */
-
-package io.tarantool.spring.data27;
-
-import java.util.Map;
-
-import org.springframework.data.keyvalue.core.AbstractKeyValueAdapter;
-import org.springframework.data.util.CloseableIterator;
-import org.springframework.lang.NonNull;
-
-import io.tarantool.client.box.TarantoolBoxClient;
-import io.tarantool.spring.data.ProxyTarantoolBoxKeyValueAdapter;
-
-public class TarantoolBoxKeyValueAdapter extends AbstractKeyValueAdapter {
-
- private final ProxyTarantoolBoxKeyValueAdapter adapter;
-
- public TarantoolBoxKeyValueAdapter(@NonNull TarantoolBoxClient tarantoolBoxClient) {
- adapter = new ProxyTarantoolBoxKeyValueAdapter(tarantoolBoxClient);
- }
-
- @Override
- public Object put(Object id, Object item, String keyspace) {
- return adapter.put(id, item, keyspace);
- }
-
- @Override
- public boolean contains(Object id, String keyspace) {
- return adapter.contains(id, keyspace);
- }
-
- @Override
- public Object get(Object id, String keyspace) {
- return adapter.get(id, keyspace);
- }
-
- @Override
- public Object delete(Object id, String keyspace) {
- return adapter.delete(id, keyspace);
- }
-
- @Override
- public Iterable> getAllOf(String keyspace) {
- return adapter.getAllOf(keyspace);
- }
-
- @Override
- public void deleteAllOf(String keyspace) {
- adapter.deleteAllOf(keyspace);
- }
-
- @Override
- public void clear() {
- adapter.clear();
- }
-
- @Override
- public long count(String keyspace) {
- return adapter.count(keyspace);
- }
-
- @Override
- public void destroy() throws Exception {
- adapter.destroy();
- }
-
- @Override
- public CloseableIterator> entries(String keyspace) {
- throw new UnsupportedOperationException("Not implemented yet");
- }
-}
diff --git a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/TarantoolCrudKeyValueAdapter.java b/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/TarantoolCrudKeyValueAdapter.java
deleted file mode 100644
index 827cba40..00000000
--- a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/TarantoolCrudKeyValueAdapter.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (c) 2026 VK DIGITAL TECHNOLOGIES LIMITED LIABILITY COMPANY
- * All Rights Reserved.
- */
-
-package io.tarantool.spring.data27;
-
-import java.util.Collections;
-import java.util.Map.Entry;
-
-import com.fasterxml.jackson.annotation.JsonFormat;
-import org.springframework.core.annotation.AnnotatedElementUtils;
-import org.springframework.data.keyvalue.core.AbstractKeyValueAdapter;
-import org.springframework.data.util.CloseableIterator;
-import org.springframework.lang.NonNull;
-
-import io.tarantool.client.crud.TarantoolCrudClient;
-import io.tarantool.spring.data.ProxyTarantoolCrudKeyValueAdapter;
-import io.tarantool.spring.data.mapping.model.CompositeKey;
-
-public class TarantoolCrudKeyValueAdapter extends AbstractKeyValueAdapter {
-
- private final ProxyTarantoolCrudKeyValueAdapter adapter;
-
- public TarantoolCrudKeyValueAdapter(@NonNull TarantoolCrudClient client) {
- super(new TarantoolQueryEngine(client));
- this.adapter = new ProxyTarantoolCrudKeyValueAdapter(client);
- }
-
- @Override
- public Object put(Object id, Object item, String keyspace) {
- return adapter.put(convertId(id), item, keyspace);
- }
-
- @Override
- public boolean contains(Object id, String keyspace) {
- return adapter.contains(convertId(id), keyspace);
- }
-
- @Override
- public Object get(Object id, String keyspace) {
- return adapter.get(convertId(id), keyspace);
- }
-
- @Override
- public T get(Object id, String keyspace, Class type) {
- return adapter.get(convertId(id), keyspace, type);
- }
-
- @Override
- public Object delete(Object id, String keyspace) {
- return adapter.delete(convertId(id), keyspace);
- }
-
- @Override
- public T delete(Object id, String keyspace, Class type) {
- return adapter.delete(convertId(id), keyspace, type);
- }
-
- @Override
- public Iterable> getAllOf(String keyspace) {
- return adapter.getAllOf(keyspace);
- }
-
- @Override
- public void deleteAllOf(String keyspace) {
- adapter.deleteAllOf(keyspace);
- }
-
- @Override
- public void clear() {
- adapter.clear();
- }
-
- @Override
- public void destroy() throws Exception {
- adapter.destroy();
- }
-
- @Override
- public long count(String keyspace) {
- return adapter.count(keyspace);
- }
-
- @Override
- public CloseableIterator> entries(String keyspace) {
- throw new UnsupportedOperationException("Not implemented yet");
- }
-
- /**
- * Convert the identifier to the form required by the tarantool-java-sdk driver.
- *
- * @param id identifier object
- * @return identifier in the required form
- */
- private Object convertId(Object id) {
- if (id instanceof CompositeKey || hasJsonFormatArrayAnnotation(id)) {
- return id;
- }
- return Collections.singletonList(id);
- }
-
- /**
- * Determine whether the identifier type is annotated with the {@link JsonFormat} annotation.
- *
- * @param id identifier object
- * @return return true if the annotation is present, false otherwise
- */
- private boolean hasJsonFormatArrayAnnotation(Object id) {
- final JsonFormat jsonFormatAnnotation =
- AnnotatedElementUtils.findMergedAnnotation(id.getClass(), JsonFormat.class);
-
- return jsonFormatAnnotation != null
- && JsonFormat.Shape.ARRAY.equals(jsonFormatAnnotation.shape());
- }
-}
diff --git a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/TarantoolQueryEngine.java b/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/TarantoolQueryEngine.java
deleted file mode 100644
index 7f68bce3..00000000
--- a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/TarantoolQueryEngine.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2026 VK DIGITAL TECHNOLOGIES LIMITED LIABILITY COMPANY
- * All Rights Reserved.
- */
-
-package io.tarantool.spring.data27;
-
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.Map.Entry;
-
-import org.springframework.data.keyvalue.core.QueryEngine;
-import org.springframework.lang.NonNull;
-import org.springframework.lang.Nullable;
-
-import io.tarantool.client.crud.TarantoolCrudClient;
-import io.tarantool.spring.data.ProxyTarantoolQueryEngine;
-import io.tarantool.spring.data.query.TarantoolCriteria;
-import io.tarantool.spring.data27.query.TarantoolCriteriaAccessor;
-import io.tarantool.spring.data27.query.TarantoolSortAccessor;
-
-/**
- * Implementation of {@code findBy*()} and {@code countBy*{}} queries.
- *
- * @author Artyom Dubinin
- */
-public class TarantoolQueryEngine
- extends QueryEngine>> {
-
- private final ProxyTarantoolQueryEngine engine;
-
- public TarantoolQueryEngine(TarantoolCrudClient client) {
- super(new TarantoolCriteriaAccessor(), new TarantoolSortAccessor());
- this.engine = new ProxyTarantoolQueryEngine(client);
- }
-
- @Override
- @NonNull
- public Collection> execute(
- @Nullable final TarantoolCriteria criteria,
- @Nullable final Comparator> sort,
- final long offset,
- final int rows,
- @NonNull final String keyspace) {
- return engine.execute(criteria, sort, offset, rows, keyspace);
- }
-
- /**
- * Construct the final query predicate for Tarantool to execute, from the base query plus any
- * paging and sorting.
- *
- *
Variations here allow the base query predicate to be omitted, sorting to be omitted, and
- * paging to be omitted.
- *
- * @param criteria Search criteria, null means match everything
- * @param sort Possibly null collation
- * @param offset Start point of returned page, -1 if not used
- * @param rows Size of page, -1 if not used
- * @param keyspace The map name
- * @return Results from Tarantool
- */
- @Override
- @NonNull
- public Collection execute(
- @Nullable final TarantoolCriteria criteria,
- @Nullable final Comparator> sort,
- final long offset,
- final int rows,
- @NonNull final String keyspace,
- @NonNull Class type) {
- return engine.execute(criteria, sort, offset, rows, keyspace, type);
- }
-
- /**
- * Execute {@code countBy*()} queries against a Tarantool space.
- *
- * @param criteria Predicate to use, not null
- * @param keyspace The map name
- * @return Results from Tarantool
- */
- @Override
- public long count(@Nullable final TarantoolCriteria criteria, @NonNull final String keyspace) {
- return engine.count(criteria, keyspace);
- }
-}
diff --git a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/config/TarantoolCrudConfiguration.java b/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/config/TarantoolCrudConfiguration.java
deleted file mode 100644
index b285c0fa..00000000
--- a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/config/TarantoolCrudConfiguration.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2026 VK DIGITAL TECHNOLOGIES LIMITED LIABILITY COMPANY
- * All Rights Reserved.
- */
-
-package io.tarantool.spring.data27.config;
-
-import org.springframework.beans.factory.ObjectProvider;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-import static io.tarantool.spring.data.TarantoolBeanNames.DEFAULT_TARANTOOL_CRUD_CLIENT_BEAN_REF;
-import static io.tarantool.spring.data.TarantoolBeanNames.DEFAULT_TARANTOOL_CRUD_KEY_VALUE_ADAPTER_REF;
-import io.tarantool.client.crud.TarantoolCrudClient;
-import io.tarantool.client.factory.TarantoolCrudClientBuilder;
-import io.tarantool.spring.data.config.BaseTarantoolCrudConfiguration;
-import io.tarantool.spring.data27.TarantoolCrudKeyValueAdapter;
-import io.tarantool.spring.data27.config.properties.TarantoolProperties;
-
-@Configuration(proxyBeanMethods = false)
-public class TarantoolCrudConfiguration extends BaseTarantoolCrudConfiguration {
-
- public TarantoolCrudConfiguration(
- ObjectProvider properties,
- ObjectProvider tarantoolClientConfiguration) {
- super(properties.getIfAvailable(), tarantoolClientConfiguration.getIfAvailable());
- }
-
- @Bean(name = DEFAULT_TARANTOOL_CRUD_KEY_VALUE_ADAPTER_REF)
- @ConditionalOnMissingBean(TarantoolCrudKeyValueAdapter.class)
- public TarantoolCrudKeyValueAdapter tarantoolCrudKeyValueAdapter(
- TarantoolCrudClient tarantoolCrudClient) {
- return new TarantoolCrudKeyValueAdapter(tarantoolCrudClient);
- }
-
- @Bean(name = DEFAULT_TARANTOOL_CRUD_CLIENT_BEAN_REF)
- @ConditionalOnMissingBean(TarantoolCrudClient.class)
- public TarantoolCrudClient tarantoolCrudClient() throws Exception {
- return super.tarantoolCrudClient();
- }
-
- public TarantoolCrudClientBuilder getClientBuilder() {
- return super.getClientBuilder();
- }
-}
diff --git a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/config/package-info.java b/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/config/package-info.java
deleted file mode 100644
index a3414471..00000000
--- a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/config/package-info.java
+++ /dev/null
@@ -1,3 +0,0 @@
-/** Config package. */
-@org.springframework.lang.NonNullApi
-package io.tarantool.spring.data27.config;
diff --git a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/TarantoolTemplate.java b/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/TarantoolTemplate.java
deleted file mode 100644
index 1e196048..00000000
--- a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/TarantoolTemplate.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2026 VK DIGITAL TECHNOLOGIES LIMITED LIABILITY COMPANY
- * All Rights Reserved.
- */
-
-package io.tarantool.spring.data27.core;
-
-import org.springframework.data.keyvalue.core.IdentifierGenerator;
-import org.springframework.data.keyvalue.core.KeyValueAdapter;
-import org.springframework.data.keyvalue.core.KeyValueTemplate;
-import org.springframework.data.keyvalue.core.mapping.KeyValuePersistentEntity;
-import org.springframework.data.keyvalue.core.mapping.KeyValuePersistentProperty;
-import org.springframework.data.mapping.IdentifierAccessor;
-import org.springframework.data.mapping.PersistentEntity;
-import org.springframework.data.mapping.context.MappingContext;
-import org.springframework.util.ClassUtils;
-
-import io.tarantool.spring.data27.core.annotation.DefaultIdClassResolver;
-import io.tarantool.spring.data27.core.mapping.TarantoolMappingContext;
-
-public class TarantoolTemplate extends KeyValueTemplate {
-
- public TarantoolTemplate(KeyValueAdapter adapter) {
- super(adapter, new TarantoolMappingContext<>());
- }
-
- public TarantoolTemplate(
- KeyValueAdapter adapter,
- MappingContext<
- ? extends KeyValuePersistentEntity, ?>, ? extends KeyValuePersistentProperty>>
- mappingContext) {
- super(adapter, mappingContext);
- }
-
- public TarantoolTemplate(
- KeyValueAdapter adapter,
- MappingContext<
- ? extends KeyValuePersistentEntity, ?>, ? extends KeyValuePersistentProperty>>
- mappingContext,
- IdentifierGenerator identifierGenerator) {
- super(adapter, mappingContext, identifierGenerator);
- }
-
- @Override
- public T insert(T objectToInsert) {
- if (DefaultIdClassResolver.INSTANCE.resolveIdClassType(objectToInsert.getClass()) == null) {
- return super.insert(objectToInsert);
- }
-
- PersistentEntity, ?> entity =
- getMappingContext().getRequiredPersistentEntity(ClassUtils.getUserClass(objectToInsert));
-
- IdentifierAccessor identifierAccessor = entity.getIdentifierAccessor(objectToInsert);
- Object id = identifierAccessor.getRequiredIdentifier();
- return insert(id, objectToInsert);
- }
-}
diff --git a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/annotation/DefaultIdClassResolver.java b/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/annotation/DefaultIdClassResolver.java
deleted file mode 100644
index 69aaf7d1..00000000
--- a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/annotation/DefaultIdClassResolver.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2026 VK DIGITAL TECHNOLOGIES LIMITED LIABILITY COMPANY
- * All Rights Reserved.
- */
-
-package io.tarantool.spring.data27.core.annotation;
-
-import org.springframework.core.annotation.AnnotatedElementUtils;
-import org.springframework.lang.Nullable;
-import org.springframework.util.Assert;
-
-import io.tarantool.spring.data.core.annotation.IdClass;
-import io.tarantool.spring.data.core.annotation.IdClassResolver;
-
-/** Default implementation of {@link IdClassResolver}. */
-public enum DefaultIdClassResolver implements IdClassResolver {
- INSTANCE;
-
- public static final String ANNOTATION_TYPE_EXCEPTION =
- "The class of a composite identifier specified in the @IdClass annotation cannot be"
- + " annotation!";
-
- @Nullable
- @Override
- public Class> resolveIdClassType(Class> type) {
- Assert.notNull(type, "Type for IdClass must be not null!");
-
- IdClass idClassTypeAnnotation = AnnotatedElementUtils.findMergedAnnotation(type, IdClass.class);
-
- if (idClassTypeAnnotation == null) {
- return null;
- }
-
- Class> idClassTypeValue = idClassTypeAnnotation.value();
- Assert.isTrue(!idClassTypeValue.isAnnotation(), ANNOTATION_TYPE_EXCEPTION);
-
- return idClassTypeValue;
- }
-}
diff --git a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/annotation/package-info.java b/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/annotation/package-info.java
deleted file mode 100644
index e49b1a90..00000000
--- a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/annotation/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/** Core annotations of data mapping. */
-@org.springframework.lang.NonNullFields
-@org.springframework.lang.NonNullApi
-package io.tarantool.spring.data27.core.annotation;
diff --git a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/mapping/BasicKeyValueCompositePersistentEntity.java b/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/mapping/BasicKeyValueCompositePersistentEntity.java
deleted file mode 100644
index 2e44c76b..00000000
--- a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/mapping/BasicKeyValueCompositePersistentEntity.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright (c) 2026 VK DIGITAL TECHNOLOGIES LIMITED LIABILITY COMPANY
- * All Rights Reserved.
- */
-
-package io.tarantool.spring.data27.core.mapping;
-
-import java.lang.reflect.Field;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.springframework.data.domain.Persistable;
-import org.springframework.data.keyvalue.core.mapping.BasicKeyValuePersistentEntity;
-import org.springframework.data.keyvalue.core.mapping.KeySpaceResolver;
-import org.springframework.data.mapping.IdentifierAccessor;
-import org.springframework.data.mapping.PersistentEntity;
-import org.springframework.data.support.IsNewStrategy;
-import org.springframework.data.util.TypeInformation;
-import org.springframework.lang.Nullable;
-import org.springframework.util.Assert;
-
-import io.tarantool.spring.data.core.annotation.IdClass;
-import io.tarantool.spring.data.mapping.model.CompositeKey;
-import io.tarantool.spring.data27.core.mapping.model.CompositeIdPropertyAccessor;
-import io.tarantool.spring.data27.core.mapping.model.PersistentCompositeIdIsNewStrategy;
-
-public class BasicKeyValueCompositePersistentEntity>
- extends BasicKeyValuePersistentEntity implements KeyValueCompositePersistentEntity {
-
- public static final String TYPE_MISMATCH =
- "Target bean of type %s is not of type of the persistent entity (%s)";
-
- private final Class> idClassTypeValue;
- private @Nullable P idProperty;
-
- private Map entityIdClassFields;
-
- /**
- * @param information must not be {@literal null}.
- * @param fallbackKeySpaceResolver can be {@literal null}.
- * @param idClassTypeValue class that specified in {@link IdClass}
- */
- public BasicKeyValueCompositePersistentEntity(
- TypeInformation information,
- @Nullable KeySpaceResolver fallbackKeySpaceResolver,
- Class> idClassTypeValue) {
- super(information, fallbackKeySpaceResolver);
-
- Assert.notNull(idClassTypeValue, "idClassTypeValue must be not null for this class!");
- this.idClassTypeValue = idClassTypeValue;
- }
-
- @Override
- public IdentifierAccessor getIdentifierAccessor(Object bean) {
- verifyBeanType(bean);
-
- if (Persistable.class.isAssignableFrom(getType())) {
- throw new IllegalArgumentException(
- "Persistable override is not currently supported for entities with a composite key.");
- }
-
- return hasIdProperty()
- ? new CompositeIdPropertyAccessor(bean, this.entityIdClassFields, getIdClassType())
- : new AbsentIdentifierAccessor();
- }
-
- @Override
- public Class> getIdClassType() {
- return this.idClassTypeValue;
- }
-
- @Override
- public void verify() {
- super.verify();
-
- if (this.idProperty != null) {
- this.entityIdClassFields = KeyPartTypeChecker.getFieldMapIfTypesValid(this, this.idProperty);
- }
- }
-
- @Override
- protected IsNewStrategy getFallbackIsNewStrategy() {
- return PersistentCompositeIdIsNewStrategy.of(this);
- }
-
- @Override
- protected P returnPropertyIfBetterIdPropertyCandidateOrNull(P property) {
- Assert.isInstanceOf(Identifier.class, property, "property must be Identifier for this class");
-
- if (!property.isIdProperty()) {
- return null;
- }
-
- if (this.idProperty == null) {
- this.idProperty = property;
- return this.idProperty;
- }
-
- this.idProperty.addPart(property);
-
- return this.idProperty;
- }
-
- /**
- * Verifies the given bean type to no be {@literal null} and of the type of the current {@link
- * PersistentEntity}.
- *
- * @param bean must not be {@literal null}.
- */
- private void verifyBeanType(Object bean) {
-
- Assert.notNull(bean, "Target bean must not be null");
- Assert.isInstanceOf(
- getType(),
- bean,
- () -> String.format(TYPE_MISMATCH, bean.getClass().getName(), getType().getName()));
- }
-
- /**
- * A null-object implementation of {@link IdentifierAccessor} to be able to return an accessor for
- * entities that do not have an identifier property.
- */
- private static class AbsentIdentifierAccessor implements IdentifierAccessor {
-
- /*
- * (non-Javadoc)
- * @see org.springframework.data.mapping.IdentifierAccessor#getIdentifier()
- */
- @Override
- @Nullable
- public Object getIdentifier() {
- return null;
- }
- }
-
- /**
- * A class that checks the types of fields of a composite key. In addition, the correspondence
- * between types and field names marked with {@code @Id}.
- */
- public static class KeyPartTypeChecker {
-
- public static final String COMPOSITE_KEY_FIELDS_NUMBER_EXCEPTION =
- "Number of fields specified in domain class and composite class the key is different!";
-
- public static final String COMPOSITE_KEY_FIELD_DIFFERENT_EXCEPTION =
- "Domain class fields marked with @Id differ from fields specified in the composite key"
- + " class";
-
- /**
- * Check the number and types of entity fields, annotated {@code @Id} and fields {@link
- * CompositeKey} and if the types and quantities match return the id part fields mapping.
- *
- * @param persistentEntity persistent entity
- * @param idProperty id property
- * @return mapping between fields of composite key class and fields annotated {@code @Id} in
- * entity.
- */
- public static Map getFieldMapIfTypesValid(
- KeyValueCompositePersistentEntity, ?> persistentEntity, Identifier> idProperty) {
- Map entityIdClassFields = new HashMap<>();
-
- List compositeKeyFields = persistentEntity.getIdClassTypeFields();
-
- Field[] entityFields = idProperty.getFields();
-
- if (compositeKeyFields.size() != entityFields.length) {
- throw new IllegalArgumentException(COMPOSITE_KEY_FIELDS_NUMBER_EXCEPTION);
- }
-
- for (int i = 0; i < compositeKeyFields.size(); i++) {
- Field compositeKeyField = compositeKeyFields.get(i);
- Field entityField = entityFields[i];
-
- if (!equalFields(compositeKeyField, entityField)) {
- throw new IllegalArgumentException(COMPOSITE_KEY_FIELD_DIFFERENT_EXCEPTION);
- }
-
- entityIdClassFields.put(entityField, compositeKeyField);
- }
- return entityIdClassFields;
- }
-
- /**
- * Compares two class fields by name and type.
- *
- * @param firstField first field
- * @param secondField second field
- * @return true if fields are equal
- */
- private static boolean equalFields(Field firstField, Field secondField) {
- return firstField.getName().equals(secondField.getName())
- && firstField.getType().equals(secondField.getType());
- }
- }
-}
diff --git a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/mapping/Identifier.java b/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/mapping/Identifier.java
deleted file mode 100644
index 96660102..00000000
--- a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/mapping/Identifier.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2026 VK DIGITAL TECHNOLOGIES LIMITED LIABILITY COMPANY
- * All Rights Reserved.
- */
-
-package io.tarantool.spring.data27.core.mapping;
-
-import java.lang.reflect.Field;
-import java.util.Collection;
-
-import org.springframework.data.mapping.PersistentProperty;
-
-/** The interface of the identifier class that will contain information about the composite key. */
-public interface Identifier
> {
-
- /**
- * Add a {@link PersistentProperty} tagged with {@code Id}. Don't add the current property.
- *
- * @param property {@link PersistentProperty} tagged {@code Id}
- */
- void addPart(P property);
-
- /**
- * Return the parts of a composite key that are {@link PersistentProperty}.
- *
- * @return parts of a composite key
- */
- Collection
getParts();
-
- /**
- * Return a list {@link Field} of fields that are annotated {@code @Id}. Unlike method {@link
- * #getParts()} this method returns an array {@link Field}, where {@link Field} is taken from each
- * element of the collection returned by the {@link #getParts()} method. Necessary in order not to
- * write polluting code.
- *
- * @return fields of a composite key
- */
- Field[] getFields();
-}
diff --git a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/mapping/KeyValueCompositePersistentEntity.java b/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/mapping/KeyValueCompositePersistentEntity.java
deleted file mode 100644
index d31d1ef9..00000000
--- a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/mapping/KeyValueCompositePersistentEntity.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2026 VK DIGITAL TECHNOLOGIES LIMITED LIABILITY COMPANY
- * All Rights Reserved.
- */
-
-package io.tarantool.spring.data27.core.mapping;
-
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.springframework.data.keyvalue.core.mapping.KeyValuePersistentProperty;
-import org.springframework.data.mapping.PersistentEntity;
-import org.springframework.data.mapping.PersistentProperty;
-import org.springframework.data.mapping.model.MutablePersistentEntity;
-
-import io.tarantool.spring.data.core.annotation.IdClass;
-
-/**
- * An interface to enable {@link PersistentEntity}-specific operations with a composite key.
- *
- * @param domain class type
- * @param
{@link PersistentProperty} type
- */
-public interface KeyValueCompositePersistentEntity>
- extends MutablePersistentEntity {
-
- /**
- * Returns the fields of the class specified in the {@link IdClass} annotation.
- *
- * @return all fields that are in composite key class
- */
- default List getIdClassTypeFields() {
- List fields = new ArrayList<>();
-
- for (Field field : getIdClassType().getDeclaredFields()) {
- if (!field.isSynthetic()) {
- fields.add(field);
- }
- }
- return fields;
- }
-
- /**
- * Returns the type of the class specified in the {@link IdClass} annotation.
- *
- * @return class that specified in {@link IdClass}
- */
- Class> getIdClassType();
-}
diff --git a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/mapping/KeyValueCompositeProperty.java b/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/mapping/KeyValueCompositeProperty.java
deleted file mode 100644
index 2e32d2d2..00000000
--- a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/mapping/KeyValueCompositeProperty.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2026 VK DIGITAL TECHNOLOGIES LIMITED LIABILITY COMPANY
- * All Rights Reserved.
- */
-
-package io.tarantool.spring.data27.core.mapping;
-
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Objects;
-
-import org.springframework.data.keyvalue.core.mapping.KeyValuePersistentProperty;
-import org.springframework.data.mapping.PersistentEntity;
-import org.springframework.data.mapping.model.Property;
-import org.springframework.data.mapping.model.SimpleTypeHolder;
-import org.springframework.util.Assert;
-
-public class KeyValueCompositeProperty
>
- extends KeyValuePersistentProperty
implements Identifier
{
-
- private final List
identifierPartsWithoutFirst;
-
- public KeyValueCompositeProperty(
- Property property, PersistentEntity, P> owner, SimpleTypeHolder simpleTypeHolder) {
- super(property, owner, simpleTypeHolder);
- this.identifierPartsWithoutFirst = new ArrayList<>();
- }
-
- @Override
- public void addPart(P property) {
- Assert.notNull(property, "property must be not null");
-
- if (equals(property) || this.identifierPartsWithoutFirst.contains(property)) {
- return;
- }
- this.identifierPartsWithoutFirst.add(property);
- }
-
- @Override
- @SuppressWarnings("unchecked")
- public Collection
getParts() {
- List
resultList = new ArrayList<>(this.identifierPartsWithoutFirst);
- resultList.add(0, (P) this);
-
- return resultList;
- }
-
- @Override
- public Field[] getFields() {
- int totalSize = this.identifierPartsWithoutFirst.size() + 1;
-
- final Field[] fields = new Field[totalSize];
- fields[0] = getField();
-
- for (int i = 1; i < totalSize; i++) {
- fields[i] = this.identifierPartsWithoutFirst.get(i - 1).getField();
- }
- return fields;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
- KeyValueCompositeProperty> other = (KeyValueCompositeProperty>) o;
-
- if (this.identifierPartsWithoutFirst.isEmpty() && other.identifierPartsWithoutFirst.isEmpty()) {
- return super.equals(o);
- }
-
- if (this.identifierPartsWithoutFirst.size() != other.identifierPartsWithoutFirst.size()
- || !other.getProperty().equals(getProperty())) {
- return false;
- }
-
- for (int i = 0; i < this.identifierPartsWithoutFirst.size(); i++) {
- // take Property from both parts
- Property thisKeyPartProperty =
- ((KeyValueCompositeProperty>) this.identifierPartsWithoutFirst.get(i)).getProperty();
- Property otherKeyPartProperty =
- ((KeyValueCompositeProperty>) other.identifierPartsWithoutFirst.get(i)).getProperty();
-
- if (!thisKeyPartProperty.equals(otherKeyPartProperty)) {
- return false;
- }
- }
- return true;
- }
-
- @Override
- public int hashCode() {
- int hashCode = super.hashCode();
-
- if (this.identifierPartsWithoutFirst.isEmpty()) {
- return hashCode;
- }
-
- // sublist to avoid endless recursion
- return Objects.hash(hashCode, this.identifierPartsWithoutFirst);
- }
-}
diff --git a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/mapping/TarantoolMappingContext.java b/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/mapping/TarantoolMappingContext.java
deleted file mode 100644
index e08a4e97..00000000
--- a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/mapping/TarantoolMappingContext.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2026 VK DIGITAL TECHNOLOGIES LIMITED LIABILITY COMPANY
- * All Rights Reserved.
- */
-
-package io.tarantool.spring.data27.core.mapping;
-
-import org.springframework.data.keyvalue.core.mapping.BasicKeyValuePersistentEntity;
-import org.springframework.data.keyvalue.core.mapping.KeySpaceResolver;
-import org.springframework.data.keyvalue.core.mapping.KeyValuePersistentEntity;
-import org.springframework.data.keyvalue.core.mapping.KeyValuePersistentProperty;
-import org.springframework.data.keyvalue.core.mapping.context.KeyValueMappingContext;
-import org.springframework.data.mapping.model.Property;
-import org.springframework.data.mapping.model.SimpleTypeHolder;
-import org.springframework.data.util.TypeInformation;
-import org.springframework.lang.Nullable;
-
-import io.tarantool.spring.data.core.annotation.IdClassResolver;
-import io.tarantool.spring.data27.core.annotation.DefaultIdClassResolver;
-
-public class TarantoolMappingContext<
- E extends KeyValuePersistentEntity, P>, P extends KeyValuePersistentProperty
>
- extends KeyValueMappingContext {
-
- private final IdClassResolver idClassResolver;
-
- private @Nullable KeySpaceResolver fallbackKeySpaceResolver;
-
- public TarantoolMappingContext() {
- super();
- this.idClassResolver = DefaultIdClassResolver.INSTANCE;
- }
-
- /**
- * Configures the {@link KeySpaceResolver} to be used if not explicit key space is annotated to
- * the domain type.
- *
- * @param fallbackKeySpaceResolver can be {@literal null}.
- */
- @Override
- public void setFallbackKeySpaceResolver(KeySpaceResolver fallbackKeySpaceResolver) {
- super.setFallbackKeySpaceResolver(fallbackKeySpaceResolver);
- this.fallbackKeySpaceResolver = fallbackKeySpaceResolver;
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public E createPersistentEntity(TypeInformation typeInformation) {
- final Class> idClassTypeValue =
- this.idClassResolver.resolveIdClassType(typeInformation.getType());
- if (idClassTypeValue == null) {
- return (E)
- new BasicKeyValuePersistentEntity(typeInformation, this.fallbackKeySpaceResolver);
- }
- return (E)
- new BasicKeyValueCompositePersistentEntity<>(
- typeInformation, this.fallbackKeySpaceResolver, idClassTypeValue);
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public P createPersistentProperty(Property property, E owner, SimpleTypeHolder simpleTypeHolder) {
- if (KeyValueCompositePersistentEntity.class.isAssignableFrom(owner.getClass())) {
- return (P) new KeyValueCompositeProperty<>(property, owner, simpleTypeHolder);
- }
- return (P) new KeyValuePersistentProperty<>(property, owner, simpleTypeHolder);
- }
-}
diff --git a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/mapping/model/CompositeIdPropertyAccessor.java b/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/mapping/model/CompositeIdPropertyAccessor.java
deleted file mode 100644
index af6cb4d7..00000000
--- a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/mapping/model/CompositeIdPropertyAccessor.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2026 VK DIGITAL TECHNOLOGIES LIMITED LIABILITY COMPANY
- * All Rights Reserved.
- */
-
-package io.tarantool.spring.data27.core.mapping.model;
-
-import java.lang.reflect.Field;
-import java.util.Map;
-
-import org.springframework.data.mapping.TargetAwareIdentifierAccessor;
-import org.springframework.lang.NonNull;
-import org.springframework.lang.Nullable;
-import org.springframework.util.Assert;
-import org.springframework.util.ReflectionUtils;
-
-import io.tarantool.spring.data.mapping.model.CompositeKey;
-
-/** Class that allows to convert {@code @Id} annotated fields in an entity into a composite key. */
-public class CompositeIdPropertyAccessor extends TargetAwareIdentifierAccessor {
-
- private final Map entityIdClassFields;
-
- private final Class> idClassType;
-
- private final Object target;
-
- public CompositeIdPropertyAccessor(
- Object target, @NonNull Map entityIdClassFields, Class> idClassType) {
-
- super(target);
- this.target = target;
- this.entityIdClassFields = entityIdClassFields;
- this.idClassType = idClassType;
- }
-
- @Nullable
- public Object getIdentifier() {
- try {
- return generateIdentifier();
- } catch (InstantiationException | IllegalAccessException e) {
- throw new RuntimeException(e);
- }
- }
-
- /**
- * Generates a composite identifier from those marked with the {@code @Id} annotation in a domain
- * class based on fields, specified in the composite key class.
- *
- * @return identifier
- * @throws IllegalAccessException if the class or its nullary constructor is not accessible.
- * @throws InstantiationException if this {@code Class} represents an abstract class, an
- * interface, an array class, a primitive type, or void; or if the class has no nullary
- * constructor; or if the instantiation fails for some other reason.
- */
- private Object generateIdentifier() throws InstantiationException, IllegalAccessException {
- Assert.notNull(this.target, "target object must be not null!");
- Object compositeKey = idClassType.newInstance();
- for (Map.Entry fieldPair : this.entityIdClassFields.entrySet()) {
- writeValuesFromEntityId(compositeKey, fieldPair.getKey(), fieldPair.getValue());
- }
- return compositeKey;
- }
-
- /**
- * Write the composite primary key fields provided in the entity to the class which implements
- * {@link CompositeKey}.
- *
- * @param compositeKey object of the composite key into which the values are written.
- * @param entityField field from the represented entity.
- * @param compositeKeyField field from the composite key class.
- */
- private void writeValuesFromEntityId(
- Object compositeKey, Field entityField, Field compositeKeyField) {
- ReflectionUtils.makeAccessible(entityField);
- ReflectionUtils.makeAccessible(compositeKeyField);
-
- Object value = ReflectionUtils.getField(entityField, this.target);
- ReflectionUtils.setField(compositeKeyField, compositeKey, value);
- }
-}
diff --git a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/mapping/model/PersistentCompositeIdIsNewStrategy.java b/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/mapping/model/PersistentCompositeIdIsNewStrategy.java
deleted file mode 100644
index b7fc8ec6..00000000
--- a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/mapping/model/PersistentCompositeIdIsNewStrategy.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2026 VK DIGITAL TECHNOLOGIES LIMITED LIABILITY COMPANY
- * All Rights Reserved.
- */
-
-package io.tarantool.spring.data27.core.mapping.model;
-
-import org.springframework.data.mapping.PersistentEntity;
-import org.springframework.data.support.IsNewStrategy;
-import org.springframework.util.Assert;
-
-/**
- * Strategy class for entity with composite key to determine whether a given entity is to be
- * considered new.
- */
-public class PersistentCompositeIdIsNewStrategy implements IsNewStrategy {
-
- /**
- * Create a new {@link PersistentCompositeIdIsNewStrategy} for the given entity.
- *
- * @param entity must not be {@literal null}.
- * @param idOnly check only id to determine
- */
- private PersistentCompositeIdIsNewStrategy(PersistentEntity, ?> entity, boolean idOnly) {
- // TODO сделать реализацию версионирования
- // TODO add idOnly support
- Assert.notNull(entity, "PersistentEntity must not be null");
- }
-
- /**
- * Create a new {@link PersistentCompositeIdIsNewStrategy} to only consider the identifier of the
- * given entity.
- *
- * @param entity must not be {@literal null}.
- * @return strategy to determine whether entity is new or not
- */
- public static PersistentCompositeIdIsNewStrategy forIdOnly(PersistentEntity, ?> entity) {
- return new PersistentCompositeIdIsNewStrategy(entity, true);
- }
-
- /**
- * Create a new {@link PersistentCompositeIdIsNewStrategy} to consider version properties before
- * falling back to the identifier.
- *
- * @param entity must not be {@literal null}.
- * @return strategy to determine whether entity is new or not
- */
- public static PersistentCompositeIdIsNewStrategy of(PersistentEntity, ?> entity) {
- return new PersistentCompositeIdIsNewStrategy(entity, false);
- }
-
- /**
- * Determine whether the current domain entity type object is new. Currently stub and always
- * returns false.
- *
- * @param entity must not be {@literal null}.
- * @return result of the question of entity is new or not
- */
- @Override
- public boolean isNew(Object entity) {
- return false;
- }
-}
diff --git a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/mapping/model/package-info.java b/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/mapping/model/package-info.java
deleted file mode 100644
index 8d4898d2..00000000
--- a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/mapping/model/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/** Core implementation of the mapping subsystem's model. */
-@org.springframework.lang.NonNullFields
-@org.springframework.lang.NonNullApi
-package io.tarantool.spring.data27.core.mapping.model;
diff --git a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/mapping/package-info.java b/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/mapping/package-info.java
deleted file mode 100644
index 1f1d7174..00000000
--- a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/mapping/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/** Base package for the mapping subsystem. */
-@org.springframework.lang.NonNullFields
-@org.springframework.lang.NonNullApi
-package io.tarantool.spring.data27.core.mapping;
diff --git a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/package-info.java b/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/package-info.java
deleted file mode 100644
index c6acdd7b..00000000
--- a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/core/package-info.java
+++ /dev/null
@@ -1,7 +0,0 @@
-/**
- * Core package for integrating Tarantool with Spring
- * concepts.
- */
-@org.springframework.lang.NonNullFields
-@org.springframework.lang.NonNullApi
-package io.tarantool.spring.data27.core;
diff --git a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/query/Field.java b/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/query/Field.java
deleted file mode 100644
index 5ab2a6b0..00000000
--- a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/query/Field.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2026 VK DIGITAL TECHNOLOGIES LIMITED LIABILITY COMPANY
- * All Rights Reserved.
- */
-
-package io.tarantool.spring.data27.query;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Inherited;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-import org.springframework.core.annotation.AliasFor;
-
-/**
- * Allows adding some metadata to the class fields relevant for storing them in the Tarantool space
- *
- * @author Artyom Dubinin
- */
-@Inherited
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
-public @interface Field {
-
- /**
- * The target Tarantool space field for storing the marked class field. Alias for {@link #name()}.
- *
- * @return the name of a field in space
- */
- @AliasFor("name")
- String value() default "";
-
- /**
- * The target Tarantool space field for storing the marked class field. Alias for {@link
- * #value()}.
- *
- * @return the name of a field in space
- */
- @AliasFor("value")
- String name() default "";
-
- /**
- * The order in which fields shall be stored in the tuple. Has to be a positive integer.
- *
- * @return the order the field shall have in the tuple or -1 if undefined.
- */
- int order() default -1;
-}
diff --git a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/query/PaginationUtils.java b/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/query/PaginationUtils.java
deleted file mode 100644
index fc37636d..00000000
--- a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/query/PaginationUtils.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (c) 2026 VK DIGITAL TECHNOLOGIES LIMITED LIABILITY COMPANY
- * All Rights Reserved.
- */
-
-package io.tarantool.spring.data27.query;
-
-import java.util.List;
-
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.Pageable;
-import org.springframework.data.keyvalue.core.IterableConverter;
-import org.springframework.data.keyvalue.core.KeyValueOperations;
-import org.springframework.data.keyvalue.core.query.KeyValueQuery;
-import org.springframework.util.Assert;
-
-import io.tarantool.spring.data.query.PaginationDirection;
-import io.tarantool.spring.data.query.TarantoolCriteria;
-
-public class PaginationUtils {
-
- private static final String CRITERIA_NULL_EXC_MSG = "TarantoolCriteria must be not null";
-
- /**
- * Returns {@link TarantoolPageable} cast from {@link Pageable} with type checking.
- *
- * @param sliceParams pageable
- * @return {@link TarantoolPageable}
- */
- public static TarantoolPageable> castToTarantoolPageable(Pageable sliceParams) {
- Assert.isInstanceOf(TarantoolPageable.class, sliceParams, "Pageable must be TarantoolPageable");
- return (TarantoolPageable>) sliceParams;
- }
-
- /**
- * A general method for retrieving data for paginated queries.
- *
- * @param query query
- * @param pageRequest {@link TarantoolPageable}
- * @param pageSize page size
- * @return selection result.
- */
- public static List> doPaginationQuery(
- final KeyValueQuery> query,
- TarantoolPageable> pageRequest,
- int pageSize,
- KeyValueOperations keyValueOperations,
- Class> targetType) {
-
- TarantoolCriteria criteria = (TarantoolCriteria) query.getCriteria();
- PaginationDirection paginationDirection = pageRequest.getPaginationDirection();
-
- Assert.notNull(criteria, CRITERIA_NULL_EXC_MSG);
- criteria.withAfter(pageRequest.getTupleCursor());
-
- query.setRows(pageSize * paginationDirection.getMultiplier());
-
- return IterableConverter.toList(keyValueOperations.find(query, targetType));
- }
-
- public static Page> doPageQuery(
- Pageable pageable,
- KeyValueQuery> query,
- KeyValueOperations keyValueOperations,
- Class> targetType) {
- if (pageable.isUnpaged()) {
- return new TarantoolPageImpl<>();
- }
- TarantoolPageable> resultSliceParams = castToTarantoolPageable(pageable);
-
- int pageSize = resultSliceParams.getPageSize();
-
- // non transactional calls
- List> content =
- doPaginationQuery(query, resultSliceParams, pageSize, keyValueOperations, targetType);
-
- if (content.isEmpty()) {
- return new TarantoolPageImpl<>();
- }
-
- long totalElements = keyValueOperations.count(query, targetType);
- return new TarantoolPageImpl<>(content, resultSliceParams, totalElements);
- }
-}
diff --git a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/query/TarantoolChunk.java b/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/query/TarantoolChunk.java
deleted file mode 100644
index a1e852e4..00000000
--- a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/query/TarantoolChunk.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (c) 2026 VK DIGITAL TECHNOLOGIES LIMITED LIABILITY COMPANY
- * All Rights Reserved.
- */
-
-package io.tarantool.spring.data27.query;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Objects;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-
-import org.springframework.data.domain.Pageable;
-import org.springframework.data.domain.Slice;
-import org.springframework.data.domain.Sort;
-import org.springframework.lang.NonNull;
-import org.springframework.util.Assert;
-
-/**
- * A chunk of data restricted by the configured {@link Pageable} for Tarantool.
- *
- * @author Nikolay Belonogov
- */
-abstract class TarantoolChunk implements Slice, Serializable {
-
- private static final long serialVersionUID = 867755909294344406L;
-
- private final List content = new ArrayList<>();
-
- private final Pageable pageable;
-
- /**
- * Creates a new {@link TarantoolChunk} with the given content and the given governing {@link
- * TarantoolPageable}.
- *
- * @param content must not be {@literal null}.
- * @param pageable must not be {@literal null}.
- */
- public TarantoolChunk(List content, Pageable pageable) {
-
- Assert.notNull(content, "Content must not be null");
- Assert.notNull(pageable, "Pageable must not be null");
-
- if (pageable.isPaged() && !(pageable instanceof TarantoolPageable)) {
- throw new IllegalArgumentException("Pageable must be TarantoolPageable or Unpaged type");
- }
-
- this.content.addAll(content);
- this.pageable = pageable;
- }
-
- @Override
- public boolean isFirst() {
- return !hasPrevious();
- }
-
- @Override
- public boolean isLast() {
- return !hasNext();
- }
-
- @Override
- public boolean hasPrevious() {
- return getNumber() > 0 && hasContent();
- }
-
- @Override
- public boolean hasContent() {
- return !content.isEmpty();
- }
-
- /**
- * Returns the {@link Pageable} to request the next {@link Slice}. Can be {@link
- * Pageable#unpaged()} in case the current {@link Slice} is already the last one or when data
- * content is empty. Clients should check {@link #hasNext()} and {@link #hasContent()} before
- * calling this method.
- *
- * @see #nextOrLastPageable()
- */
- @NonNull
- @Override
- @SuppressWarnings("unchecked")
- public Pageable nextPageable() {
- if (hasNext() && pageable.isPaged()) {
- return ((TarantoolPageable) pageable).next(content.get(content.size() - 1));
- }
- return Pageable.unpaged();
- }
-
- /**
- * Returns the {@link Pageable} to request the previous {@link Slice}. Can be {@link
- * Pageable#unpaged()} in case the current {@link Slice} is already the first one or data content
- * is empty. Clients should check {@link #hasPrevious()} and {@link #hasContent()} before calling
- * this method.
- *
- * @see #previousOrFirstPageable()
- */
- @NonNull
- @Override
- @SuppressWarnings("unchecked")
- public Pageable previousPageable() {
- if (hasPrevious() && pageable.isPaged()) {
- return ((TarantoolPageable) pageable).previousOrFirst(content.get(0));
- }
- return Pageable.unpaged();
- }
-
- @Override
- public Iterator iterator() {
- return content.iterator();
- }
-
- @NonNull
- @Override
- public List getContent() {
- return Collections.unmodifiableList(content);
- }
-
- @NonNull
- @Override
- public Pageable getPageable() {
- return pageable;
- }
-
- @NonNull
- @Override
- public Sort getSort() {
- return pageable.getSort();
- }
-
- @Override
- public int getNumber() {
- if (pageable.isPaged()) {
- return pageable.getPageNumber();
- }
- return 0;
- }
-
- @Override
- public int getSize() {
- if (pageable.isPaged()) {
- return pageable.getPageSize();
- }
- return content.size();
- }
-
- @Override
- public int getNumberOfElements() {
- return content.size();
- }
-
- /**
- * Applies the given {@link Function} to the content of the {@link TarantoolChunk}.
- *
- * @param converter must not be {@literal null}.
- */
- protected List getConvertedContent(Function super T, ? extends U> converter) {
-
- Assert.notNull(converter, "Function must not be null");
-
- return this.stream().map(converter).collect(Collectors.toList());
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (!(o instanceof TarantoolChunk)) {
- return false;
- }
- TarantoolChunk> that = (TarantoolChunk>) o;
- return content.equals(that.content) && pageable.equals(that.pageable);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(content, pageable);
- }
-}
diff --git a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/query/TarantoolCriteriaAccessor.java b/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/query/TarantoolCriteriaAccessor.java
deleted file mode 100644
index 00f1143e..00000000
--- a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/query/TarantoolCriteriaAccessor.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2026 VK DIGITAL TECHNOLOGIES LIMITED LIABILITY COMPANY
- * All Rights Reserved.
- */
-
-package io.tarantool.spring.data27.query;
-
-import org.springframework.data.keyvalue.core.CriteriaAccessor;
-import org.springframework.data.keyvalue.core.query.KeyValueQuery;
-
-import io.tarantool.spring.data.query.TarantoolCriteria;
-
-/**
- * Provide a mechanism to convert the abstract query into the direct implementation in Tarantool.
- *
- * @author Artyom Dubinin
- */
-public class TarantoolCriteriaAccessor implements CriteriaAccessor {
-
- /**
- * @param query in Spring form
- * @return The same in Tarantool form
- */
- public TarantoolCriteria resolve(KeyValueQuery> query) {
- return (TarantoolCriteria) query.getCriteria();
- }
-}
diff --git a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/query/TarantoolPageImpl.java b/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/query/TarantoolPageImpl.java
deleted file mode 100644
index 3f72b54f..00000000
--- a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/query/TarantoolPageImpl.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (c) 2026 VK DIGITAL TECHNOLOGIES LIMITED LIABILITY COMPANY
- * All Rights Reserved.
- */
-
-package io.tarantool.spring.data27.query;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-import java.util.function.Function;
-
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.PageImpl;
-import org.springframework.data.domain.Pageable;
-import org.springframework.lang.NonNull;
-
-/**
- * Basic {@code Page} implementation for Tarantool.
- *
- * @param domain class type.
- * @author Nikolay Belonogov
- */
-class TarantoolPageImpl extends TarantoolChunk implements Page {
-
- private static final long serialVersionUID = 867755909294344406L;
-
- private final long total;
-
- /**
- * Creates a new {@link TarantoolPageImpl} with empty content. This will result in the created
- * {@link Page} being identical to the entire {@link List}.
- */
- public TarantoolPageImpl() {
- this(Collections.emptyList(), Pageable.unpaged(), 0L);
- }
-
- /**
- * Creates a new {@link TarantoolPageImpl} with the given content. This will result in the created
- * {@link Page} being identical to the entire {@link List}.
- *
- * @param content must not be {@literal null}.
- */
- public TarantoolPageImpl(List content) {
- this(content, Pageable.unpaged(), content == null ? 0L : content.size());
- }
-
- /**
- * Constructor of {@link TarantoolPageImpl}.
- *
- * @param content the content of this page, must not be {@literal null}.
- * @param pageable the paging information, must not be {@literal null}.
- * @param total the total amount of items available. The total might be adapted considering the
- * length of the content given, if it is going to be the content of the last page. This is in
- * place to mitigate inconsistencies.
- */
- public TarantoolPageImpl(List content, Pageable pageable, long total) {
-
- super(content, pageable);
-
- this.total =
- pageable
- .toOptional()
- .filter(it -> !content.isEmpty())
- .filter(it -> it.getOffset() + it.getPageSize() > total)
- .map(it -> it.getOffset() + content.size())
- .orElse(total);
- }
-
- @Override
- public int getTotalPages() {
- return getSize() == 0 ? 1 : (int) Math.ceil((double) total / (double) getSize());
- }
-
- @Override
- public long getTotalElements() {
- return total;
- }
-
- @Override
- public boolean hasNext() {
- return getNumber() + 1 < getTotalPages() && hasContent();
- }
-
- @Override
- public boolean isLast() {
- return !hasNext();
- }
-
- @Override
- @NonNull
- public Page map(@NonNull Function super T, ? extends U> converter) {
- return new PageImpl<>(getConvertedContent(converter), getPageable(), total);
- }
-
- @Override
- public String toString() {
-
- List content = getContent();
- boolean canGetContentType = !content.isEmpty() && content.get(0) != null;
-
- String contentType = canGetContentType ? content.get(0).getClass().getName() : "UNKNOWN";
-
- return String.format(
- "Page %s of %d containing %s instances", getNumber() + 1, getTotalPages(), contentType);
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (!(o instanceof TarantoolPageImpl)) {
- return false;
- }
- if (!super.equals(o)) {
- return false;
- }
- TarantoolPageImpl> that = (TarantoolPageImpl>) o;
- return total == that.total;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(super.hashCode(), total);
- }
-}
diff --git a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/query/TarantoolPageRequest.java b/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/query/TarantoolPageRequest.java
deleted file mode 100644
index 918af34a..00000000
--- a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/query/TarantoolPageRequest.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright (c) 2026 VK DIGITAL TECHNOLOGIES LIMITED LIABILITY COMPANY
- * All Rights Reserved.
- */
-
-package io.tarantool.spring.data27.query;
-
-import java.util.Objects;
-
-import org.springframework.data.domain.AbstractPageRequest;
-import org.springframework.data.domain.Sort;
-import org.springframework.lang.NonNull;
-import org.springframework.util.Assert;
-
-import static io.tarantool.spring.data.query.PaginationDirection.BACKWARD;
-import static io.tarantool.spring.data.query.PaginationDirection.FORWARD;
-import io.tarantool.spring.data.query.PaginationDirection;
-
-/**
- * Basic implementation of {@link TarantoolPageable} for Tarantool.
- *
- *
Important: When specifying a cursor tuple, you must adhere to the following
- * rules:
- *
- *
1. To specify a page starting from the beginning of {@code space} (the first element of the
- * page is the first element found in {@code space}), use {@code tupleCursor == null}.
- *
- *
2. To specify an arbitrary page (the first element of the page is the next/previous one from
- * the given one tuple cursor depending on the methods used and page number), use {@code tupleCursor
- * == someTupleCursor} .
- *
- * @param domain entity type
- */
-public final class TarantoolPageRequest extends AbstractPageRequest
- implements TarantoolPageable {
-
- private static final long serialVersionUID = -4541509938956089562L;
-
- private final Sort sort;
-
- private final T tupleCursor;
-
- private final PaginationDirection paginationDirection;
-
- /**
- * Creates a new unsorted {@link TarantoolPageRequest} from begin of {@code space}.
- *
- * @param pageSize the size of the page to be returned, must be greater than 0.
- */
- public TarantoolPageRequest(int pageSize) {
- this(0, pageSize, null);
- }
-
- /**
- * Creates a new unsorted {@link TarantoolPageRequest}.
- *
- *
Important: Use this method with caution! It is important to know the exact
- * match of number pages and the tuple after (before) which the page goes (without including this
- * tuple in the page itself). A mistake in compliance results in the appearance of blank pages
- * with unpaged pageable even when using methods {@link
- * TarantoolPageImpl#previousOrFirstPageable()} / {@link TarantoolPageImpl#nextOrLastPageable()}
- * and {@link TarantoolSliceImpl#previousOrFirstPageable()} / {@link
- * TarantoolSliceImpl#nextOrLastPageable()}.
- *
- * @param page zero-based page index (virtual), must not be negative.
- * @param size the size of the page to be returned, must be greater than 0.
- * @param tupleCursor tuple cursor from which the page count begins. More: {@link
- * TarantoolPageRequest}.
- */
- public TarantoolPageRequest(int page, int size, T tupleCursor) {
- this(page, size, Sort.unsorted(), tupleCursor, FORWARD);
- }
-
- /**
- * Private constructor to create an instance with a specific {@link PaginationDirection}.
- *
- * @param page zero-based page index, must not be negative.
- * @param size the size of the page to be returned, must be greater than 0.
- * @param sort must not be {@literal null}, use {@link Sort#unsorted()} instead.
- * @param tupleCursor tuple cursor from which the page count begins. More: {@link
- * TarantoolPageRequest}.
- * @param direction direction of pagination.
- */
- TarantoolPageRequest(
- int page, int size, Sort sort, T tupleCursor, @NonNull PaginationDirection direction) {
- super(page, size);
- Assert.notNull(sort, "Sort must not be null");
- Assert.notNull(direction, "PaginationDirection must not be null");
-
- this.sort = sort;
- this.tupleCursor = tupleCursor;
- this.paginationDirection = direction;
- }
-
- /** Non supported for Tarantool. */
- @Override
- @NonNull
- public TarantoolPageRequest withPage(int pageNumber) throws UnsupportedOperationException {
- throw new UnsupportedOperationException("method \"withPage(int pageNumber)\" unsupported");
- }
-
- @Override
- @NonNull
- public TarantoolPageable first() {
- return new TarantoolPageRequest<>(getPageSize());
- }
-
- /** Non supported for Tarantool. Use {@link #next(Object)}. */
- @Override
- @NonNull
- public TarantoolPageRequest next() throws UnsupportedOperationException {
- throw new UnsupportedOperationException(
- "method \"next()\" unsupported, use next(T nextTupleCursor)");
- }
-
- @Override
- public TarantoolPageRequest next(T tupleCursor) {
- return new TarantoolPageRequest<>(
- getPageNumber() + 1, getPageSize(), getSort(), tupleCursor, FORWARD);
- }
-
- /** Non supported for Tarantool. Use {@link #previous(Object)}. */
- @Override
- @NonNull
- public TarantoolPageRequest previous() throws UnsupportedOperationException {
- throw new UnsupportedOperationException(
- "method \"previous()\" unsupported, use previous(T prevTupleCursor)");
- }
-
- private TarantoolPageRequest previous(T tupleCursor) {
- if (hasPrevious()) {
- return new TarantoolPageRequest<>(
- getPageNumber() - 1, getPageSize(), getSort(), tupleCursor, BACKWARD);
- }
- return this;
- }
-
- /** Non supported for Tarantool. Use {@link #previousOrFirst(Object)}. */
- @Override
- @NonNull
- public TarantoolPageable previousOrFirst() throws UnsupportedOperationException {
- throw new UnsupportedOperationException(
- "method \"previousOrFirst()\" unsupported, use previousOrFirst(T prevTupleCursor)");
- }
-
- @Override
- public TarantoolPageable previousOrFirst(T tupleCursor) {
- if (hasPrevious()) {
- return previous(tupleCursor);
- }
- return new TarantoolPageRequest<>(0, getPageSize(), getSort(), null, BACKWARD);
- }
-
- @Override
- public PaginationDirection getPaginationDirection() {
- return this.paginationDirection;
- }
-
- @Override
- @NonNull
- public Sort getSort() {
- return this.sort;
- }
-
- @Override
- public T getTupleCursor() {
- return this.tupleCursor;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (!(o instanceof TarantoolPageRequest)) {
- return false;
- }
- if (!super.equals(o)) {
- return false;
- }
- TarantoolPageRequest> that = (TarantoolPageRequest>) o;
- return sort.equals(that.sort)
- && Objects.equals(tupleCursor, that.tupleCursor)
- && paginationDirection == that.paginationDirection;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(super.hashCode(), sort, tupleCursor, paginationDirection);
- }
-}
diff --git a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/query/TarantoolPageable.java b/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/query/TarantoolPageable.java
deleted file mode 100644
index e4bd60f5..00000000
--- a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/query/TarantoolPageable.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2026 VK DIGITAL TECHNOLOGIES LIMITED LIABILITY COMPANY
- * All Rights Reserved.
- */
-
-package io.tarantool.spring.data27.query;
-
-import org.springframework.data.domain.Pageable;
-import org.springframework.lang.NonNull;
-import org.springframework.lang.Nullable;
-
-import io.tarantool.spring.data.query.PaginationDirection;
-
-/**
- * Abstract interface for pagination information in Tarantool.
- *
- * @param domain class type.
- * @author Nikolay Belonogov
- */
-public interface TarantoolPageable extends Pageable {
-
- /**
- * Returns tuple cursor of domain type. Can be {@code null}. If the cursor is {@code null} then
- * the page is counted from the first tuple in Tarantool.
- *
- * @return tuple cursor of domain type.
- */
- @Nullable
- T getTupleCursor();
-
- /**
- * Returns the {@link TarantoolPageable} for previous page or the {@link TarantoolPageable} for
- * first page if the current one already is the first one. Important: this method
- * always returns {@link TarantoolPageable} c {@link PaginationDirection#BACKWARD}.
- *
- * @param tupleCursor tuple cursor of domain type for previous page.
- * @return {@link TarantoolPageable} instance.
- */
- TarantoolPageable previousOrFirst(T tupleCursor);
-
- /**
- * Returns the {@link TarantoolPageable} requesting the next {@link
- * org.springframework.data.domain.Page}.
- *
- *
Important: method always creates a new {@link TarantoolPageable} with the
- * same parameters Sort and page size. Pagination direction is {@link
- * PaginationDirection#FORWARD}, the page number always has value {@code n+1}, n is the current
- * page number.
- *
- * @param tupleCursor tuple cursor of domain type for next page.
- * @return {@link TarantoolPageable} object
- */
- TarantoolPageable next(T tupleCursor);
-
- /**
- * Returns pagination direction by {@link PaginationDirection} enumeration.
- *
- * @return {@link PaginationDirection}.
- */
- PaginationDirection getPaginationDirection();
-
- /**
- * Returns a {@link TarantoolPageable} that points to the first page with {@link
- * PaginationDirection#FORWARD} pagination direction.
- *
- * @return {@link TarantoolPageable} which has {@code cursor == null}, page number is 0, the rest
- * parameters are equivalent to the parameters of the current {@link TarantoolPageable}.
- */
- @NonNull
- TarantoolPageable first();
-}
diff --git a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/query/TarantoolPartTreeQuery.java b/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/query/TarantoolPartTreeQuery.java
deleted file mode 100644
index 32952852..00000000
--- a/tarantool-spring-data/tarantool-spring-data-27/src/main/java/io/tarantool/spring/data27/query/TarantoolPartTreeQuery.java
+++ /dev/null
@@ -1,391 +0,0 @@
-/*
- * Copyright (c) 2026 VK DIGITAL TECHNOLOGIES LIMITED LIABILITY COMPANY
- * All Rights Reserved.
- */
-
-package io.tarantool.spring.data27.query;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import org.springframework.data.domain.Pageable;
-import org.springframework.data.domain.Sort;
-import org.springframework.data.keyvalue.core.KeyValueOperations;
-import org.springframework.data.keyvalue.core.query.KeyValueQuery;
-import org.springframework.data.keyvalue.repository.query.KeyValuePartTreeQuery;
-import org.springframework.data.repository.query.Parameter;
-import org.springframework.data.repository.query.Parameters;
-import org.springframework.data.repository.query.ParametersParameterAccessor;
-import org.springframework.data.repository.query.QueryMethod;
-import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider;
-import org.springframework.data.repository.query.RepositoryQuery;
-import org.springframework.data.repository.query.parser.AbstractQueryCreator;
-import org.springframework.data.repository.query.parser.Part;
-import org.springframework.data.repository.query.parser.PartTree;
-import org.springframework.data.util.StreamUtils;
-import org.springframework.lang.NonNull;
-import org.springframework.util.Assert;
-
-import static io.tarantool.spring.data27.query.PaginationUtils.castToTarantoolPageable;
-import static io.tarantool.spring.data27.query.PaginationUtils.doPageQuery;
-import static io.tarantool.spring.data27.query.PaginationUtils.doPaginationQuery;
-import io.tarantool.client.crud.options.SelectOptions;
-import io.tarantool.spring.data.query.PaginationDirection;
-
-/**
- * There is one instance for each query method defined for a repository, providing a query from the
- * bind parameters.
- *
- * @author Artyom Dubinin
- */
-public class TarantoolPartTreeQuery extends KeyValuePartTreeQuery {
-
- public static final String ILLEGAL_RETURN_TYPE_FOR_DELETE =
- "Illegal returned type: %s. The operation 'deleteBy' accepts only 'long' and 'Collection' as"
- + " the returned object type";
- public static final String QUERY_METHOD_S_NOT_SUPPORTED = "Query method '%s' not supported.";
- private final QueryMethod queryMethod;
- private final KeyValueOperations keyValueOperations;
- private final PartTree tree;
-
- private final boolean isCount;
- private final boolean isDelete;
- private final boolean isDistinct;
- private final boolean isExists;
- private final Class> targetType;
- private final Class> returnType;
-
- private boolean isRearrangeKnown;
- private boolean isRearrangeRequired;
- private int[] rearrangeIndex;
-
- /**
- * Create a {@link RepositoryQuery} implementation for each query method defined in a tarantool
- * repository.
- *
- * @param queryMethod Method defined in Tarantool Repositories
- * @param evaluationContextProvider Not used
- * @param keyValueOperations Interface to Tarantool
- * @param queryCreator Not used
- */
- public TarantoolPartTreeQuery(
- QueryMethod queryMethod,
- QueryMethodEvaluationContextProvider evaluationContextProvider,
- KeyValueOperations keyValueOperations,
- Class extends AbstractQueryCreator, ?>> queryCreator) {
- super(queryMethod, evaluationContextProvider, keyValueOperations, queryCreator);
- this.queryMethod = queryMethod;
- this.keyValueOperations = keyValueOperations;
- this.isRearrangeKnown = false;
- this.targetType = queryMethod.getEntityInformation().getJavaType();
- this.returnType = queryMethod.getReturnedObjectType();
- this.tree = new PartTree(getQueryMethod().getName(), targetType);
- if (queryMethod.getParameters().getNumberOfParameters() > 0) {
- this.isCount = tree.isCountProjection();
- this.isDelete = tree.isDelete();
- this.isDistinct = tree.isDistinct();
- this.isExists = tree.isExistsProjection();
- } else {
- this.isCount = false;
- this.isDelete = false;
- this.isDistinct = false;
- this.isExists = false;
- }
- }
-
- /**
- * Execute this query instance, using any invocation parameters.
- *
- *
Expecting {@code findBy...()}, {@code countBy...()} or {@code deleteBy...()}
- *
- * @param parameters Any parameters
- * @return Query result
- */
- @Override
- public Object execute(@NonNull Object[] parameters) {
- ParametersParameterAccessor accessor = this.prepareAccessor(parameters, tree);
-
- KeyValueQuery> query = prepareQuery(accessor);
-
- if (this.isCount) {
- if (this.isDistinct) {
- final Iterable> iterable = this.keyValueOperations.find(query, targetType);
- return StreamUtils.createStreamFromIterator(iterable.iterator()).distinct().count();
- }
- return this.keyValueOperations.count(query, targetType);
- }
-
- if (this.isDelete) {
- return this.executeDeleteQuery(query);
- }
-
- if (this.isExists) {
- query.setOffset(0);
- query.setRows(1);
- final Iterable> result = this.keyValueOperations.find(query, targetType);
- return result.iterator().hasNext();
- }
-
- if (queryMethod.isPageQuery()) {
- return this.executePageQuery(query, accessor);
- }
-
- if (queryMethod.isSliceQuery()) {
- return this.executeSliceQuery(query, accessor);
- }
-
- if (queryMethod.isCollectionQuery()
- || queryMethod.isQueryForEntity()
- || queryMethod.isStreamQuery()) {
- return this.executeFindQuery(query);
- }
-
- throw new UnsupportedOperationException(
- String.format(QUERY_METHOD_S_NOT_SUPPORTED, queryMethod.getName()));
- }
-
- /**
- * Execute a "delete" query, not really a query more of an operation.
- *
- *
- *
- * @param query The query to run
- * @return Collection of deleted objects or the number of deleted objects
- */
- private Object executeDeleteQuery(final KeyValueQuery> query) {
-
- Iterable> resultSet = this.keyValueOperations.find(query, targetType);
- Iterator> iterator = resultSet.iterator();
-
- List