Register Converters for Offset java.time types in JSR310Converters.
We now appropriately handle OffsetDateTime and OffsetTime the same as all other java.time types, supported as simple types on Spring application (persistent) entity classes. Closes #2677
This commit is contained in:
@@ -50,7 +50,7 @@ class RedisRepositoryClusterIntegrationTests extends RedisRepositoryIntegrationT
|
||||
@EnableRedisRepositories(considerNestedRepositories = true, indexConfiguration = MyIndexConfiguration.class,
|
||||
keyspaceConfiguration = MyKeyspaceConfiguration.class,
|
||||
includeFilters = { @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,
|
||||
classes = { PersonRepository.class, CityRepository.class, ImmutableObjectRepository.class }) })
|
||||
classes = { PersonRepository.class, CityRepository.class, ImmutableObjectRepository.class, UserRepository.class }) })
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
@@ -62,6 +62,7 @@ class RedisRepositoryClusterIntegrationTests extends RedisRepositoryIntegrationT
|
||||
connectionFactory.afterPropertiesSet();
|
||||
|
||||
RedisTemplate<byte[], byte[]> template = new RedisTemplate<>();
|
||||
|
||||
template.setConnectionFactory(connectionFactory);
|
||||
|
||||
return template;
|
||||
|
||||
@@ -21,6 +21,8 @@ import lombok.Data;
|
||||
import lombok.Value;
|
||||
import lombok.With;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.OffsetTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -51,6 +53,9 @@ import org.springframework.data.redis.core.index.SimpleIndexDefinition;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
import org.springframework.data.repository.query.QueryByExampleExecutor;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Base for testing Redis repository support in different configurations.
|
||||
@@ -63,6 +68,7 @@ public abstract class RedisRepositoryIntegrationTestBase {
|
||||
@Autowired PersonRepository repo;
|
||||
@Autowired CityRepository cityRepo;
|
||||
@Autowired ImmutableObjectRepository immutableObjectRepo;
|
||||
@Autowired UserRepository userRepository;
|
||||
@Autowired KeyValueTemplate kvTemplate;
|
||||
|
||||
@BeforeEach
|
||||
@@ -474,6 +480,24 @@ public abstract class RedisRepositoryIntegrationTestBase {
|
||||
assertThat(loaded.nested).isEqualTo(nested);
|
||||
}
|
||||
|
||||
@Test // GH-2677
|
||||
void shouldProperlyHandleEntityWithOffsetJavaTimeTypes() {
|
||||
|
||||
User jonDoe = User.as("Jon Doe")
|
||||
.expires(OffsetTime.now().plusMinutes(5))
|
||||
.lastAccess(OffsetDateTime.now());
|
||||
|
||||
this.userRepository.save(jonDoe);
|
||||
|
||||
User loadedJonDoe = this.userRepository.findById(jonDoe.getName()).orElse(null);
|
||||
|
||||
assertThat(loadedJonDoe).isNotNull();
|
||||
assertThat(loadedJonDoe).isNotSameAs(jonDoe);
|
||||
assertThat(loadedJonDoe.getName()).isEqualTo(jonDoe.getName());
|
||||
assertThat(loadedJonDoe.getLastAccessed()).isEqualTo(jonDoe.getLastAccessed());
|
||||
assertThat(loadedJonDoe.getExpiration()).isEqualTo(jonDoe.getExpiration());
|
||||
}
|
||||
|
||||
public static interface PersonRepository
|
||||
extends PagingAndSortingRepository<Person, String>, CrudRepository<Person, String>,
|
||||
QueryByExampleExecutor<Person> {
|
||||
@@ -519,6 +543,8 @@ public abstract class RedisRepositoryIntegrationTestBase {
|
||||
|
||||
public interface ImmutableObjectRepository extends CrudRepository<Immutable, String> {}
|
||||
|
||||
public interface UserRepository extends CrudRepository<User, String> { }
|
||||
|
||||
/**
|
||||
* Custom Redis {@link IndexConfiguration} forcing index of {@link Person#lastname}.
|
||||
*
|
||||
@@ -583,4 +609,72 @@ public abstract class RedisRepositoryIntegrationTestBase {
|
||||
|
||||
Immutable nested;
|
||||
}
|
||||
|
||||
@RedisHash("Users")
|
||||
static class User {
|
||||
|
||||
static User as(@NonNull String name) {
|
||||
Assert.hasText(name, () -> String.format("Name [%s] of User is required", name));
|
||||
return new User(name);
|
||||
}
|
||||
|
||||
private OffsetDateTime lastAccessed;
|
||||
|
||||
private OffsetTime expiration;
|
||||
|
||||
@Id
|
||||
private final String name;
|
||||
|
||||
private User(@NonNull String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public OffsetTime getExpiration() {
|
||||
return this.expiration;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public OffsetDateTime getLastAccessed() {
|
||||
return this.lastAccessed;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public User lastAccess(@Nullable OffsetDateTime dateTime) {
|
||||
this.lastAccessed = dateTime;
|
||||
return this;
|
||||
}
|
||||
|
||||
public User expires(@Nullable OffsetTime time) {
|
||||
this.expiration = time;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(obj instanceof User that)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.getName().equals(that.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,8 +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, ImmutableObjectRepository.class }) })
|
||||
|
||||
classes = { PersonRepository.class, CityRepository.class, ImmutableObjectRepository.class, UserRepository.class }) })
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
@@ -67,6 +66,7 @@ public class RedisRepositoryIntegrationTests extends RedisRepositoryIntegrationT
|
||||
connectionFactory.afterPropertiesSet();
|
||||
|
||||
RedisTemplate<String, String> template = new RedisTemplate<>();
|
||||
|
||||
template.setDefaultSerializer(StringRedisSerializer.UTF_8);
|
||||
template.setConnectionFactory(connectionFactory);
|
||||
|
||||
@@ -104,6 +104,7 @@ public class RedisRepositoryIntegrationTests extends RedisRepositoryIntegrationT
|
||||
public void shouldConsiderCustomTypeMapper() {
|
||||
|
||||
Person rand = new Person();
|
||||
|
||||
rand.id = "rand";
|
||||
rand.firstname = "rand";
|
||||
rand.lastname = "al'thor";
|
||||
|
||||
Reference in New Issue
Block a user