DATAREDIS-849 - Add support for immutable objects.
We now support immutable objects for saving (e.g. object without a provided Id) and loading (i.e. persistence constructor declares a subset of properties). New instances are created using wither methods/Kotlin copy(…) methods if an immutable object requires association with an Id. Association of the Id to its object moved from RedisKeyValueAdapter to RedisKeyValueTemplate.
This commit is contained in:
committed by
Oliver Gierke
parent
3defab118e
commit
322cfabb17
@@ -19,8 +19,10 @@ import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.hamcrest.number.IsCloseTo.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Wither;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -805,6 +807,33 @@ public class RedisKeyValueTemplateTests {
|
||||
assertThat(target.get().ttl, is(-1L));
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-849
|
||||
public void shouldWriteImmutableType() {
|
||||
|
||||
ImmutableObject source = new ImmutableObject().withValue("foo").withTtl(1234L);
|
||||
|
||||
ImmutableObject inserted = template.insert(source);
|
||||
|
||||
assertThat(source.id, is(nullValue()));
|
||||
assertThat(inserted.id, is(notNullValue()));
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-849
|
||||
public void shouldReadImmutableType() {
|
||||
|
||||
ImmutableObject source = new ImmutableObject().withValue("foo").withTtl(1234L);
|
||||
ImmutableObject inserted = template.insert(source);
|
||||
|
||||
Optional<ImmutableObject> loaded = template.findById(inserted.id, ImmutableObject.class);
|
||||
|
||||
assertThat(loaded.isPresent(), is(true));
|
||||
|
||||
ImmutableObject immutableObject = loaded.get();
|
||||
assertThat(immutableObject.id, is(inserted.id));
|
||||
assertThat(immutableObject.ttl, is(notNullValue()));
|
||||
assertThat(immutableObject.value, is(inserted.value));
|
||||
}
|
||||
|
||||
@EqualsAndHashCode
|
||||
@RedisHash("template-test-type-mapping")
|
||||
static class VariousTypes {
|
||||
@@ -929,4 +958,20 @@ public class RedisKeyValueTemplateTests {
|
||||
String value;
|
||||
@TimeToLive int ttl;
|
||||
}
|
||||
|
||||
@Data
|
||||
@Wither
|
||||
@AllArgsConstructor
|
||||
static class ImmutableObject {
|
||||
|
||||
final @Id String id;
|
||||
final String value;
|
||||
final @TimeToLive Long ttl;
|
||||
|
||||
ImmutableObject() {
|
||||
this.id = null;
|
||||
this.value = null;
|
||||
this.ttl = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ public class RedisRepositoryClusterIntegrationTests extends RedisRepositoryInteg
|
||||
@EnableRedisRepositories(considerNestedRepositories = true, indexConfiguration = MyIndexConfiguration.class,
|
||||
keyspaceConfiguration = MyKeyspaceConfiguration.class,
|
||||
includeFilters = { @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,
|
||||
classes = { PersonRepository.class, CityRepository.class }) })
|
||||
classes = { PersonRepository.class, CityRepository.class, ImmutableObjectRepository.class }) })
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -19,6 +19,8 @@ import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.Value;
|
||||
import lombok.experimental.Wither;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@@ -60,6 +62,7 @@ public abstract class RedisRepositoryIntegrationTestBase {
|
||||
|
||||
@Autowired PersonRepository repo;
|
||||
@Autowired CityRepository cityRepo;
|
||||
@Autowired ImmutableObjectRepository immutableObjectRepo;
|
||||
@Autowired KeyValueTemplate kvTemplate;
|
||||
|
||||
@Before
|
||||
@@ -403,6 +406,37 @@ public abstract class RedisRepositoryIntegrationTestBase {
|
||||
assertThat(result, not(hasItems(p1)));
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-849
|
||||
public void shouldReturnNewObjectInstanceOnImmutableSave() {
|
||||
|
||||
Immutable object = new Immutable(null, "Walter", new Immutable("heisenberg", "White", null));
|
||||
Immutable saved = immutableObjectRepo.save(object);
|
||||
|
||||
assertThat(object.id, is(nullValue()));
|
||||
assertThat(saved.id, is(notNullValue()));
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-849
|
||||
public void shouldReturnNewObjectInstanceOnImmutableSaveAll() {
|
||||
|
||||
Immutable object = new Immutable(null, "Walter", new Immutable("heisenberg", "White", null));
|
||||
List<Immutable> saved = (List) immutableObjectRepo.saveAll(Collections.singleton(object));
|
||||
|
||||
assertThat(object.id, is(nullValue()));
|
||||
assertThat(saved.get(0).id, is(notNullValue()));
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-849
|
||||
public void shouldProperlyReadNestedImmutableObject() {
|
||||
|
||||
Immutable nested = new Immutable("heisenberg", "White", null);
|
||||
Immutable object = new Immutable(null, "Walter", nested);
|
||||
Immutable saved = immutableObjectRepo.save(object);
|
||||
|
||||
Immutable loaded = immutableObjectRepo.findById(saved.id).get();
|
||||
assertThat(loaded.nested, is(nested));
|
||||
}
|
||||
|
||||
public static interface PersonRepository
|
||||
extends PagingAndSortingRepository<Person, String>, QueryByExampleExecutor<Person> {
|
||||
|
||||
@@ -434,11 +468,13 @@ public abstract class RedisRepositoryIntegrationTestBase {
|
||||
<S extends Person> List<S> findAll(Example<S> example);
|
||||
}
|
||||
|
||||
public static interface CityRepository extends CrudRepository<City, String> {
|
||||
public interface CityRepository extends CrudRepository<City, String> {
|
||||
|
||||
List<City> findByLocationNear(Point point, Distance distance);
|
||||
}
|
||||
|
||||
public interface ImmutableObjectRepository extends CrudRepository<Immutable, String> {}
|
||||
|
||||
/**
|
||||
* Custom Redis {@link IndexConfiguration} forcing index of {@link Person#lastname}.
|
||||
*
|
||||
@@ -493,4 +529,14 @@ public abstract class RedisRepositoryIntegrationTestBase {
|
||||
|
||||
@GeoIndexed Point location;
|
||||
}
|
||||
|
||||
@Value
|
||||
@Wither
|
||||
public static class Immutable {
|
||||
|
||||
@Id String id;
|
||||
String name;
|
||||
|
||||
Immutable nested;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ public class RedisRepositoryIntegrationTests extends RedisRepositoryIntegrationT
|
||||
@EnableRedisRepositories(considerNestedRepositories = true, indexConfiguration = MyIndexConfiguration.class,
|
||||
keyspaceConfiguration = MyKeyspaceConfiguration.class,
|
||||
includeFilters = { @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,
|
||||
classes = { PersonRepository.class, CityRepository.class }) })
|
||||
classes = { PersonRepository.class, CityRepository.class, ImmutableObjectRepository.class }) })
|
||||
|
||||
static class Config {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user