Skip to content

Latest commit

 

History

History
 
 

custom_codecs

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 

Using custom codecs

The mapper can take advantage of custom codecs to apply custom conversions to mapped columns and fields.

Declaring codecs

Let's assume you have a table containing a timestamp column:

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

You've created a custom class, and the codec to convert it:

public class MyCustomDate { ... }

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

Pre-registered codecs

If you register your 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());

You can normally create your mapped classes using your custom type, without any additional configuration:

@Table(name = "user")
public class User {
  @PartitionKey
  private int id;
  private MyCustomDate birth;

  ... // getters and setters
}

This also works in accessors:

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

One-time declaration

Sometimes you might want to use your codec only for one particular column/field. In that case you won't register it when initializing the Cluster:

Cluster cluster = Cluster.builder()
    .addContactPoint("127.0.0.1")
    .build();

MappingManager mappingManager = new MappingManager(cluster.connect());

Instead, reference the codec's class in the @Column annotation:

@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 @Field and @Param annotations.

Implicit UDT codecs

The mapper uses custom codecs internally to handle UDT conversions: when you register an entity, the mapper inspects the type of all fields to find classes annotated with @UDT (this works recursively with nested UDTs and collections). For each class, the mapper creates a codec and registers it with the underlying Cluster.

@UDT(name = "address")
public class Address { ... }

@Entity(name = "user")
public class User {
  ...
  private Address address;
  ...
}

Mapper<User> userMapper = mappingManager.mapper(User.class);

// Codec is now registered for Address <-> CQL address

A nice side-effect is that you can now use the @UDT-annotated class with any driver method, not just mapper methods:

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