Skip to content

Instantly share code, notes, and snippets.

@mp911de
Created February 28, 2017 17:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save mp911de/f8c06dfb12098d1fd7d9eab8167d6d74 to your computer and use it in GitHub Desktop.
Save mp911de/f8c06dfb12098d1fd7d9eab8167d6d74 to your computer and use it in GitHub Desktop.
Using ZonedDateTime with Spring Data Cassandra stored in tuples.
spring.data.cassandra.keyspace-name=example
package com.example;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import java.time.ZonedDateTime;
import java.util.List;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Import;
import org.springframework.data.annotation.Id;
import org.springframework.data.cassandra.core.CassandraOperations;
import org.springframework.data.cassandra.mapping.Table;
import com.datastax.driver.core.Row;
@SpringBootApplication
@Import(MyConfig.class)
@RequiredArgsConstructor
public class CassandraZoneddatetimeApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(CassandraZoneddatetimeApplication.class, args);
}
private final CassandraOperations cassandraOperations;
@Override
public void run(String... strings) throws Exception {
cassandraOperations.execute("DROP TABLE IF EXISTS myentity;");
cassandraOperations.execute("CREATE TABLE myentity (id text PRIMARY KEY, zonedDateTime tuple<timestamp,text>);");
MyEntity entity = new MyEntity("foo", ZonedDateTime.parse("2007-12-03T10:15:30+01:00[Europe/Paris]"));
cassandraOperations.insert(entity);
List<Row> rows = cassandraOperations.select("SELECT * FROM myentity WHERE id = 'foo';", Row.class);
for (Row row : rows) {
System.out.println(row.getObject(0) + " - " + row.getObject(1));
}
List<MyEntity> myEntities = cassandraOperations.select("SELECT * FROM myentity WHERE id = 'foo';", MyEntity.class);
System.out.println(myEntities);
}
@AllArgsConstructor
@NoArgsConstructor
@Data
@Table
static class MyEntity {
@Id private String id;
private ZonedDateTime zonedDateTime;
}
}
package com.example;
import lombok.AllArgsConstructor;
import java.sql.Date;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.Arrays;
import java.util.List;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
import org.springframework.boot.autoconfigure.cassandra.CassandraProperties;
import org.springframework.boot.autoconfigure.domain.EntityScanPackages;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.cassandra.config.CassandraEntityClassScanner;
import org.springframework.data.cassandra.convert.CassandraConverter;
import org.springframework.data.cassandra.convert.CustomConversions;
import org.springframework.data.cassandra.convert.MappingCassandraConverter;
import org.springframework.data.cassandra.mapping.BasicCassandraMappingContext;
import org.springframework.data.cassandra.mapping.CassandraMappingContext;
import org.springframework.data.cassandra.mapping.CassandraPersistentProperty;
import org.springframework.data.cassandra.mapping.SimpleUserTypeResolver;
import org.springframework.data.convert.ReadingConverter;
import org.springframework.data.convert.WritingConverter;
import org.springframework.util.StringUtils;
import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.CodecRegistry;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.ProtocolVersion;
import com.datastax.driver.core.TupleType;
import com.datastax.driver.core.TupleValue;
/**
* @author Mark Paluch
*/
@Configuration
@AllArgsConstructor
public class MyConfig {
private final BeanFactory beanFactory;
private final CassandraProperties properties;
@Bean
CustomConversions customConversions() {
return new CustomConversions(
Arrays.asList(TupleToZonedDateTimeConverter.INSTANCE, ZonedDateTimeToTupleConverter.INSTANCE));
}
@Bean
public CassandraMappingContext cassandraMapping(Cluster cluster, CustomConversions customConversions)
throws ClassNotFoundException {
BasicCassandraMappingContext context = new BasicCassandraMappingContext() {
@Override
public DataType getDataType(CassandraPersistentProperty property) {
if (property.getType().equals(ZonedDateTime.class)) {
return ZonedDateTimeToTupleConverter.type;
}
return super.getDataType(property);
}
};
context.setCustomConversions(customConversions);
List<String> packages = EntityScanPackages.get(this.beanFactory).getPackageNames();
if (packages.isEmpty() && AutoConfigurationPackages.has(this.beanFactory)) {
packages = AutoConfigurationPackages.get(this.beanFactory);
}
if (!packages.isEmpty()) {
context.setInitialEntitySet(CassandraEntityClassScanner.scan(packages));
}
if (StringUtils.hasText(this.properties.getKeyspaceName())) {
context.setUserTypeResolver(new SimpleUserTypeResolver(cluster, this.properties.getKeyspaceName()));
}
return context;
}
@Bean
public CassandraConverter cassandraConverter(CassandraMappingContext mapping, CustomConversions customConversions) {
MappingCassandraConverter mappingCassandraConverter = new MappingCassandraConverter(mapping);
mappingCassandraConverter.setCustomConversions(customConversions);
return mappingCassandraConverter;
}
@ReadingConverter
static enum TupleToZonedDateTimeConverter implements Converter<TupleValue, ZonedDateTime> {
INSTANCE;
@Override
public ZonedDateTime convert(TupleValue source) {
java.util.Date timestamp = source.getTimestamp(0);
ZoneId zoneId = ZoneId.of(source.getString(1));
return timestamp.toInstant().atZone(zoneId);
}
}
@WritingConverter
static enum ZonedDateTimeToTupleConverter implements Converter<ZonedDateTime, TupleValue> {
INSTANCE;
final static TupleType type = TupleType.of(ProtocolVersion.NEWEST_SUPPORTED, CodecRegistry.DEFAULT_INSTANCE,
DataType.timestamp(), DataType.text());
@Override
public TupleValue convert(ZonedDateTime source) {
TupleValue tupleValue = type.newValue();
tupleValue.setTimestamp(0, Date.from(source.toLocalDateTime().toInstant(ZoneOffset.UTC)));
tupleValue.setString(1, source.getZone().toString());
return tupleValue;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment