In Part 1 we discussed design objectives of a data access layer in general, and now we turn to the interface for the operations on a column family. This corresponds to the JDBCOperationsinterface in Spring JDBC, the implementation of which is JDBCTemplate.
Column Family Operations
The Operations object is responsible for providing access to the data source in terms of generic types, which a DAO object can then use to bind to the application domain types.
It should be mentioned here that there are already classes in the Hector project that provide functionality at this level, namely ColumnFamilyTemplate andSuperColumnFamilyTemplate in the me.prettyprint.cassandra.service.templatepackage. The design here is influenced by those ideas, but it is also an attempt to improve on those classes by meeting more of the design objectives discussed in Part 1. Later in this series we will come back to compare the templates provided in Hector with the design and implementation arrived at here.
At the level of a column family, we deal with three generic types: The row key type (K), the column name type (N), and the column value type (V). This is the same nomenclature used for the templates in Hector, and we will stick with this.
We will of course need read, write, and delete operations, but let’s start with the interface definition itself:
Should ColumnFamilyOperations extendKeyspaceOperations?
It just so happens that it is convenient to be able to begin and commit batch operations using a ColumnFamilyOperations so that you don’t necessarily need to have a KeyspaceOperations object around as well. For example, it is perfectly reasonable to do batch operations on a single column family, in which case it would make sense to just use a single DAO for that column family. However, extending KeyspaceOperations is an opportunistic design decision that doesn’t really make sense logically. For example, later there might be operations that are added to KeyspaceOperations that can only be done at the Keyspace level, such aslistColumnFamilies. Then all of a sudden it doesn’t make sense for ColumnFamilyOperations to extend KeyspaceOperations. Therefore, we will simply add the methods from KeyspaceOperations that also make sense for column families, which just happens to be all of them we have so far:
Ideally the TransactionContext would be propagated by an aspect using thread locals so that it would not need to be explicit as a parameter, but this is beyond the scope of this article.
Now it is a matter of adding read, write, and delete operations for working with column families.
Write and Delete Operations
The write and delete operations are fairly straight forward:
We can now take a look at a very simple example of code that shows a batch operation of deleting two rows: