Skip to content
Merged
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
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@

- Add `tarantool-spring-data-40` module with support for Spring Boot 4.0.x and Spring Data 4.0.x

### Testcontainers

- Add constructor/builder parameters to supply the initial Lua script as a string or as a file path, and optional additional script paths copied into the container data directory (`Tarantool2Container`, `CartridgeClusterContainer`, `VshardClusterContainer`); simplify bundled `server.lua` accordingly.

### Documentation

- Document supported Java types for Tarantool data mapping in `tuple_pojo_mapping` docs (RU/EN), including Tarantool extension types (`decimal`, `uuid`, `datetime`, `interval`, `tuple`) and related mapping notes.
- Document Jackson MsgPack deserialization: integers, `bin`/`str` vs `byte[]`/`String`, floating-point vs `decimal`; reference `jackson-dataformat-msgpack` for defaults and type coercion.

## [1.6.0] - 2026-04-01

### BOM Module
Expand Down
69 changes: 69 additions & 0 deletions documentation/doc-src/pages/client/arch/tuple_pojo_mapping.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,75 @@ guide, but will help you understand the principles of interaction. Mastering the
efficiently with the database in any scenarios, whether it's a cluster or a single instance, and with any POJO
objects.

## Supported Java Types for Mapping

The SDK uses `Jackson + jackson-dataformat-msgpack`, so:

- standard Java/Jackson types (primitives and wrappers, `String`, `byte[]`, `List`, `Map`, nested POJOs)
are supported by default;
- Tarantool extension types are additionally supported.

Below are the types that have explicit Tarantool extension-type mapping in the SDK:

| Tarantool type | Java type | Comment |
| --- | --- | --- |
| `decimal` | `java.math.BigDecimal` | Uses MsgPack `decimal` extension; scale with absolute value up to and including `38` is supported. |
| `uuid` | `java.util.UUID` | Uses MsgPack `uuid` extension. |
| `datetime` | `java.time.Instant`, `java.time.LocalDateTime`, `java.time.LocalDate`, `java.time.LocalTime`, `java.time.OffsetDateTime`, `java.time.ZonedDateTime` | Uses MsgPack `datetime` extension. |
| `interval` | `io.tarantool.mapping.Interval` | Uses MsgPack `interval` extension. |
| `tuple` (Tarantool 3.x, `TUPLE_EXT`) | `io.tarantool.mapping.Tuple<T>` | Uses MsgPack `tuple` extension; useful when tuple format is returned with tuple data. |

???+ note "Note"

If you read data as `Object` (without an explicit target type), extension values are
deserialized to SDK Java objects automatically:
`decimal -> BigDecimal`, `uuid -> UUID`, `datetime -> ZonedDateTime`,
`interval -> Interval`, `tuple -> Tuple<?>`.

## Jackson MsgPack: defaults and deserialization

POJO mapping uses **Jackson** and the [**jackson-dataformat-msgpack**](https://github.com/FasterXML/jackson-dataformats-binary/tree/2.18/msg-pack) module.
Handling of **missing properties**, **default values**, and **type coercion** on deserialization is defined by Jackson configuration and API (`DeserializationFeature`, constructors, `@JsonCreator`, etc.) and by the actual MsgPack value type on the wire. Authoritative specification is in the `jackson-dataformat-msgpack` documentation and release notes for the Jackson line in use.

### Integers

MsgPack encodes integers with variable width (fixint, int8/16/32/64, uint*). The deserializer coerces them to the declared Java type (`int`, `long`, `Integer`, `BigInteger`, ...).
If the target type is **narrower** than the wire value allows, deserialization may fail or lose precision; the Java field type must match the value range stored in Tarantool (including large `unsigned` values).

### Deserialization into `Object` (untyped)

If the target type is `java.lang.Object` (including elements of `List<?>`, values in `Map<String, Object>`, and raw `Object` fields), Jackson uses `UntypedObjectDeserializer` and, for numbers, `JsonParser.getNumberValue()`. The SDK depends on **`org.msgpack:jackson-dataformat-msgpack`**; scalar shapes are determined by its `MessagePackParser` (integers are **not** mapped to `Byte`/`Short` just because the wire encoding is small).

| MsgPack on the wire | Java type when binding to `Object` (default `ObjectMapper` in the SDK) |
| --- | --- |
| **Signed** integer (fixint, int8, int16, int32, int64) | `Integer` if the value fits in `int`; otherwise `Long` |
| **uint64** | `Long` if the value fits in signed `long`; otherwise `BigInteger` |
| **float32** / **float64** | `Double` (both are read as double-precision) |
| **nil** | `null` |
| **boolean** | `Boolean` |
| **binary** (`bin`) | `byte[]` |
| **string** (`str`) | `String` |
| **map** | `LinkedHashMap<String, Object>` |
| **array** | `ArrayList<Object>` |
| Tarantool/SDK **extensions** (`decimal`, `uuid`, `datetime`, …) | `BigDecimal`, `UUID`, `ZonedDateTime`, `Interval`, `Tuple<?>`, … (see the Tarantool/SDK type table and the `Object` note at the start of the POJO section) |

With `DeserializationFeature.USE_BIG_INTEGER_FOR_INTS` enabled on the `ObjectMapper`, untyped integers may always deserialize as `BigInteger` — see Jackson Javadoc. `BaseTarantoolJacksonMapping` does **not** enable this flag.

### `byte[]` and `String` (`bin` and `str` families)

In MsgPack, **binary** (`bin` family) and **string** (`str` family) are distinct. Default mapping:

- **`byte[]`** — **binary** payload;
- **`String`** — **string** payload (UTF-8).

A mismatch between the MsgPack format and the Java field type (for example, **string** on the wire and **`byte[]`** in the POJO) does not guarantee successful deserialization with the module defaults. Alternatives: aligned storage schema and POJO types, an intermediate type with conversion, **`@JsonDeserialize`**, or a custom `JsonDeserializer` (see `jackson-dataformat-msgpack` documentation).

### `float` / `double` and `decimal`

Non-extension floating-point values in MsgPack are **float32** / **float64**. Tarantool **`decimal`** is transmitted as a **MsgPack extension** in this SDK and maps to **`java.math.BigDecimal`** (table above).

Pairing **float32/float64** on the wire with a **`BigDecimal`** field, or a **decimal extension** with **`float`** / **`double`**, follows Jackson type-coercion rules and the module version; an explicit field type or a boundary deserializer may be required.

## Efficient Mapping (Flatten input, Flatten output)

By default, field mapping in any of the clients (CrudClient, BoxClient) is performed in the most
Expand Down
69 changes: 69 additions & 0 deletions documentation/doc-src/pages/client/arch/tuple_pojo_mapping.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,75 @@ tarantool-java-sdk SDK есть модуль, который будет сери
работать с базой данных в любых сценариях, будь то кластер или одиночный экземпляр, и с любыми POJO
объектами.

## Поддерживаемые Java-типы при маппинге

SDK использует `Jackson + jackson-dataformat-msgpack`, поэтому:

- базовые типы Java/Jackson (примитивы и их обертки, `String`, `byte[]`, `List`, `Map`, вложенные POJO)
поддерживаются по умолчанию;
- дополнительно поддерживаются extension-типы Tarantool.

Ниже приведены типы, для которых в SDK есть явный маппинг из/в Tarantool extension types:

| Tarantool type | Java type | Комментарий |
| --- | --- | --- |
| `decimal` | `java.math.BigDecimal` | Используется MsgPack extension `decimal`; поддерживается scale по модулю до `38` включительно. |
| `uuid` | `java.util.UUID` | Используется MsgPack extension `uuid`. |
| `datetime` | `java.time.Instant`, `java.time.LocalDateTime`, `java.time.LocalDate`, `java.time.LocalTime`, `java.time.OffsetDateTime`, `java.time.ZonedDateTime` | Используется MsgPack extension `datetime`. |
| `interval` | `io.tarantool.mapping.Interval` | Используется MsgPack extension `interval`. |
| `tuple` (Tarantool 3.x, `TUPLE_EXT`) | `io.tarantool.mapping.Tuple<T>` | Используется MsgPack extension `tuple`; полезно, когда вместе с данными приходит формат кортежа. |

???+ note "Заметка"

Если вы читаете данные как `Object` (без явного целевого класса), extension-типы будут
десериализованы в Java-объекты SDK автоматически:
`decimal -> BigDecimal`, `uuid -> UUID`, `datetime -> ZonedDateTime`,
`interval -> Interval`, `tuple -> Tuple<?>`.

## Jackson MsgPack: значения по умолчанию и десериализация

Маппинг POJO выполняется через **Jackson** и модуль [**jackson-dataformat-msgpack**](https://github.com/FasterXML/jackson-dataformats-binary/tree/2.18/msg-pack).
Обработка **отсутствующих свойств**, **значений по умолчанию** и **приведения типов** при десериализации определяется настройками и API Jackson (`DeserializationFeature`, конструкторы, `@JsonCreator` и др.) и фактическим типом значения в MsgPack. Нормативное описание — в документации и release notes `jackson-dataformat-msgpack` для используемой линии Jackson.

### Целые числа

В MsgPack целые значения кодируются с переменной шириной (fixint, int8/16/32/64, uint*). Десериализатор приводит их к объявленному типу Java (`int`, `long`, `Integer`, `BigInteger` и т.д.).
При **более узком** целевом типе, чем допускает значение на wire, возможны ошибка десериализации или потеря точности; тип поля в Java должен соответствовать диапазону данных на стороне Tarantool (в том числе для больших `unsigned`).

### Десериализация в `Object` (без явного типа)

Если целевой тип — `java.lang.Object` (в т.ч. элементы `List<?>`, значения в `Map<String, Object>` и поля с сырым `Object`), Jackson использует `UntypedObjectDeserializer`, а для чисел вызывает `JsonParser.getNumberValue()`. В SDK подключается **`org.msgpack:jackson-dataformat-msgpack`**; фактические классы для скаляров задаёт его `MessagePackParser` (целые не становятся `Byte`/`Short` только из‑за «малого» значения на wire).

| Что приходит в MsgPack | Тип в Java при десериализации в `Object` (настройки `ObjectMapper` по умолчанию в SDK) |
| --- | --- |
| Целое **signed** (fixint, int8, int16, int32, int64) | `Integer`, если значение в диапазоне `int`; иначе `Long` |
| **uint64** | `Long`, если значение помещается в диапазон signed `long`; иначе `BigInteger` |
| **float32** / **float64** | `Double` (оба формата читаются как double-precision) |
| **nil** | `null` |
| **boolean** | `Boolean` |
| **binary** (`bin`) | `byte[]` |
| **string** (`str`) | `String` |
| **map** | `LinkedHashMap<String, Object>` |
| **array** | `ArrayList<Object>` |
| **extension** Tarantool/SDK (`decimal`, `uuid`, `datetime`, …) | `BigDecimal`, `UUID`, `ZonedDateTime`, `Interval`, `Tuple<?>`, … (таблица типов и заметка про чтение как `Object` — в начале раздела про POJO) |

Если на `ObjectMapper` включён `DeserializationFeature.USE_BIG_INTEGER_FOR_INTS`, целые в контексте «untyped» могут стабильно приходить как `BigInteger` — см. Javadoc Jackson. В `BaseTarantoolJacksonMapping` этот флаг **не** включается.

### `byte[]` и `String` (семейства `bin` и `str`)

В MsgPack типы **binary** (семейство `bin`) и **string** (семейство `str`) различны. Сопоставление по умолчанию:

- **`byte[]`** — полезная нагрузка в формате **binary**;
- **`String`** — полезная нагрузка в формате **string** (UTF-8).

Несовпадение формата MsgPack и типа поля Java (например, **string** на wire и **`byte[]`** в POJO) не гарантирует успешную десериализацию стандартными средствами модуля. Альтернативы: согласованный тип в схеме хранения и в POJO, промежуточный тип с последующим преобразованием, **`@JsonDeserialize`** или пользовательский `JsonDeserializer` (см. документацию `jackson-dataformat-msgpack`).

### `float` / `double` и `decimal`

В MsgPack значения с плавающей точкой без extension — **float32** / **float64**. Значение **`decimal`** Tarantool в SDK передаётся как **MsgPack extension** и мапится на **`java.math.BigDecimal`** (таблица выше).

Сочетание **float32/float64** на wire с полем **`BigDecimal`**, либо **decimal extension** с полем **`float`** / **`double`**, задаётся правилами приведения типов Jackson и версией модуля; при необходимости используется явный тип поля или десериализатор на границе.

## Эффективный Маппинг (Flatten input, Flatten output)

По умолчанию маппинг полей в любом из клиентов(CrudClient, BoxClient), выполняется наиболее
Expand Down