-
Notifications
You must be signed in to change notification settings - Fork 1
Home
Helenus is collection of Scala utilities for Apache Cassandra. Its goal is to make interacting with Cassandra easier, in a type-safe manner, while trying to avoid introducing a complex API.
This wiki covers the Scala 3 version of Helenus. For Scala 2, go here.
Include the library into you project definition:
libraryDependencies += "net.nmoncho" %% "helenus-core" % "1.0.0"
We tried using libraries such as Phantom and Quill, which are great by the way, but they didn't fit entirely our mindset or workflow. We believe the best way to use Cassandra, or any DB for that matter, is to use its Query Language directly.
Helenus takes inspiration from libraries such as Anorm, trying to provide a similar experience by putting CQL first. Our goals are:
- Give users control over the queries that are actually executed.
- Keep the library simple with a concise API.
With this motivation in mind, Helenus builds on top of the concepts defined by the Cassandra Java Driver:
-
PrepareStatement:
The preferred way to define an DML operation (e.g.
SELECT
, orINSERT
). We use a string literal to define an operation. The driver will parse and validate the query. -
BoundStatement:
Once we have a
PreparedStatement
, we can run it against the database by binding all the defined parameters (e.g.?
) -
TypeCodec:
A
TypeCodec
tells the driver how to encode, or decode, a particular JVM type.
Helenus builds on top of these concepts:
- ScalaPreparedStatement: Extends the original
PreparedStatement
statement by introducing helper methods for execution. AScalaPreparedStatement
can be treated as a function, where its input parameters are the bound parameters defined in the statement, and its output as the rows that come out of executing the statement. - ScalaBoundStatement: When a
ScalaPreparedStatement
is executed it will produce aScalaBoundStatement
which carries along the output type defined by the original statement - RowMapper: A
RowMapper
tells Helenus how to extract desired results out of a Row.RowMapper
s can be defined explicitly, or derived implicitly (See Extracting Results) - Adapter: Statements are defined with a sequence of parameters. An
Adapter
tells Helenus how to adapt a complex type, such as case class, to the parameters a statement expects. - Mapping: A
Mapping
brings both anAdapter
and aRowMapper
under the same abstraction. Its goal is to make working with case classes easier.Mapping
s are specially useful when the statement takes more than 22 parameters (e.g. inserting a case class that has more than 22 fields) - ColumnMapper: By default, implicitly derived
RowMapper
s will map columns to fields one-to-one. AColumnMapper
tells Helenus how to convert columns into/from fields in a more controlled fashion. - ColumnNamingScheme: By default, field names are mapped one-to-one to column names (e.g. for a field named
"hotelId"
Helenus will expect a column name"hotelId"
). With an implicitColumnNamingScheme
you can control how this mapping is done. - Pager: A
Pager
let's you query results in a paginated fashion, providing a consistent behavior regardless of how you execute such query. Please read Pagination
With these concepts in mind, let's see how we work with the library.
We can define queries and statements in two ways: as functions, or as interpolated statements.
The main distinction between these two is that with the former we get a ScalaPreparedStatement
which we use as a function to get data in or out of Cassandra, creating a ScalaBoundStatement
in
the process (ie. parameters have to be bound before executing the statement). With the latter we
get directly a ScalaBoundStatement
as parameters are defined at the same moment as the statement
(the statement is still prepared but everything is done in one step).
The Cassandra Java Driver caches PreparedStatement
s, so using an Interpolated Statement won't
prepare the query multiple times.
Statements can be executed in three ways:
- Synchronously
- Asynchronously
- Reactively (e.g. Akka or Pekko Streams)
To learn how to query with Helenus, see Queries and Statements. And for using the asynchronous API, see Queries and Statements (Async).
For documentation on TypeCodec, see Codecs.
For Akka Streams integration, see Akka.
For Flink integration, see Flink.
For Pekko Streams integration, see Pekko.