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
96 changes: 40 additions & 56 deletions documentation/doc-src/pages/client/arch/tuple_pojo_mapping.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ objects.

## Efficient Mapping (Flatten input, Flatten output)

By default, field mapping in any of the clients (CrudClient, BoxClient), is performed in the most
By default, field mapping in any of the clients (CrudClient, BoxClient) is performed in the most
efficient way — by the field's ordinal number.

This means that if the field order in Tarantool is:
Expand Down Expand Up @@ -193,7 +193,7 @@ public class TestClass {

## Flexible Mapping Using Keys

You can also configure flexible mapping and work with keys in several ways. In these ways
You can also configure flexible mapping and work with keys in several ways. In these approaches
we will use the same data schema on the Tarantool side that we used for efficient
mapping:

Expand Down Expand Up @@ -225,7 +225,7 @@ public class UnorderedPerson {
public Boolean isMarried;
public Integer id;

public Person(
public UnorderedPerson(
@JsonProperty("is_married") Boolean isMarried,
@JsonProperty("id") Integer id,
@JsonProperty("name") String name) {
Expand Down Expand Up @@ -343,8 +343,8 @@ Deserialization is possible in several ways:

1. ```
Flatten output method -- Using standard Tarantool read methods -> receiving Msgpack array \
Converting array using data format to POJO format
Getting the {field key -> field number} map in any way /
Converting array using data format to POJO format
Getting the {field key -> field number} map in any way /
```
2. ```
Unflatten output -- Receiving Msgpack Map -> converting Msgpack Map to POJO using Jackson
Expand All @@ -371,7 +371,7 @@ List<UnorderedPerson> persons = routerClient.eval("""
"person",
Arrays.asList(Arrays.asList("==", "pk", 1))
),
new TypeReference<List<List<PersonWithDifferentFieldsOrder>>>() {}
new TypeReference<List<List<UnorderedPerson>>>() {}
).thenApply(
tarantoolResponse -> tarantoolResponse.get() // unwrap TarantoolResponse
.get(0) // get first object from multi return
Expand Down Expand Up @@ -424,29 +424,11 @@ public class TestClass {
@Test
public void test() {
space.select(Arrays.asList(1)).thenApply(
list -> {
var result = new ArrayList<>();

for (var t : list.get()) { // unwrap tuple struct from select response struct
List<?> dataList = t.get(); // unwrap data from tuple struct
Map<String, ?> map = IntStream // create map {key -> value}
.range(0, dataList.size())
.boxed()
.collect(
Collectors.toMap(
(i) -> tupleFormat.get(i).getName(),
dataList::get
)
);
// use jackson mapper to map from Map to Person POJO
// import static io.tarantool.mapping.BaseTarantoolJacksonMapping.objectMapper;
UnorderedPerson person = objectMapper.convertValue(map, UnorderedPerson.class);

result.add(person);
}

return result;
}
list -> TupleMapper.mapToPojoList(
list.get(),
tupleFormat,
UnorderedPerson.class
)
).join();
// [UnorderedPerson{name='artyom', isMarried=true, id=1}]
}
Expand All @@ -456,7 +438,7 @@ public class TestClass {
##### 2. Using tarantool/crud Response Metadata

More information about the tarantool/crud response structure can be found
here [github.com/tarantool/crud](https://github.com/tarantool/crud?tab=readme-ov-file#api).
here [github.com/tarantool/crud](https://github.com/tarantool/crud?tab=readme-ov-file#api).
Create a TarantoolCrud client that is a proxy to the tarantool/crud module API.

```java
Expand All @@ -481,7 +463,30 @@ person:format({
var space = client.space("person");
```

If you have a connector version that does not return tarantool/crud response metadata,
###### Connector version > 1.5.0

Metadata can be obtained from TUPLE_EXT if the crud method supports TUPLE_EXT format, or from
crud response metadata.

```java
public class TestClass {

@Test
public void test() {
// Format is automatically passed from CrudResponse.metadata
List<Tuple<List<?>>> tuples = space.select(
Collections.singletonList(Condition.create(EQ, "id", 1))
).join();

// Map using format from tuple
UnorderedPerson person = TupleMapper.mapToPojo(tuples.get(0), UnorderedPerson.class);
}
}
```

###### Connector version <= 1.5.0

If you have a connector version that does not return tarantool/crud response metadata,
you can call the tarantool/crud methods directly:

```java
Expand Down Expand Up @@ -510,19 +515,8 @@ public class TestClass {
}

for (List<?> tuple : tuples) {
Map<Object, ?> map = IntStream // create map {key -> value}
.range(0, tuple.size())
.boxed()
.collect(
Collectors.toMap(
(i) -> metadata.get(i).getName(),
tuple::get
)
);

// use jackson mapper to map from Map to Person POJO
// import static io.tarantool.mapping.BaseTarantoolJacksonMapping.objectMapper;
UnorderedPerson person = objectMapper.convertValue(map, UnorderedPerson.class);
// use TupleMapper to map from tuple data and format to Person POJO
UnorderedPerson person = TupleMapper.mapToPojo(tuple, metadata, UnorderedPerson.class);

result.add(person);
}
Expand Down Expand Up @@ -566,19 +560,9 @@ public class TestClass {
}

for (Tuple<List<?>> tuple : tuples) {
List<io.tarantool.mapping.Field> format = tuple.getFormat();
List<?> data = tuple.get();
Map<Object, ?> map = IntStream
.range(0, data.size())
.boxed()
.collect(
Collectors.toMap(
(i) -> format.get(i).getName(),
data::get
)
);
// use TupleMapper to map tuple with embedded format to POJO
result.add(
objectMapper.convertValue(map, PersonWithDifferentFieldsOrder.class)
TupleMapper.mapToPojo(tuple, PersonWithDifferentFieldsOrder.class)
);
}

Expand Down
102 changes: 43 additions & 59 deletions documentation/doc-src/pages/client/arch/tuple_pojo_mapping.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ title: Маппинг данных
Jackson.

С помощью Jackson можно преобразовывать Java объекты в JSON (сериализация) и наоборот
(десериализация). Также можно использовать расширения Jackson для других форматов сериализация
(десериализация). Также можно использовать расширения Jackson для других форматов сериализации
данных.

В `tarantool-java-sdk` используется библиотека Jackson с расширением для работы с `Msgpack`, которая
Expand Down Expand Up @@ -227,7 +227,7 @@ public class UnorderedPerson {
public Boolean isMarried;
public Integer id;

public Person(
public UnorderedPerson(
@JsonProperty("is_married") Boolean isMarried,
@JsonProperty("id") Integer id,
@JsonProperty("name") String name) {
Expand Down Expand Up @@ -314,7 +314,7 @@ person:format({
})
```

То метод в POJO должен выглядит так:
То метод в POJO должен выглядеть так:

```java
public class UnorderedPerson {
Expand All @@ -340,9 +340,9 @@ public class TestClass {

Что позволит передавать POJO как кортеж, при этом, продолжая, работать с объектом UnorderedPerson.

### Чтения POJO из Tarantool
### Чтение POJO из Tarantool

Десериалиация возможна несколькими способами:
Десериализация возможна несколькими способами:

1. ```
Flatten output method -- Использование стандартных методов чтения Tarantool -> получение Msgpack массива \
Expand Down Expand Up @@ -374,7 +374,7 @@ List<UnorderedPerson> persons = routerClient.eval("""
"person",
Arrays.asList(Arrays.asList("==", "pk", 1))
),
new TypeReference<List<List<PersonWithDifferentFieldsOrder>>>() {}
new TypeReference<List<List<UnorderedPerson>>>() {}
).thenApply(
tarantoolResponse -> tarantoolResponse.get() // unwrap TarantoolResponse
.get(0) // get first object from multi return
Expand Down Expand Up @@ -428,29 +428,11 @@ public class TestClass {
@Test
public void test() {
space.select(Arrays.asList(1)).thenApply(
list -> {
var result = new ArrayList<>();

for (var t : list.get()) { // unwrap tuple struct from select response struct
List<?> dataList = t.get(); // unwrap data from tuple struct
Map<String, ?> map = IntStream // create map {key -> value}
.range(0, dataList.size())
.boxed()
.collect(
Collectors.toMap(
(i) -> tupleFormat.get(i).getName(),
dataList::get
)
);
// use jackson mapper to map from Map to Person POJO
// import static io.tarantool.mapping.BaseTarantoolJacksonMapping.objectMapper;
UnorderedPerson person = objectMapper.convertValue(map, UnorderedPerson.class);

result.add(person);
}

return result;
}
list -> TupleMapper.mapToPojoList(
list.get(),
tupleFormat,
UnorderedPerson.class
)
).join();
// [UnorderedPerson{name='artyom', isMarried=true, id=1}]
}
Expand Down Expand Up @@ -485,6 +467,29 @@ person:format({
var space = client.space("person");
```

###### Connector version > 1.5.0

Метаданные могут быть получены из TUPLE_EXT, если метод crud поддерживает TUPLE_EXT формат, или из
metadata ответа crud.

```java
public class TestClass {

@Test
public void test() {
// Формат автоматически передается из CrudResponse.metadata
List<Tuple<List<?>>> tuples = space.select(
Collections.singletonList(Condition.create(EQ, "id", 1))
).join();

// Маппим используя формат из tuple
UnorderedPerson person = TupleMapper.mapToPojo(tuples.get(0), UnorderedPerson.class);
}
}
```

###### Connector version <= 1.5.0

Если у вас версия коннектора, которая не выдает метаданные ответа tarantool/crud,
то можно вызывать методы tarantool/crud напрямую:

Expand Down Expand Up @@ -514,19 +519,8 @@ public class TestClass {
}

for (List<?> tuple : tuples) {
Map<Object, ?> map = IntStream // create map {key -> value}
.range(0, tuple.size())
.boxed()
.collect(
Collectors.toMap(
(i) -> metadata.get(i).getName(),
tuple::get
)
);

// use jackson mapper to map from Map to Person POJO
// import static io.tarantool.mapping.BaseTarantoolJacksonMapping.objectMapper;
UnorderedPerson person = objectMapper.convertValue(map, UnorderedPerson.class);
// use TupleMapper to map from tuple data and format to Person POJO
UnorderedPerson person = TupleMapper.mapToPojo(tuple, metadata, UnorderedPerson.class);

result.add(person);
}
Expand All @@ -545,19 +539,19 @@ IPROTO пакета. Отличие от предыдущего варианта

???+ warning "Важно"

В `crud` версии `1.7.1` функционал возврата формата ответа в отдельном поле IPROTO пакета не
В `crud` версии `1.7.1` функционал возврата формата ответа в отдельном поле IPROTO пакета не
поддерживается.

Воспользуемся Box API клиентом:

```java
public class TestClass {

@Test
public void test() {
// other code

// other code

space.select(Arrays.asList(1))
.thenApply(
selectResponse -> {
Expand All @@ -570,19 +564,9 @@ public class TestClass {
}

for (Tuple<List<?>> tuple : tuples) {
List<io.tarantool.mapping.Field> format = tuple.getFormat();
List<?> data = tuple.get();
Map<Object, ?> map = IntStream
.range(0, data.size())
.boxed()
.collect(
Collectors.toMap(
(i) -> format.get(i).getName(),
data::get
)
);
// use TupleMapper to map tuple with embedded format to POJO
result.add(
objectMapper.convertValue(map, PersonWithDifferentFieldsOrder.class)
TupleMapper.mapToPojo(tuple, UnorderedPerson.class)
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,12 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletionException;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import static org.junit.jupiter.api.Assertions.assertArrayEquals;
Expand Down Expand Up @@ -49,7 +47,6 @@
import org.testcontainers.shaded.com.google.common.base.CaseFormat;

import static io.tarantool.client.box.TarantoolBoxSpace.WITHOUT_ENABLED_FETCH_SCHEMA_OPTION_FOR_TARANTOOL_LESS_3_0_0;
import static io.tarantool.mapping.BaseTarantoolJacksonMapping.objectMapper;
import io.tarantool.client.BaseOptions;
import io.tarantool.client.ClientType;
import io.tarantool.client.Options;
Expand All @@ -69,6 +66,7 @@
import io.tarantool.mapping.SelectResponse;
import io.tarantool.mapping.TarantoolResponse;
import io.tarantool.mapping.Tuple;
import io.tarantool.mapping.TupleMapper;
import io.tarantool.schema.NoSchemaException;
import io.tarantool.schema.Space;
import io.tarantool.schema.TarantoolSchemaFetcher;
Expand Down Expand Up @@ -399,12 +397,8 @@ public void testMappingWithFormat() {

for (Tuple<List<?>> t : list.get()) {
List<io.tarantool.mapping.Field> tupleFormat = formatGetter.apply(t);
List<?> dataList = t.get();
Map<String, ?> map =
IntStream.range(0, dataList.size())
.boxed()
.collect(Collectors.toMap((i) -> tupleFormat.get(i).getName(), dataList::get));
result.add(objectMapper.convertValue(map, PersonWithDifferentFieldsOrder.class));
result.add(
TupleMapper.mapToPojo(t.get(), tupleFormat, PersonWithDifferentFieldsOrder.class));
}
return result;
};
Expand Down
Loading