Scylla Documentation Logo Documentation
  • Server
    • Scylla Open Source
    • Scylla Enterprise
    • Scylla Alternator
  • Cloud
    • Scylla Cloud
    • Scylla Cloud Docs
  • Tools
    • Scylla Manager
    • Scylla Monitoring Stack
    • Scylla Operator
  • Drivers
    • CQL Drivers
    • DynamoDB Drivers
Download
Menu

Caution

You're viewing documentation for a previous version of Scylla Java Driver. Switch to the latest stable version.

Scylla Java Driver Manual Mapper DAOs Query provider methods

Query provider methods¶

Annotate a DAO method with @QueryProvider to delegate the execution of the query to one of your own classes:

@Dao
public interface SensorDao {
  @QueryProvider(providerClass = FindSliceProvider.class, entityHelpers = SensorReading.class)
  PagingIterable<SensorReading> findSlice(int id, Integer month, Integer day);
}

/* Schema:
   CREATE TABLE sensor_reading(sensor_id int, month int, day int, value double,
       PRIMARY KEY (id, month, day)
       WITH CLUSTERING ORDER BY (month DESC, day DESC);
 */

Use this for requests that can’t be expressed as static query strings. For example, we want the month and day parameters above to be optional:

  • if both are present, we query for a particular day: WHERE id = ? AND month = ? AND day = ?

  • if day is null, we query for the whole month: WHERE id = ? AND month = ?

  • if month is also null, we query the whole partition: WHERE id = ?

We assume that you’ve already written a corresponding entity class:

@Entity
public class SensorReading {
  @PartitionKey private int id;
  @ClusteringColumn(1) private int month;
  @ClusteringColumn(2) private int day;
  private double value;
  // constructors, getters and setters omitted for conciseness
}

Provider class¶

@QueryProvider.providerClass() indicates which class to delegate to. The mapper will create one instance for each DAO instance.

This class must expose a constructor that is accessible from the DAO interface’s package.

The first constructor argument must always be MapperContext. This is a utility type that provides access to mapper- and DAO-level state. In particular, this is how you get hold of the session.

If @QueryProvider.entityHelpers() is specified, the constructor must take an additional EntityHelper argument for each provided entity class. We specified SensorReading.class so our argument types are (MapperContext, EntityHelper<SensorReading>).

An entity helper is a utility type generated by the mapper. One thing it can do is construct query templates (with the query builder). We want to retrieve entities so we use selectStart(), chain a first WHERE clause for the id (which is always present), and store the result in a field for later use:

public class FindSliceProvider {
  private final CqlSession session;
  private final EntityHelper<SensorReading> sensorReadingHelper;
  private final Select selectStart;

  public FindSliceProvider(
      MapperContext context, EntityHelper<SensorReading> sensorReadingHelper) {
    this.session = context.getSession();
    this.sensorReadingHelper = sensorReadingHelper;
    this.selectStart =
        sensorReadingHelper.selectStart().whereColumn("id").isEqualTo(bindMarker());
  }
  
  ... // (to be continued)

Provider method¶

@QueryProvider.providerMethod() indicates which method to invoke on the provider class. When it’s not specified (as is our case), it defaults to the same name as the DAO method.

The provider method must be accessible from the DAO interface’s package, and have the same parameters and return type as the DAO method.

Here is the full implementation:

  ... // public class FindSliceProvider (continued)
  
  public PagingIterable<SensorReading> findSlice(int id, Integer month, Integer day) {

    // (1) complete the query
    Select select = this.selectStart;
    if (month != null) {
      select = select.whereColumn("month").isEqualTo(bindMarker());
      if (day != null) {
        select = select.whereColumn("day").isEqualTo(bindMarker());
      }
    }
    
    // (2) prepare
    PreparedStatement preparedStatement = session.prepare(select.build());
    
    // (3) bind
    BoundStatementBuilder boundStatementBuilder =
        preparedStatement.boundStatementBuilder().setInt("id", id);
    if (month != null) {
      boundStatementBuilder = boundStatementBuilder.setInt("month", month);
      if (day != null) {
        boundStatementBuilder = boundStatementBuilder.setInt("day", day);
      }
    }
    
    // (4) execute and map the results
    return session.execute(boundStatementBuilder.build()).map(sensorReadingHelper::get);
  }
}
  1. Retrieve the SELECT query that was started in the constructor, and append additional WHERE clauses as appropriate.

    Note that all query builder objects are immutable, so this creates a new instance every time, there is no risk of corrupting the original field.

  2. Prepare the resulting statement.

    session.prepare caches its results, so if we already prepared that particular combination, there is no network call at this step.

  3. Bind the parameters, according to the WHERE clauses we’ve generated.

  4. Execute the request.

    Another useful helper feature is mapping entities to/from low-level driver data structures: get extracts a SensorReading from a Row, so by mapping it to the ResultSet we get back the desired PagingIterable.

PREVIOUS
Query methods
NEXT
Select methods
  • 4.10.0.x
    • 4.13.0.x
    • 4.12.0.x
    • 4.11.1.x
    • 4.10.0.x
    • 4.7.2.x
    • 3.11.2.x
    • 3.11.0.x
    • 3.10.2.x
    • 3.7.2.x
  • Java Driver for Scylla and Apache Cassandra®
  • API Documentation
  • Manual
    • API conventions
    • Case sensitivity
    • Core driver
      • Address resolution
      • Asynchronous programming
      • Authentication
      • Bill of Materials (BOM)
      • Compression
      • Configuration
        • Reference configuration
      • Control connection
      • Custom codecs
      • Detachable types
      • Query idempotence
      • Integration
      • Load balancing
      • Logging
      • Metadata
        • Node metadata
        • Schema metadata
        • Token metadata
      • Metrics
      • Native protocol
      • Non-blocking programming
      • Paging
      • Performance
      • Connection pooling
      • Query timestamps
      • Reactive Style Programming
      • Reconnection
      • Request tracker
      • Retries
      • Using the shaded JAR
      • Speculative query execution
      • SSL
      • Statements
        • Batch statements
        • Per-query keyspace
        • Prepared statements
        • Simple statements
      • Temporal types
      • Request throttling
      • Query tracing
      • Tuples
      • User-defined types
    • Developer docs
      • Administrative tasks
      • Common infrastructure
        • Concurrency
        • Driver context
        • Event bus
      • Native protocol layer
      • Netty pipeline
      • Request execution
    • Mapper
      • Integration
        • Kotlin
        • Lombok
        • Java 14 Records
        • Scala
      • DAOs
        • Custom result types
        • Delete methods
        • GetEntity methods
        • Increment methods
        • Insert methods
        • Null saving strategy
        • Query methods
        • Query provider methods
        • Select methods
        • SetEntity methods
        • Statement attributes
        • Update methods
      • Entities
      • Mapper interface
    • OSGi
    • Query builder
      • Conditions
      • DELETE
      • Idempotence in the query builder
      • INSERT
      • Relations
      • Schema builder
        • Aggregate
        • Function
        • Index
        • Keyspace
        • Materialized View
        • Table
        • Type
      • SELECT
      • Terms
      • TRUNCATE
      • UPDATE
  • Upgrade guide
  • Frequently asked questions
  • Changelog
  • Create an issue
  • Edit this page

On this page

  • Query provider methods
    • Provider class
    • Provider method
Logo
Docs Contact Us About Us
Mail List Icon Slack Icon
© 2022, ScyllaDB. All rights reserved.
Last updated on 25 May 2022.
Powered by Sphinx 4.3.2 & ScyllaDB Theme 1.2.2