Java 8, 11, 17+

Java Driver

Build high-performance enterprise Java apps with Cassandra!

📦 Maven Setup & Dependencies

Add driver to your project!

1

Maven pom.xml

Add dependency to your project

<!-- Add to pom.xml --> <dependencies> <!-- Cassandra Java Driver 4.x --> <dependency> <groupId>com.datastax.oss</groupId> <artifactId>java-driver-core</artifactId> <version>4.18.0</version> </dependency> <!-- Object Mapper (optional) --> <dependency> <groupId>com.datastax.oss</groupId> <artifactId>java-driver-mapper-runtime</artifactId> <version>4.18.0</version> </dependency> </dependencies>
2

Gradle build.gradle

For Gradle projects

// Add to build.gradle dependencies { // Cassandra Java Driver implementation 'com.datastax.oss:java-driver-core:4.18.0' // Object Mapper (optional) implementation 'com.datastax.oss:java-driver-mapper-runtime:4.18.0' annotationProcessor 'com.datastax.oss:java-driver-mapper-processor:4.18.0' }

System Requirements

Component Requirement Notes
Java 8, 11, 17+ LTS versions recommended
Driver 4.18.0+ Latest stable version
Cassandra 2.1+ Best with 3.11 or 4.0+
Build Tool Maven 3.6+ or Gradle 7+ For dependency management

🚀 Quick Start Example

Your first Java + Cassandra app!

// HelloCassandra.java import com.datastax.oss.driver.api.core.CqlSession; import com.datastax.oss.driver.api.core.cql.*; import java.net.InetSocketAddress; import java.util.UUID; public class HelloCassandra { public static void main(String[] args) { // 1. Connect to Cassandra try (CqlSession session = CqlSession.builder() .addContactPoint(new InetSocketAddress("127.0.0.1", 9042)) .withLocalDatacenter("datacenter1") .build()) { // 2. Create keyspace session.execute(""" CREATE KEYSPACE IF NOT EXISTS tutorial WITH replication = { 'class': 'SimpleStrategy', 'replication_factor': 1 } """); // 3. Create table session.execute(""" CREATE TABLE IF NOT EXISTS tutorial.users ( user_id UUID PRIMARY KEY, name TEXT, email TEXT, age INT ) """); // 4. Insert data UUID userId = UUID.randomUUID(); PreparedStatement insertStmt = session.prepare( "INSERT INTO tutorial.users (user_id, name, email, age) VALUES (?, ?, ?, ?)" ); session.execute(insertStmt.bind(userId, "Alice", "alice@example.com", 28)); // 5. Query data ResultSet results = session.execute("SELECT * FROM tutorial.users"); for (Row row : results) { System.out.printf("%s (%s) - Age: %d%n", row.getString("name"), row.getString("email"), row.getInt("age") ); } } // Session auto-closed by try-with-resources } } // Output: Alice (alice@example.com) - Age: 28

Compile and Run

# Compile $ mvn compile # Run $ mvn exec:java -Dexec.mainClass="HelloCassandra" # Output: Alice (alice@example.com) - Age: 28

🔌 Connection Management

Proper session setup!

Basic Connection

import com.datastax.oss.driver.api.core.CqlSession; import java.net.InetSocketAddress; // Simple connection CqlSession session = CqlSession.builder() .addContactPoint(new InetSocketAddress("127.0.0.1", 9042)) .withLocalDatacenter("datacenter1") .withKeyspace("my_keyspace") .build(); // Use session... // Always close when done session.close();

Production-Ready Connection

import com.datastax.oss.driver.api.core.CqlSession; import com.datastax.oss.driver.api.core.CqlSessionBuilder; import com.datastax.oss.driver.api.core.config.*; import java.net.InetSocketAddress; import java.time.Duration; public class CassandraConnection { public static CqlSession createSession() { return CqlSession.builder() // Contact points .addContactPoint(new InetSocketAddress("node1", 9042)) .addContactPoint(new InetSocketAddress("node2", 9042)) .addContactPoint(new InetSocketAddress("node3", 9042)) // Datacenter .withLocalDatacenter("datacenter1") // Authentication .withAuthCredentials("cassandra", "cassandra") // Keyspace .withKeyspace("my_keyspace") // Timeouts .withConfigLoader(DriverConfigLoader.programmaticBuilder() .withDuration(DefaultDriverOption.REQUEST_TIMEOUT, Duration.ofSeconds(10)) .withDuration(DefaultDriverOption.CONNECTION_INIT_QUERY_TIMEOUT, Duration.ofSeconds(5)) .build()) .build(); } }

Singleton Pattern (Recommended)

// CassandraManager.java import com.datastax.oss.driver.api.core.CqlSession; import java.net.InetSocketAddress; public class CassandraManager { private static CqlSession session; private CassandraManager() {} public static synchronized CqlSession getSession() { if (session == null) { session = CqlSession.builder() .addContactPoint(new InetSocketAddress("localhost", 9042)) .withLocalDatacenter("datacenter1") .withKeyspace("my_keyspace") .build(); } return session; } public static void shutdown() { if (session != null) { session.close(); session = null; } } } // Usage in your app public class UserService { public User getUser(UUID userId) { CqlSession session = CassandraManager.getSession(); // Execute queries... return user; } } // On application shutdown CassandraManager.shutdown();

📝 Basic Query Operations

CRUD operations!

SELECT Queries

import com.datastax.oss.driver.api.core.cql.*; // Simple select ResultSet results = session.execute( "SELECT * FROM users" ); for (Row row : results) { System.out.println(row.getString("name") + ": " + row.getString("email")); } // With parameters SimpleStatement stmt = SimpleStatement.newInstance( "SELECT * FROM users WHERE user_id = ?", userId ); ResultSet rs = session.execute(stmt); // Get single row Row row = rs.one(); if (row != null) { String name = row.getString("name"); Integer age = row.getInt("age"); }

INSERT Queries

import java.util.UUID; // Simple insert session.execute(SimpleStatement.newInstance( "INSERT INTO users (user_id, name, email, age) VALUES (?, ?, ?, ?)", UUID.randomUUID(), "Bob", "bob@example.com", 30 )); // Insert with TTL session.execute(SimpleStatement.newInstance( "INSERT INTO sessions (session_id, user_id) VALUES (?, ?) USING TTL ?", sessionId, userId, 3600 // 1 hour )); // Conditional insert ResultSet result = session.execute(SimpleStatement.newInstance( "INSERT INTO users (user_id, name, email) VALUES (?, ?, ?) IF NOT EXISTS", userId, "Charlie", "charlie@example.com" )); if (result.wasApplied()) { System.out.println("User created"); } else { System.out.println("User already exists"); }

UPDATE Queries

// Simple update session.execute(SimpleStatement.newInstance( "UPDATE users SET age = ?, email = ? WHERE user_id = ?", 31, "newemail@example.com", userId )); // Conditional update ResultSet result = session.execute(SimpleStatement.newInstance( "UPDATE users SET age = ? WHERE user_id = ? IF age = ?", 32, userId, 31 )); if (result.wasApplied()) { System.out.println("Update successful"); } // Increment counter session.execute(SimpleStatement.newInstance( "UPDATE page_views SET views = views + ? WHERE page_id = ?", 1, pageId ));

DELETE Queries

// Delete row session.execute(SimpleStatement.newInstance( "DELETE FROM users WHERE user_id = ?", userId )); // Delete specific columns session.execute(SimpleStatement.newInstance( "DELETE email, age FROM users WHERE user_id = ?", userId )); // Conditional delete ResultSet result = session.execute(SimpleStatement.newInstance( "DELETE FROM users WHERE user_id = ? IF age > ?", userId, 50 )); if (result.wasApplied()) { System.out.println("User deleted"); }

BATCH Queries

import com.datastax.oss.driver.api.core.cql.BatchStatement; import com.datastax.oss.driver.api.core.cql.DefaultBatchType; // Create batch statement BatchStatement batch = BatchStatement.newInstance( DefaultBatchType.LOGGED, SimpleStatement.newInstance( "INSERT INTO users (user_id, name) VALUES (?, ?)", UUID.randomUUID(), "User1" ), SimpleStatement.newInstance( "INSERT INTO users (user_id, name) VALUES (?, ?)", UUID.randomUUID(), "User2" ), SimpleStatement.newInstance( "INSERT INTO users (user_id, name) VALUES (?, ?)", UUID.randomUUID(), "User3" ) ); // Execute batch (atomic) session.execute(batch); // WARNING: Only batch operations on SAME partition!

⚡ Prepared Statements

Maximum performance!

Why Use Prepared Statements?

  • ✅ Performance: 10x faster execution (parsed once)
  • ✅ Security: Protection from CQL injection
  • ✅ Type safety: Compile-time parameter validation
  • ✅ Efficiency: Less network overhead

Basic Prepared Statements

import com.datastax.oss.driver.api.core.cql.*; // Prepare statement ONCE (at startup) PreparedStatement insertUser = session.prepare( "INSERT INTO users (user_id, name, email, age) VALUES (?, ?, ?, ?)" ); // Execute MANY times (in request handlers) session.execute(insertUser.bind( UUID.randomUUID(), "Alice", "alice@example.com", 28 )); session.execute(insertUser.bind( UUID.randomUUID(), "Bob", "bob@example.com", 30 )); session.execute(insertUser.bind( UUID.randomUUID(), "Charlie", "charlie@example.com", 25 )); // 10x faster than SimpleStatement! ✅

Named Parameters

// Prepare with named parameters PreparedStatement selectUser = session.prepare( "SELECT name, email, age FROM users WHERE user_id = :userId AND age > :minAge" ); // Bind by name BoundStatement bound = selectUser.bind() .setUuid("userId", userId) .setInt("minAge", 25); ResultSet results = session.execute(bound);

Query Repository Pattern

// UserRepository.java import com.datastax.oss.driver.api.core.CqlSession; import com.datastax.oss.driver.api.core.cql.*; import java.util.UUID; public class UserRepository { private final CqlSession session; private final PreparedStatement insertStmt; private final PreparedStatement selectStmt; private final PreparedStatement updateStmt; private final PreparedStatement deleteStmt; public UserRepository(CqlSession session) { this.session = session; // Prepare all statements at startup this.insertStmt = session.prepare( "INSERT INTO users (user_id, name, email, age) VALUES (?, ?, ?, ?)" ); this.selectStmt = session.prepare( "SELECT * FROM users WHERE user_id = ?" ); this.updateStmt = session.prepare( "UPDATE users SET name = ?, email = ?, age = ? WHERE user_id = ?" ); this.deleteStmt = session.prepare( "DELETE FROM users WHERE user_id = ?" ); } public void createUser(UUID userId, String name, String email, int age) { session.execute(insertStmt.bind(userId, name, email, age)); } public Row findUser(UUID userId) { ResultSet rs = session.execute(selectStmt.bind(userId)); return rs.one(); } public void updateUser(UUID userId, String name, String email, int age) { session.execute(updateStmt.bind(name, email, age, userId)); } public void deleteUser(UUID userId) { session.execute(deleteStmt.bind(userId)); } } // Usage UserRepository repo = new UserRepository(session); repo.createUser(UUID.randomUUID(), "Alice", "alice@example.com", 28);

🔄 Reactive API

Non-blocking reactive queries!

Reactive Programming

Java driver 4.x supports full reactive programming with Project Reactor!

  • ✅ Non-blocking async operations
  • ✅ Backpressure handling
  • ✅ Streaming large result sets
  • ✅ Composable operations

Reactive Query Execution

import com.datastax.oss.driver.api.core.cql.AsyncResultSet; import java.util.concurrent.CompletionStage; // Async query returns CompletionStage CompletionStage<AsyncResultSet> future = session.executeAsync("SELECT * FROM users WHERE user_id = ?", userId); // Handle result asynchronously future.thenAccept(resultSet -> { for (Row row : resultSet.currentPage()) { System.out.println(row.getString("name")); } }).exceptionally(error -> { System.err.println("Query failed: " + error.getMessage()); return null; });

Reactive Streams

import com.datastax.dse.driver.api.core.cql.reactive.ReactiveResultSet; import reactor.core.publisher.Flux; // Execute query reactively ReactiveResultSet reactiveRs = session.executeReactive("SELECT * FROM users"); // Convert to Flux (reactive stream) Flux.from(reactiveRs) .map(row -> row.getString("name")) .doOnNext(System.out::println) .doOnError(error -> System.err.println("Error: " + error)) .doOnComplete(() -> System.out.println("Query complete")) .subscribe();

🗺️ Object Mapping

Map POJOs to tables!

Object Mapper

The Java driver includes a powerful object mapper that automatically maps Java objects to Cassandra tables!

  • ✅ Automatic CRUD operations
  • ✅ Type-safe queries
  • ✅ Compile-time code generation
  • ✅ No reflection at runtime

Entity Definition

import com.datastax.oss.driver.api.mapper.annotations.*; import java.util.UUID; @Entity @CqlName("users") public class User { @PartitionKey private UUID userId; private String name; private String email; private Integer age; // Constructors public User() {} public User(UUID userId, String name, String email, Integer age) { this.userId = userId; this.name = name; this.email = email; this.age = age; } // Getters and setters public UUID getUserId() { return userId; } public void setUserId(UUID userId) { this.userId = userId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }

DAO Interface

import com.datastax.oss.driver.api.mapper.annotations.*; import java.util.UUID; @Dao public interface UserDao { @Insert void save(User user); @Select User findById(UUID userId); @Update void update(User user); @Delete void delete(User user); @Query("SELECT * FROM users WHERE age > :age") PagingIterable<User> findByAgeGreaterThan(int age); }

Mapper Interface

import com.datastax.oss.driver.api.mapper.annotations.*; @Mapper public interface UserMapper { @DaoFactory UserDao userDao(@DaoKeyspace CqlIdentifier keyspace); }

Usage

import com.datastax.oss.driver.api.core.CqlSession; import com.datastax.oss.driver.api.mapper.MapperBuilder; import java.util.UUID; // Create mapper (once at startup) UserMapper mapper = new UserMapperBuilder(session).build(); UserDao userDao = mapper.userDao(CqlIdentifier.fromCql("my_keyspace")); // Create user User user = new User( UUID.randomUUID(), "Alice", "alice@example.com", 28 ); userDao.save(user); // Find user User found = userDao.findById(user.getUserId()); System.out.println(found.getName()); // Update user found.setAge(29); userDao.update(found); // Custom query for (User u : userDao.findByAgeGreaterThan(25)) { System.out.println(u.getName()); } // Delete user userDao.delete(found);

💡 Java Driver Best Practices

Production tips!

✅

DO

  • Use singleton pattern for CqlSession
  • Use prepared statements for repeated queries
  • Use object mapper for clean code
  • Use try-with-resources for auto-close
  • Configure appropriate timeouts
  • Use async/reactive for high throughput
  • Monitor session metrics
  • Close session on shutdown
❌

DON'T

  • Create session per request
  • Use string concatenation for queries
  • Ignore timeout configuration
  • Use blocking calls in reactive code
  • Forget to close sessions
  • Mix sync and async patterns
  • Skip connection pooling config
  • Use SELECT * on large tables

Performance Tips

Technique Benefit When to Use
Prepared Statements 10x faster Repeated queries
Async/Reactive Non-blocking High concurrency
Object Mapper Type-safe, clean code CRUD-heavy apps
Batch Statements Atomic operations Same partition updates
Connection Pooling Resource efficiency Always (automatic)

Complete Production Example

// Application.java - Production-ready import com.datastax.oss.driver.api.core.CqlSession; import java.net.InetSocketAddress; public class Application { private static CqlSession session; private static UserRepository userRepository; public static void main(String[] args) { // Initialize at startup initialize(); try { // Your application logic runApplication(); } finally { // Clean shutdown shutdown(); } } private static void initialize() { // Create session (ONCE) session = CqlSession.builder() .addContactPoint(new InetSocketAddress("localhost", 9042)) .withLocalDatacenter("datacenter1") .withKeyspace("my_keyspace") .build(); // Initialize repository with prepared statements userRepository = new UserRepository(session); } private static void runApplication() { // Use repository in your handlers UUID userId = UUID.randomUUID(); userRepository.createUser(userId, "Alice", "alice@example.com", 28); Row user = userRepository.findUser(userId); System.out.println(user.getString("name")); } private static void shutdown() { if (session != null) { session.close(); } } }

🎉 Master Java + Cassandra!

You now know how to build enterprise Java apps with Cassandra!

🎓 What You Learned:

  • 📦 Maven setup: com.datastax.oss:java-driver-core:4.18.0
  • 🚀 Quick start: Complete example with CqlSession
  • 🔌 Connection: Singleton pattern, production config
  • 📝 Basic queries: SELECT, INSERT, UPDATE, DELETE, BATCH
  • ⚡ Prepared statements: 10x faster, repository pattern
  • 🔄 Reactive API: Non-blocking with CompletionStage
  • 🗺️ Object mapping: Type-safe POJO to table mapping
  • 💡 Best practices: Production-ready patterns

💡 Key Takeaways:

  1. Singleton CqlSession - Create once, reuse everywhere
  2. Prepared statements - 10x faster for repeated queries
  3. Object mapper - Type-safe, annotation-based mapping
  4. Reactive API - Non-blocking with CompletionStage/Flux
  5. Try-with-resources - Automatic session cleanup
  6. Repository pattern - Organize prepared statements

☕ Quick Reference:

// Maven dependency com.datastax.oss:java-driver-core:4.18.0 // Connect (singleton) CqlSession session = CqlSession.builder() .addContactPoint(new InetSocketAddress("localhost", 9042)) .withLocalDatacenter("datacenter1") .build(); // Prepared statement (10x faster!) PreparedStatement ps = session.prepare("SELECT * FROM users WHERE id = ?"); session.execute(ps.bind(userId)); // Async query CompletionStage<AsyncResultSet> future = session.executeAsync(...); // Close session.close();

☕ Java + Cassandra = Enterprise power! 🎯
Start building now!

Advertisement

📱 Responsive Ad 📱