Skip to content

Commit 00c48ed

Browse files
tomekl007olim7t
authored andcommitted
JAVA-2141: Support null saving strategies
1 parent 1e8a11d commit 00c48ed

30 files changed

Lines changed: 854 additions & 42 deletions

File tree

integration-tests/src/test/java/com/datastax/oss/driver/mapper/InsertIT.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import com.datastax.oss.driver.api.mapper.annotations.Insert;
2828
import com.datastax.oss.driver.api.mapper.annotations.Mapper;
2929
import com.datastax.oss.driver.api.mapper.annotations.Select;
30+
import com.datastax.oss.driver.api.mapper.entity.saving.NullSavingStrategy;
3031
import com.datastax.oss.driver.api.testinfra.CassandraRequirement;
3132
import com.datastax.oss.driver.api.testinfra.ccm.CcmRule;
3233
import com.datastax.oss.driver.api.testinfra.session.SessionRule;
@@ -226,6 +227,34 @@ public void should_insert_entity_if_not_exists_returning_optional_asynchronously
226227
.contains(FLAMETHROWER);
227228
}
228229

230+
@Test
231+
public void should_insert_entity_and_do_not_set_null_field() {
232+
// given
233+
assertThat(dao.findById(FLAMETHROWER.getId())).isNull();
234+
dao.save(FLAMETHROWER);
235+
assertThat(dao.findById(FLAMETHROWER.getId()).getDescription()).isNotNull();
236+
237+
// when
238+
dao.saveDoNotSetNull(new Product(FLAMETHROWER.getId(), null, FLAMETHROWER.getDimensions()));
239+
240+
// then
241+
assertThat(dao.findById(FLAMETHROWER.getId()).getDescription()).isNotNull();
242+
}
243+
244+
@Test
245+
public void should_insert_entity_and_set_null_field() {
246+
// given
247+
assertThat(dao.findById(FLAMETHROWER.getId())).isNull();
248+
dao.save(FLAMETHROWER);
249+
assertThat(dao.findById(FLAMETHROWER.getId()).getDescription()).isNotNull();
250+
251+
// when
252+
dao.saveSetNull(new Product(FLAMETHROWER.getId(), null, FLAMETHROWER.getDimensions()));
253+
254+
// then
255+
assertThat(dao.findById(FLAMETHROWER.getId()).getDescription()).isNull();
256+
}
257+
229258
@Mapper
230259
public interface InventoryMapper {
231260
@DaoFactory
@@ -238,6 +267,12 @@ public interface ProductDao {
238267
@Insert
239268
void save(Product product);
240269

270+
@Insert(nullSavingStrategy = NullSavingStrategy.DO_NOT_SET)
271+
void saveDoNotSetNull(Product product);
272+
273+
@Insert(nullSavingStrategy = NullSavingStrategy.SET_TO_NULL)
274+
void saveSetNull(Product product);
275+
241276
@Insert(timestamp = ":timestamp")
242277
void saveWithBoundTimestamp(Product product, long timestamp);
243278

integration-tests/src/test/java/com/datastax/oss/driver/mapper/NamingStrategyIT.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import com.datastax.oss.driver.api.mapper.annotations.PartitionKey;
3333
import com.datastax.oss.driver.api.mapper.annotations.Select;
3434
import com.datastax.oss.driver.api.mapper.entity.naming.NameConverter;
35+
import com.datastax.oss.driver.api.testinfra.CassandraRequirement;
3536
import com.datastax.oss.driver.api.testinfra.ccm.CcmRule;
3637
import com.datastax.oss.driver.api.testinfra.session.SessionRule;
3738
import com.datastax.oss.driver.categories.ParallelizableTests;
@@ -56,6 +57,7 @@
5657
* <p>See each entity's corresponding table schema in {@link #setup()}.
5758
*/
5859
@Category(ParallelizableTests.class)
60+
@CassandraRequirement(min = "2.2", description = "support for unset values")
5961
public class NamingStrategyIT {
6062

6163
private static CcmRule ccm = CcmRule.getInstance();

integration-tests/src/test/java/com/datastax/oss/driver/mapper/NestedUdtIT.java

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
import com.datastax.oss.driver.api.mapper.annotations.Mapper;
3131
import com.datastax.oss.driver.api.mapper.annotations.PartitionKey;
3232
import com.datastax.oss.driver.api.mapper.annotations.Select;
33+
import com.datastax.oss.driver.api.mapper.entity.saving.NullSavingStrategy;
34+
import com.datastax.oss.driver.api.testinfra.CassandraRequirement;
3335
import com.datastax.oss.driver.api.testinfra.ccm.CcmRule;
3436
import com.datastax.oss.driver.api.testinfra.session.SessionRule;
3537
import com.datastax.oss.driver.categories.ParallelizableTests;
@@ -41,6 +43,7 @@
4143
import java.util.Objects;
4244
import java.util.Set;
4345
import java.util.UUID;
46+
import org.junit.Before;
4447
import org.junit.BeforeClass;
4548
import org.junit.ClassRule;
4649
import org.junit.Test;
@@ -50,6 +53,7 @@
5053

5154
/** Tests that entities with UDTs nested at various levels are properly mapped. */
5255
@Category(ParallelizableTests.class)
56+
@CassandraRequirement(min = "2.2", description = "support for unset values")
5357
public class NestedUdtIT {
5458

5559
private static CcmRule ccm = CcmRule.getInstance();
@@ -58,9 +62,10 @@ public class NestedUdtIT {
5862

5963
@ClassRule public static TestRule chain = RuleChain.outerRule(ccm).around(sessionRule);
6064

65+
private static UUID CONTAINER_ID = UUID.randomUUID();
6166
private static final Container SAMPLE_CONTAINER =
6267
new Container(
63-
UUID.randomUUID(),
68+
CONTAINER_ID,
6469
ImmutableList.of(new Type1("a"), new Type1("b")),
6570
ImmutableMap.of(
6671
"cd",
@@ -73,6 +78,21 @@ public class NestedUdtIT {
7378
ImmutableMap.of(
7479
new Type1("12"), ImmutableMap.of("12", ImmutableSet.of(new Type2(1), new Type2(2)))));
7580

81+
private static final Container SAMPLE_CONTAINER_NULL_LIST =
82+
new Container(
83+
CONTAINER_ID,
84+
null,
85+
ImmutableMap.of(
86+
"cd",
87+
ImmutableList.of(new Type1("c"), new Type1("d")),
88+
"ef",
89+
ImmutableList.of(new Type1("e"), new Type1("f"))),
90+
ImmutableMap.of(
91+
new Type1("12"),
92+
ImmutableSet.of(ImmutableList.of(new Type2(1)), ImmutableList.of(new Type2(2)))),
93+
ImmutableMap.of(
94+
new Type1("12"), ImmutableMap.of("12", ImmutableSet.of(new Type2(1), new Type2(2)))));
95+
7696
private static ContainerDao containerDao;
7797

7898
@BeforeClass
@@ -97,6 +117,15 @@ public static void setup() {
97117
containerDao = udtsMapper.containerDao(sessionRule.keyspace());
98118
}
99119

120+
@Before
121+
public void clearContainerData() {
122+
CqlSession session = sessionRule.session();
123+
session.execute(
124+
SimpleStatement.builder("TRUNCATE container")
125+
.setExecutionProfile(sessionRule.slowProfile())
126+
.build());
127+
}
128+
100129
@Test
101130
public void should_insert_and_retrieve_entity_with_nested_udts() {
102131
// Given
@@ -110,6 +139,38 @@ public void should_insert_and_retrieve_entity_with_nested_udts() {
110139
assertThat(retrievedEntity).isEqualTo(SAMPLE_CONTAINER);
111140
}
112141

142+
@Test
143+
public void should_insert_do_not_set_to_null_udts() {
144+
// Given
145+
CqlSession session = sessionRule.session();
146+
147+
containerDao.save(SAMPLE_CONTAINER);
148+
Container retrievedEntity = containerDao.loadByPk(SAMPLE_CONTAINER.getId());
149+
150+
assertThat(retrievedEntity.list).isNotNull();
151+
152+
// When
153+
containerDao.saveDoNotSetNull(SAMPLE_CONTAINER_NULL_LIST);
154+
Container retrievedEntitySecond = containerDao.loadByPk(SAMPLE_CONTAINER.getId());
155+
assertThat(retrievedEntitySecond.list).isNotNull();
156+
}
157+
158+
@Test
159+
public void should_insert_set_to_null_udts() {
160+
// Given
161+
CqlSession session = sessionRule.session();
162+
163+
containerDao.save(SAMPLE_CONTAINER);
164+
Container retrievedEntity = containerDao.loadByPk(SAMPLE_CONTAINER.getId());
165+
166+
assertThat(retrievedEntity.list).isNotNull();
167+
168+
// When
169+
containerDao.saveSetToNull(SAMPLE_CONTAINER_NULL_LIST);
170+
Container retrievedEntitySecond = containerDao.loadByPk(SAMPLE_CONTAINER.getId());
171+
assertThat(retrievedEntitySecond.list).isEmpty();
172+
}
173+
113174
@Mapper
114175
public interface UdtsMapper {
115176
@DaoFactory
@@ -125,6 +186,12 @@ public interface ContainerDao {
125186
@Insert
126187
void save(Container container);
127188

189+
@Insert(nullSavingStrategy = NullSavingStrategy.DO_NOT_SET)
190+
void saveDoNotSetNull(Container container);
191+
192+
@Insert(nullSavingStrategy = NullSavingStrategy.SET_TO_NULL)
193+
void saveSetToNull(Container container);
194+
128195
@GetEntity
129196
Container get(GettableByName source);
130197
}
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
/*
2+
* Copyright DataStax, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.datastax.oss.driver.mapper;
17+
18+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
19+
20+
import com.datastax.oss.driver.api.core.CqlIdentifier;
21+
import com.datastax.oss.driver.api.core.CqlSession;
22+
import com.datastax.oss.driver.api.core.config.DefaultDriverOption;
23+
import com.datastax.oss.driver.api.core.config.DriverConfigLoader;
24+
import com.datastax.oss.driver.api.core.cql.SimpleStatement;
25+
import com.datastax.oss.driver.api.mapper.annotations.Dao;
26+
import com.datastax.oss.driver.api.mapper.annotations.DaoFactory;
27+
import com.datastax.oss.driver.api.mapper.annotations.DaoKeyspace;
28+
import com.datastax.oss.driver.api.mapper.annotations.Entity;
29+
import com.datastax.oss.driver.api.mapper.annotations.Mapper;
30+
import com.datastax.oss.driver.api.mapper.annotations.PartitionKey;
31+
import com.datastax.oss.driver.api.mapper.annotations.Select;
32+
import com.datastax.oss.driver.api.mapper.annotations.Update;
33+
import com.datastax.oss.driver.api.mapper.entity.saving.NullSavingStrategy;
34+
import com.datastax.oss.driver.api.testinfra.ccm.CcmRule;
35+
import com.datastax.oss.driver.api.testinfra.session.SessionRule;
36+
import com.datastax.oss.driver.categories.ParallelizableTests;
37+
import java.util.Objects;
38+
import java.util.UUID;
39+
import org.junit.BeforeClass;
40+
import org.junit.ClassRule;
41+
import org.junit.Test;
42+
import org.junit.experimental.categories.Category;
43+
import org.junit.rules.RuleChain;
44+
import org.junit.rules.TestRule;
45+
46+
@Category(ParallelizableTests.class)
47+
public class NullSavingStrategyIT {
48+
49+
private static CcmRule ccm = CcmRule.getInstance();
50+
51+
private static SessionRule<CqlSession> sessionRule =
52+
SessionRule.builder(ccm)
53+
.withConfigLoader(
54+
DriverConfigLoader.programmaticBuilder()
55+
.withString(DefaultDriverOption.PROTOCOL_VERSION, "V3")
56+
.build())
57+
.build();
58+
59+
private static InventoryMapper mapper;
60+
61+
@ClassRule public static TestRule chain = RuleChain.outerRule(ccm).around(sessionRule);
62+
63+
@BeforeClass
64+
public static void setup() {
65+
CqlSession session = sessionRule.session();
66+
session.execute(
67+
SimpleStatement.builder(
68+
"CREATE TABLE product_simple(id uuid PRIMARY KEY, description text)")
69+
.setExecutionProfile(sessionRule.slowProfile())
70+
.build());
71+
72+
mapper = new NullSavingStrategyIT_InventoryMapperBuilder(session).build();
73+
}
74+
75+
@Test
76+
public void should_throw_when_try_to_construct_dao_with_DO_NOT_SET_strategy_for_V3_protocol() {
77+
assertThatThrownBy(() -> mapper.productDao(sessionRule.keyspace()))
78+
.isInstanceOf(IllegalArgumentException.class)
79+
.hasMessage("You cannot use NullSavingStrategy.DO_NOT_SET for protocol version V3.");
80+
}
81+
82+
@Mapper
83+
public interface InventoryMapper {
84+
@DaoFactory
85+
ProductSimpleDao productDao(@DaoKeyspace CqlIdentifier keyspace);
86+
}
87+
88+
@Dao
89+
public interface ProductSimpleDao {
90+
91+
@Update(nullSavingStrategy = NullSavingStrategy.DO_NOT_SET)
92+
void update(ProductSimple product);
93+
94+
@Select
95+
ProductSimple findById(UUID productId);
96+
}
97+
98+
@Entity
99+
public static class ProductSimple {
100+
@PartitionKey private UUID id;
101+
private String description;
102+
103+
public ProductSimple() {}
104+
105+
public ProductSimple(UUID id, String description) {
106+
this.id = id;
107+
this.description = description;
108+
}
109+
110+
public UUID getId() {
111+
return id;
112+
}
113+
114+
public void setId(UUID id) {
115+
this.id = id;
116+
}
117+
118+
public String getDescription() {
119+
return description;
120+
}
121+
122+
public void setDescription(String description) {
123+
this.description = description;
124+
}
125+
126+
@Override
127+
public boolean equals(Object o) {
128+
129+
if (this == o) return true;
130+
if (o == null || getClass() != o.getClass()) return false;
131+
ProductSimple that = (ProductSimple) o;
132+
return Objects.equals(id, that.id) && Objects.equals(description, that.description);
133+
}
134+
135+
@Override
136+
public int hashCode() {
137+
return Objects.hash(id, description);
138+
}
139+
140+
@Override
141+
public String toString() {
142+
return "ProductSimple{" + "id=" + id + ", description='" + description + '\'' + '}';
143+
}
144+
}
145+
}

0 commit comments

Comments
 (0)