博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Cassandra 的Custom Codecs
阅读量:5314 次
发布时间:2019-06-14

本文共 7622 字,大约阅读时间需要 25 分钟。

mapper可以利用自定义编解码器将自定义转换映射到 columns和fields.

Declaring codecs

假定有一张表,含有timestamp column:

create table user(id int primary key, birth timestamp);

还create了一个custom class, 一个codec 来 vonvert it:

public class MyCustomDate { ... }public class MyCustomDateCodec extends TypeCodec
{ public MyCustomDate() { super(DataType.timestamp(), MyCustomDate.class); } ...}

 

Pre-registered codecs

如果你register codec with the mapper's underlying Cluster, it will be automatically available to the mapper:

Cluster cluster = Cluster.builder()    .addContactPoint("127.0.0.1")    .withCodecRegistry(        new CodecRegistry().register(new MyCustomDateCodec())    ).build();MappingManager mappingManager = new MappingManager(cluster.connect());

你可以正常的使用自定义的type来  create mapped类, 而不需要额外的配置:

@Table(name = "user")public class User {  @PartitionKey  private int id;  private MyCustomDate birth;  ... // getters and setters}

 

This also works in accessors:

@Accessorinterface UserAccessor {  @Query("update user set birth = :b where id = :i")  void updateBirth(@Param("i") int id,                   @Param("b") MyCustomDate birth);}

 

One-time declaration

有时只需要在指定的column/field上使用codec, Cluster初始化时不需要register:

Cluster cluster = Cluster.builder()    .addContactPoint("127.0.0.1")    .build();MappingManager mappingManager = new MappingManager(cluster.connect());

 

@Column注解就起到作用了

@Table(name = "user")public class User {  @PartitionKey  private int id;  @Column(codec = MyCustomDateCodec.class)  private MyCustomDate birth;  ... // getters and setters}

The class must have a no-arg constructor. The mapper will create an instance (one per column) and cache it for future use.

This also works with  and  annotations.

 

Implicit UDT codecs

隐式codec

@UDT(name = "address")public class Address { ... }@Entity(name = "user")public class User {  ...  private Address address;  ...}Mapper
userMapper = mappingManager.mapper(User.class);// Codec is now registered for Address <-> CQL address
Row row = session.execute("select address from user where id = 1").one();Address address = row.get("address", Address.class);

If you don't use entity mappers but still want the convenience of the UDT codec for core driver methods, the mapper provides a way to create it independently:

mappingManager.udtCodec(Address.class);// Codec is now registered

 

 

 

 

 

 

 

 

 

分界线, 上面的是使用,下面的是介绍//

Custom codecs支持 transparent, user-configurable mapping of CQL types to arbitrary Java objects.

这种特征的实际用例很多:

  • Ability to map CQL timestamp, date and time columns to Java 8 or Joda Time classes (rather than the built-in mappings for Date,  and Long);
  • Ability to map CQL varchar columns directly to JSON or XML mapped objects (i.e. using frameworks such as Jackson);
  • Ability to map CQL user-defined types to Java objects;
  • Ability to map CQL lists directly to Java arrays;
  • Ability to map CQL collections directly to Scala collections;
  • etc.

Overview of the serialization mechanism 序列化机制概述

序列化机制的中心部分是TypeCodec。

每一个TypeCodec支持 Java type和CQL type 双向映射.  因此TypeCodec能够进行4项基本操作

  •  a Java object into a CQL value;
  •  a CQL value into a Java object;
  •  a Java object into a CQL literal;
  •  a CQL literal into a Java object.

 

Implementing and using custom codecs

有这样一种场景: user有JSON文档store在varchar column, 他希望driver使用 library自动映射此column 为Java对象,而不是返回一个原生的JSON string.

简单的table结构如下

CREATE TABLE t (id int PRIMARY KEY, json VARCHAR);

首先实现一个合适的codec. 使用Jackson, 一个可能的Json codec 如下:

/** * A simple Json codec. */public class JsonCodec
extends TypeCodec
{ private final ObjectMapper objectMapper = new ObjectMapper(); public JsonCodec(Class
javaType) { super(DataType.varchar(), javaType); } @Override public ByteBuffer serialize(T value, ProtocolVersion protocolVersion) throws InvalidTypeException { if (value == null) return null; try { return ByteBuffer.wrap(objectMapper.writeValueAsBytes(value)); } catch (JsonProcessingException e) { throw new InvalidTypeException(e.getMessage(), e); } } @Override @SuppressWarnings("unchecked") public T deserialize(ByteBuffer bytes, ProtocolVersion protocolVersion) throws InvalidTypeException { if (bytes == null) return null; try { byte[] b = new byte[bytes.remaining()]; // always duplicate the ByteBuffer instance before consuming it! bytes.duplicate().get(b); return (T) objectMapper.readValue(b, toJacksonJavaType()); } catch (IOException e) { throw new InvalidTypeException(e.getMessage(), e); } } @Override public String format(T value) throws InvalidTypeException { if (value == null) return "NULL"; String json; try { json = objectMapper.writeValueAsString(value); } catch (IOException e) { throw new InvalidTypeException(e.getMessage(), e); } return '\'' + json.replace("\'", "''") + '\''; } @Override @SuppressWarnings("unchecked") public T parse(String value) throws InvalidTypeException { if (value == null || value.isEmpty() || value.equalsIgnoreCase("NULL")) return null; if (value.charAt(0) != '\'' || value.charAt(value.length() - 1) != '\'') throw new InvalidTypeException("JSON strings must be enclosed by single quotes"); String json = value.substring(1, value.length() - 1).replace("''", "'"); try { return (T) objectMapper.readValue(json, toJacksonJavaType()); } catch (IOException e) { throw new InvalidTypeException(e.getMessage(), e); } } protected JavaType toJacksonJavaType() { return TypeFactory.defaultInstance().constructType(getJavaType().getType()); }}

 

几个实施指南:

  • Your codecs should be thread-safe, or better yet, immutable;
  • Your codecs should be fast: do not forget that codecs are executed often and are usually very "hot" pieces of code;
  • Your codecs should never block.

接下来register你的codec with CodecRegistry实例

JsonCodec
myJsonCodec = new JsonCodec
(MyPojo.class);CodecRegistry myCodecRegistry = cluster.getConfiguration().getCodecRegistry();myCodecRegistry.register(myJsonCodec);

Cluster's CodecRegistry 是最简单的方式, Cluster实例默认使用CodecRegistry.DEFAULT_INSTANCE,对大多数用来说已经够用.

然而,我们还是可以create一个使用不同CodecRegistry的cluster

CodecRegistry myCodecRegistry = new CodecRegistry();Cluster cluster = new Cluster.builder().withCodecRegistry(myCodecRegistry).build();

Note:新的CodecRegistry,会自动register所有默认的codecs.

 

Cluster cluster = ...Session session = ...MyPojo myPojo = ...// Using SimpleStatementStatement stmt = new SimpleStatement("INSERT INTO t (id, json) VALUES (?, ?)", 42, myPojo));// Using the Query BuilderBuiltStatement insertStmt = QueryBuilder.insertInto("t")    .value("id", 42)    .value("json", myPojo);// Using BoundStatementsPreparedStatement ps = session.prepare("INSERT INTO t (id, json) VALUES (?, ?)");BoundStatement bs1 = ps.bind(42, myPojo); // or alternatively...BoundStatement bs2 = ps.bind()    .setInt(0, 42)    .set(1, myPojo, MyPojo.class);

 

And here is how to retrieve a MyPojo object converted from a JSON document:

ResultSet rs = session.execute(...);Row row = rs.one();// Let the driver convert the string for you...MyPojo myPojo = row.get(1, MyPojo.class);// ... or retrieve the raw string if you need itString json = row.get(1, String.class); // row.getString(1) would have worked too

 

....

https://github.com/datastax/java-driver/tree/3.x/manual/custom_codecs

 

转载于:https://www.cnblogs.com/tianyuxieshen/p/6273935.html

你可能感兴趣的文章
【codeforces 534B】Covered Path
查看>>
给图片添加标签
查看>>
1413确定进制
查看>>
linux 压缩文件的命令总结
查看>>
Mac上Homebrew的使用 (Homebrew 使 OS X 更完整)
查看>>
ProSolid下的遍历访问封装代码
查看>>
添加ASP.NET网站资源文件夹
查看>>
我们是如何通过全球第一免费开源ERP Odoo做到项目100%交付
查看>>
httpModules 与 httpHandlers
查看>>
本机Font字体
查看>>
html常用标签(form标签)
查看>>
综合练习:词频统计
查看>>
从服务器上的数据库备份到本地
查看>>
Tabcontrol动态添加TabPage(获取或设置当前选项卡及其属性)
查看>>
面象对象设计原则之六:迪米特原则(LeastKnowledge Principle, LKP)
查看>>
LeetCode Algorithm 03_Longest Substring Without Repeating Characters
查看>>
常见浏览器兼容性问题与解决方案?
查看>>
2016福州大学软件工程第四次团队作业-系统设计成绩汇总
查看>>
Codeforces 924D Contact ATC (看题解)
查看>>
Codeforces 173E Camping Groups 线段树
查看>>