| <!-- |
| 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. |
| --> |
| |
| ## Mapper |
| |
| The mapper generates the boilerplate to execute queries and convert the results into |
| application-level objects. |
| |
| It is published as two artifacts: `org.apache.cassandra:java-driver-mapper-processor` and |
| `org.apache.cassandra:java-driver-mapper-runtime`. See [Integration](config/) for detailed instructions |
| for different build tools. |
| |
| ### Quick start |
| |
| For a quick overview of mapper features, we are going to build a trivial example based on the |
| following schema: |
| |
| ``` |
| CREATE KEYSPACE inventory |
| WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1}; |
| |
| CREATE TABLE inventory.product(id uuid PRIMARY KEY, description text); |
| ``` |
| |
| #### Entity class |
| |
| This is a simple data container that will represent a row in the `product` table: |
| |
| ```java |
| import com.datastax.oss.driver.api.mapper.annotations.Entity; |
| import com.datastax.oss.driver.api.mapper.annotations.PartitionKey; |
| |
| @Entity |
| public class Product { |
| |
| @PartitionKey private UUID id; |
| private String description; |
| |
| public Product() {} |
| |
| public Product(UUID id, String description) { |
| this.id = id; |
| this.description = description; |
| } |
| |
| public UUID getId() { return id; } |
| |
| public void setId(UUID id) { this.id = id; } |
| |
| public String getDescription() { return description; } |
| |
| public void setDescription(String description) { this.description = description; } |
| } |
| ``` |
| |
| Entity classes must have a no-arg constructor; note that, because we also have a constructor that |
| takes all the fields, we have to define the no-arg constructor explicitly. |
| |
| We use mapper annotations to mark the class as an entity, and indicate which field(s) correspond to |
| the primary key. |
| |
| More annotations are available; for more details, see [Entities](entities/). |
| |
| #### DAO interface |
| |
| A DAO defines a set of query methods: |
| |
| ```java |
| import com.datastax.oss.driver.api.mapper.annotations.Dao; |
| import com.datastax.oss.driver.api.mapper.annotations.Delete; |
| import com.datastax.oss.driver.api.mapper.annotations.Insert; |
| import com.datastax.oss.driver.api.mapper.annotations.Select; |
| |
| @Dao |
| public interface ProductDao { |
| @Select |
| Product findById(UUID productId); |
| |
| @Insert |
| void save(Product product); |
| |
| @Delete |
| void delete(Product product); |
| } |
| ``` |
| |
| Again, mapper annotations are used to mark the interface, and indicate what kind of request each |
| method should execute. You can probably guess what they are in this example. |
| |
| For the full list of available query types, see [DAOs](daos/). |
| |
| #### Mapper interface |
| |
| This is the top-level entry point to mapper features, that allows you to obtain DAO instances: |
| |
| ```java |
| import com.datastax.oss.driver.api.mapper.annotations.DaoFactory; |
| import com.datastax.oss.driver.api.mapper.annotations.DaoKeyspace; |
| import com.datastax.oss.driver.api.mapper.annotations.Mapper; |
| |
| @Mapper |
| public interface InventoryMapper { |
| @DaoFactory |
| ProductDao productDao(@DaoKeyspace CqlIdentifier keyspace); |
| } |
| ``` |
| |
| For more details, see [Mapper](mapper/). |
| |
| #### Generating the code |
| |
| The mapper uses *annotation processing*: it hooks into the Java compiler to analyze annotations, and |
| generate additional classes that implement the mapping logic. Annotation processing is a common |
| technique in modern frameworks, and is generally well supported by build tools and IDEs; this is |
| covered in detail in [Configuring the annotation processor](config/). |
| |
| Pay attention to the compiler output: the mapper processor will sometimes generate warnings if |
| annotations are used incorrectly. |
| |
| #### Using the generated code |
| |
| One of the classes generated during annotation processing is `InventoryMapperBuilder`. It allows you |
| to initialize a mapper instance by wrapping a core driver session: |
| |
| ```java |
| CqlSession session = CqlSession.builder().build(); |
| InventoryMapper inventoryMapper = new InventoryMapperBuilder(session).build(); |
| ``` |
| |
| The mapper should have the same lifecycle as the session in your application: created once at |
| initialization time, then reused. It is thread-safe. |
| |
| From the mapper, you can then obtain a DAO instance and execute queries: |
| |
| ```java |
| ProductDao dao = inventoryMapper.productDao(CqlIdentifier.fromCql("inventory")); |
| dao.save(new Product(UUID.randomUUID(), "Mechanical keyboard")); |
| ``` |
| |
| ### Logging |
| |
| The code generated by the mapper includes logs. They are issued with SLF4J, and can be configured |
| the same way as the [core driver logs](../core/logging/). |
| |
| They can help you figure out which queries the mapper is generating under the hood, for example: |
| |
| ``` |
| DEBUG ProductDaoImpl__MapperGenerated - [s0] Initializing new instance for keyspace = ks_0 and table = null |
| DEBUG ProductHelper__MapperGenerated - [s0] Entity Product will be mapped to ks_0.product |
| DEBUG ProductDaoImpl__MapperGenerated - [s0] Preparing query |
| `SELECT id,description,dimensions FROM ks_0.product WHERE id=:id` |
| for method findById(java.util.UUID) |
| ``` |
| |
| You can decide which logs to enable using the standard SLF4J mechanisms (categories and levels). In |
| addition, if you want no logs at all, it's possible to entirely remove them from the generated code |
| with the Java compiler option `-Acom.datastax.oss.driver.mapper.logs.enabled=false`. |