Of course, applications using Java (and many other languages) can connect to, and work with, data in Cassandra. The easiest way to do so is with the DataStax Cassandra Java driver, via Apache Maven. To accomplish this, I'll create a new Maven project (naming it CassHelloWorld) with the following entries in the pom.xml:
<dependencies>
<dependency>
<groupId>com.datastax.cassandra</groupId>
<artifactId>cassandra-driver-core</artifactId>
<version>3.3.0</version>
</dependency>
</dependencies>
Once that is done, we will create a class, named CassandraConnection, to handle our Cassandra connections:
import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.Session;
import com.datastax.driver.core.ResultSet;
public class CassandraConnection {
private Cluster cluster;
private Session session;
We will create two constructors: one without arguments, and one that accepts a node, username, and password:
public CassandraConnection() {
}
public CassandraConnection(String node, String user, String pwd) {
connect(node,user,pwd);
}
Then we'll create a public connect method that takes an endpoint and our credentials and then connects to our cluster:
public void connect(String node, String user, String pwd) {
cluster = Cluster.builder()
.addContactPoint(node)
.withCredentials(user,pwd)
.build();
session = cluster.connect();
}
We will also create methods to handle queries and close the connection:
public ResultSet query(String strQuery) {
return session.execute(strQuery);
}
public void close() {
cluster.close();
}
}
Finally, we will create a short main class to connect to our cluster, query the system.local table, and print the result set:
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.Row;
public class CassHelloWorld {
public static void main(String[] args) {
CassandraConnection conn = new CassandraConnection();
conn.connect("192.168.0.100", "cassdba", "flynnLives");
String strSELECT ="SELECT cluster_name,data_center,"
+ "listen_address,release_version "
+ "FROM system.local WHERE key='local'";
ResultSet rows = conn.query(strSELECT);
for (Row row : rows) {
System.out.print(
row.getString("cluster_name") + " " +
row.getString("data_center") + " " +
row.getString("release_version"));
}
conn.close();
}
}
The cassdba account is used here for brevity in this example. You typically would not want to use a superuser account to query data for an application. The best practice is to create a new user account with privileges assigned only to the specific required keyspace or tables.
When running this code in my integrated developer environment (IDE), I get the following results:
PermanentWaves LakesidePark 3.10
Next, we will write code to use prepared/bound statements to read and write from Cassandra (much like the second Python example). We will use the same CassandraConnection class, with three new methods:
public ResultSet query(BoundStatement bStatement) {
return session.execute(bStatement);
}
public void insert(BoundStatement bStatement) {
session.execute(bStatement);
}
public Session getSession() {
return session;
}
The query method will be an overload of the existing one, with the new method allowing a bound statement object to be passed in. The insert method will take a bound statement, and execute it. And the getSession method will return the local, private session so that queries can be prepared and variables can be bound.
Next, we will create a new main class called QueryUser. It will need the following imports:
import com.datastax.driver.core.BoundStatement;
import com.datastax.driver.core.PreparedStatement;
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.Row;
import com.datastax.driver.core.Session;
The main class will connect in much the same way as the last Java example, except that we will create a local variable to hold the state of the session object:
public static void main(String[] args) {
CassandraConnection conn = new CassandraConnection();
conn.connect("192.168.0.100", "cassdba", "flynnLives");
Session session = conn.getSession();
Create a local variable for the current userID:
String userID = System.getProperty("user.name");
Here we will create our insert query, prepare it, and bind our user-ID variable and IP address to it. Once that is done, we will pass the bound statement for the insert to the CassandraConnection class insert method:
String strINSERT = "INSERT INTO packt.logins_by_user "
+ "(user_id,login_datetime,origin_ip) "
+ "VALUES (?,dateof(now()),?)";
PreparedStatement pIStatement = session.prepare(strINSERT);
BoundStatement bIStatement = new BoundStatement(pIStatement);
bIStatement.bind(userID, "192.168.0.119");
conn.insert(bIStatement);
Similarly, with the select query, we will prepare the statement and bind our user-ID variable to it. We will then pass our bound statement to the query method on the CassandraConnection class, and process the returned result set:
String strSELECT = "SELECT * "
+ "FROM packt.logins_by_user WHERE user_id=? "
+ "LIMIT 3";
PreparedStatement pSStatement = session.prepare(strSELECT);
BoundStatement bSStatement = new BoundStatement(pSStatement);
bSStatement.bind(userID);
ResultSet rows = conn.query(bSStatement);
for (Row row : rows) {
System.out.println(row.getString("user_id") + " " +
row.getTimestamp("login_datetime") + " " +
row.getString("origin_ip"));
}
conn.close();
}
When I run this code in my IDE, I see the following results:
aploetz Sun Jun 11 08:49:58 CDT 2017 192.168.0.119
aploetz Sat Jun 10 15:26:23 CDT 2017 192.168.0.114
aploetz Sat Jun 03 14:04:55 CDT 2017 192.168.0.101