| <!-- |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| --> |
| |
| # Using custom codecs |
| |
| The mapper can take advantage of [custom codecs](../../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: |
| |
| ```java |
| 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: |
| |
| ```java |
| 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: |
| |
| ```java |
| @Table(name = "user") |
| public class User { |
| @PartitionKey |
| private int id; |
| private MyCustomDate birth; |
| |
| ... // getters and setters |
| } |
| ``` |
| |
| This also works in accessors: |
| |
| ```java |
| @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`: |
| |
| ```java |
| 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][column] |
| annotation: |
| |
| ```java |
| @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][field] and [@Param][param] annotations. |
| |
| [column]:https://docs.datastax.com/en/drivers/java/3.11/com/datastax/driver/mapping/annotations/Column.html |
| [field]:https://docs.datastax.com/en/drivers/java/3.11/com/datastax/driver/mapping/annotations/Field.html |
| [param]:https://docs.datastax.com/en/drivers/java/3.11/com/datastax/driver/mapping/annotations/Param.html |
| |
| |
| ## Implicit UDT codecs |
| |
| The mapper uses custom codecs internally to handle UDT conversions: when |
| you register an [entity](../using/#entity-mappers), the mapper inspects |
| the type of all fields to find classes annotated with |
| [@UDT](../creating/#mapping-user-types) (this works recursively with |
| nested UDTs and collections). For each class, the mapper creates a codec |
| and registers it with the underlying `Cluster`. |
| |
| ```java |
| @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: |
| |
| ```java |
| 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: |
| |
| ```java |
| mappingManager.udtCodec(Address.class); |
| |
| // Codec is now registered |
| ``` |