Object mappers in DSE drivers
The C#, Java, Node.js, and Python drivers each provide an object mapper. These mappers are tools for generating, executing, and consuming the results of queries.
The object mapper APIs intentionally do not implement all the CQL features. The mapper APIs differ for each language, as each language requires a different set of patterns. Examine the API documentation for each language to make sure it fits with your application.
The following concepts are common across the mapper APIs:
A model class is a class that represents am Apache Cassandra™ or DSE table. These classes have member variables that map to columns in that table.
Instances of model classes are data objects.
In the C# object mapper, model classes are normal classes with setters and getters, also known as plain old CLR objects (POCOs).
By default, the mapper automatically discovers the object member to DSE column name mapping.
The mapping can also be explicitly configured by using the
Because model classes are POCOs, all queries must be mediated by the mapper object.
Session instances and provide methods, such as
Fetch, that execute statements and define the types into which the mapper reads data.
Similarly, mappers provide methods, such as
Update, that take in a data object and use it to generate a write statement.
All of these methods are generic and can take a parameterized query and arguments or a data object.
By default, writing null values deletes or unsets the corresponding value in the database.
Writing null values creates tombstones that can impact query performance and the overall health of the database.
Writing nulls can be controlled on a per-operation basis by setting insertNulls when using the
The C# driver also includes a C# LINQ API available that will not be covered in detail in this guide.
The Java 3.x mapper relies on annotated classes that are processed at runtime using reflection. Model classes are created by annotating classes with @Table. By default, the mapper automatically discovers the object member to DSE column name mapping. The mapping can also be explicitly configured using the @Column annotation.
To execute queries with the mapper, create a data object that defines the query and pass it using CRUD operations on the mapper. For read queries, the data object arguments are used as filters on the Cassandra or DSE columns. If custom queries are needed, the mapper extends functionality via Accessors. It is also possible to map regular ResultSets to data objects. For write requests, the data object values are used as values in the insert query.
By default, writing null values deletes or unsets the corresponding value in the database. Writing null values creates tombstones that can impact query performance and the overall health of the database. Writing nulls can be controlled by default or on a per-operation basis by setting the saveNullFields option.
The Java 4.x mapper, like the 3.x mapper, relies on annotations to configure mapped entities and queries. However, there are a few notable differences:
It uses compile-time annotation processing instead of runtime reflection.
The “mapper” and “accessor” concepts have been unified into a single “DAO” component, that handles both pre-defined CRUD patterns and user-provided queries.
See the driver manual for more on enabling annotation processor hooks.
Model classes are created by annotating classes with @Entity. The mapper automatically discovers the object member to DSE column name mapping using the default NamingConvention. The default mapping can be changed by specifying a different naming convention with the @NamingStrategy annotation, or by providing your own implementation of NameConverter (not both). In addition, you can override entity and column name mappings individually with the @CqlName annotation.
Once your Entities are designed, you will need to create Data Access Object (DAO) interfaces annotated with @Dao. Your DAOs should define all needed query methods, each marked with the appropriate query annotation for performing your CRUD operations.
Executing queries requires an instance of a DAO, which you can get from the mapper. For each DAO, your mapper interface should define a DaoFactory method. An instance of a mapper can be obtained from the auto-generated Mapper Builder. Simply build an instance of the mapper from the mapper builder and invoke the desired DaoFactory method to get an instance of a DAO. From the DAO, invoke your desired query method to execute the query.
By default, writing null values will not delete or unset the corresponding value in the database. Writing null values creates tombstones that can impact query performance and the overall health of the database. You can change this behavior by specifying a different NullSavingStrategy in the @DefaultNullSavingStrategy annotation at the DAO level, specific query methods, or both if you want some query methods of a DAO to have a different strategy than the rest.
For details on the Node.js object mapper, see this DataStax Academy blog post.
For the Python object mapper, model classes are created by sub-classing cassandra.cqlengine.model.Model.
By default, the mapper automatically discovers the mapping of object attributes created from
cassandra.cqlengine.columns.Column to DSE column names.
This mapping can also be explicitly defined using the db_field kwarg to Column subclass initializers.
It is safest to create the tables for model objects outside the scope of the mapper, though the Python driver does allow for making schema changes with the object mapper. Creating tables within the mapper can result in concurrent schema modifications, which are not recommended.
The Python mapper provides class methods for reading and writing data objects. In addition, queries can be executed by directly calling methods on the model class. The mapper read query methods return collections of data objects that have instance methods for CRUD operations.
Mapper connections are maintained in a connection registry that can be used to access the sessions that connect to the database.