|
19 | 19 | import static org.springframework.data.cassandra.core.mapping.BasicMapId.*; |
20 | 20 | import static org.springframework.data.cassandra.test.util.RowMockUtil.*; |
21 | 21 |
|
| 22 | +import com.carrotsearch.hppc.mutables.DoubleHolder; |
22 | 23 | import lombok.AllArgsConstructor; |
23 | 24 | import lombok.Data; |
24 | 25 | import lombok.EqualsAndHashCode; |
25 | 26 | import lombok.NoArgsConstructor; |
26 | 27 | import lombok.RequiredArgsConstructor; |
27 | 28 | import lombok.ToString; |
28 | 29 |
|
| 30 | +import java.awt.print.Book; |
29 | 31 | import java.io.Serializable; |
30 | 32 | import java.math.BigDecimal; |
31 | 33 | import java.math.BigInteger; |
32 | 34 | import java.net.InetAddress; |
33 | 35 | import java.net.UnknownHostException; |
| 36 | +import java.nio.ByteBuffer; |
34 | 37 | import java.time.Instant; |
35 | 38 | import java.time.LocalDate; |
36 | 39 | import java.time.LocalDateTime; |
|
49 | 52 | import java.util.Set; |
50 | 53 | import java.util.UUID; |
51 | 54 |
|
| 55 | +import org.assertj.core.data.Percentage; |
52 | 56 | import org.json.simple.JSONObject; |
53 | 57 | import org.json.simple.parser.JSONParser; |
54 | 58 | import org.json.simple.parser.ParseException; |
55 | 59 | import org.junit.jupiter.api.BeforeEach; |
56 | 60 | import org.junit.jupiter.api.Test; |
| 61 | + |
| 62 | +import org.springframework.beans.DirectFieldAccessor; |
57 | 63 | import org.springframework.beans.factory.annotation.Value; |
58 | 64 | import org.springframework.core.convert.converter.Converter; |
59 | 65 | import org.springframework.data.annotation.Id; |
|
82 | 88 | import org.springframework.data.cassandra.domain.UserToken; |
83 | 89 | import org.springframework.data.cassandra.support.UserDefinedTypeBuilder; |
84 | 90 | import org.springframework.data.cassandra.test.util.RowMockUtil; |
| 91 | +import org.springframework.data.convert.ReadingConverter; |
| 92 | +import org.springframework.data.convert.SimplePropertyValueConversions; |
| 93 | +import org.springframework.data.convert.ValueConverter; |
85 | 94 | import org.springframework.data.projection.EntityProjection; |
86 | 95 | import org.springframework.data.projection.EntityProjectionIntrospector; |
87 | 96 | import org.springframework.data.projection.SpelAwareProxyProjectionFactory; |
@@ -110,9 +119,13 @@ public class MappingCassandraConverterUnitTests { |
110 | 119 | @BeforeEach |
111 | 120 | void setUp() { |
112 | 121 |
|
| 122 | + CassandraCustomConversions conversions = new CassandraCustomConversions( |
| 123 | + List.of(new ByteBufferToDoubleHolderConverter())); |
113 | 124 | this.mappingContext = new CassandraMappingContext(); |
| 125 | + this.mappingContext.setSimpleTypeHolder(conversions.getSimpleTypeHolder()); |
114 | 126 |
|
115 | 127 | this.mappingCassandraConverter = new MappingCassandraConverter(mappingContext); |
| 128 | + this.mappingCassandraConverter.setCustomConversions(conversions); |
116 | 129 | this.mappingCassandraConverter.afterPropertiesSet(); |
117 | 130 | } |
118 | 131 |
|
@@ -1012,6 +1025,27 @@ void shouldCreateDtoProjectionsThroughConstructor() { |
1012 | 1025 | assertThat(result.getTuple().one).isEqualTo("One"); |
1013 | 1026 | } |
1014 | 1027 |
|
| 1028 | + @Test // GH-1472 |
| 1029 | + void projectShouldReadDtoProjectionPropertiesOnlyOnce() { |
| 1030 | + |
| 1031 | + ByteBuffer number = ByteBuffer.allocate(8); |
| 1032 | + number.putDouble(1.2d); |
| 1033 | + number.flip(); |
| 1034 | + |
| 1035 | + rowMock = RowMockUtil.newRowMock(RowMockUtil.column("number", number, DataTypes.BLOB)); |
| 1036 | + |
| 1037 | + EntityProjectionIntrospector introspector = EntityProjectionIntrospector.create( |
| 1038 | + new SpelAwareProxyProjectionFactory(), EntityProjectionIntrospector.ProjectionPredicate.typeHierarchy(), |
| 1039 | + this.mappingContext); |
| 1040 | + |
| 1041 | + EntityProjection<DoubleHolderDto, WithDoubleHolder> projection = introspector.introspect(DoubleHolderDto.class, |
| 1042 | + WithDoubleHolder.class); |
| 1043 | + |
| 1044 | + DoubleHolderDto result = this.mappingCassandraConverter.project(projection, rowMock); |
| 1045 | + |
| 1046 | + assertThat(result.number.number).isCloseTo(1.2, Percentage.withPercentage(1)); |
| 1047 | + } |
| 1048 | + |
1015 | 1049 | private static List<Object> getValues(Map<CqlIdentifier, Object> statement) { |
1016 | 1050 | return new ArrayList<>(statement.values()); |
1017 | 1051 | } |
@@ -1522,4 +1556,29 @@ static class Author { |
1522 | 1556 | String lastName; |
1523 | 1557 |
|
1524 | 1558 | } |
| 1559 | + |
| 1560 | + @ReadingConverter |
| 1561 | + static class ByteBufferToDoubleHolderConverter implements Converter<ByteBuffer, DoubleHolder> { |
| 1562 | + |
| 1563 | + @Override |
| 1564 | + public DoubleHolder convert(ByteBuffer source) { |
| 1565 | + return new DoubleHolder(source.getDouble()); |
| 1566 | + } |
| 1567 | + } |
| 1568 | + |
| 1569 | + record DoubleHolder(double number) { |
| 1570 | + |
| 1571 | + } |
| 1572 | + |
| 1573 | + static class WithDoubleHolder { |
| 1574 | + DoubleHolder number; |
| 1575 | + } |
| 1576 | + |
| 1577 | + static class DoubleHolderDto { |
| 1578 | + DoubleHolder number; |
| 1579 | + |
| 1580 | + public DoubleHolderDto(DoubleHolder number) { |
| 1581 | + this.number = number; |
| 1582 | + } |
| 1583 | + } |
1525 | 1584 | } |
0 commit comments