Forked from mp911de/CassandraZoneddatetimeApplication.java
Created
March 1, 2017 21:46
-
-
Save michelzanini/42f50187775ce575ae1ff46b0baca1a0 to your computer and use it in GitHub Desktop.
Using ZonedDateTime with Spring Data Cassandra stored in tuples.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
spring.data.cassandra.keyspace-name=example |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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