В своем посте Hello Cassandra я рассмотрел загрузку базы данных Cassandra NoSQL и использование cqlsh для подключения к базе данных Cassandra. В этой статье я расскажу об основах подключения к базе данных Cassandra из Java-клиента.
Хотя для доступа к базе данных Cassandra из Java существует несколько платформ, в этой статье я буду использовать JAR-файл DataStax Java Client . DataStax Java Драйвер для Apache Cassandra доступен на GitHub . На странице проекта GitHub datastax / java-driver говорится, что это «драйвер клиента Java для Apache Cassandra», который «работает исключительно с языком запросов Cassandra версии 3 ( CQL3 )» и «лицензирован по лицензии Apache License версии 2.0 ».
Страница Java Driver 2.0 для Apache Cassandra содержит общий обзор и подробные сведения об архитектуре драйвера. В разделе «Написание вашего первого клиента» представлены списки кода и пояснения, касающиеся подключения к Cassandra с помощью драйвера Java и выполнения операторов CQL из кода Java. Листинги кода в этом посте являются адаптациями тех примеров, которые применяются к моим примерам.
Драйвер Cassandra Java имеет несколько зависимостей . Java Driver 2.0 для Apache Cassandra документации включает в себя страницу под названием Настройка среды разработки Java , которая очерчивает зависимости Java 2.0 драйвер в : Cassandra-драйвер-ядро-2.0.1.jar ( datastax / Java-драйвер 2.0 ), netty- 3.9.0-Final.jar ( netty direct ), guava-16.0.1.jar ( Guava 16 direct ), metrics-core-3.0.2.jar ( Metrics Core ) и slf4j-api-1.7.5.jar ( SLF4J прямой ). Я также обнаружил, что мне нужно поместить LZ4Factory.java и snappy -java в путь к классам.
Следующий листинг кода имеет простой класс с именем CassandraConnector
.
CassandraConnector.java
package com.marxmart.persistence;
import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.Host;
import com.datastax.driver.core.Metadata;
import com.datastax.driver.core.Session;
import static java.lang.System.out;
/**
* Class used for connecting to Cassandra database.
*/
public class CassandraConnector
{
/** Cassandra Cluster. */
private Cluster cluster;
/** Cassandra Session. */
private Session session;
/**
* Connect to Cassandra Cluster specified by provided node IP
* address and port number.
*
* @param node Cluster node IP address.
* @param port Port of cluster host.
*/
public void connect(final String node, final int port)
{
this.cluster = Cluster.builder().addContactPoint(node).withPort(port).build();
final Metadata metadata = cluster.getMetadata();
out.printf("Connected to cluster: %s\n", metadata.getClusterName());
for (final Host host : metadata.getAllHosts())
{
out.printf("Datacenter: %s; Host: %s; Rack: %s\n",
host.getDatacenter(), host.getAddress(), host.getRack());
}
session = cluster.connect();
}
/**
* Provide my Session.
*
* @return My session.
*/
public Session getSession()
{
return this.session;
}
/** Close cluster. */
public void close()
{
cluster.close();
}
}
package com.marxmart.persistence;
import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.Host;
import com.datastax.driver.core.Metadata;
import com.datastax.driver.core.Session;
import static java.lang.System.out;
/**
* Class used for connecting to Cassandra database.
*/
public class CassandraConnector
{
/** Cassandra Cluster. */
private Cluster cluster;
/** Cassandra Session. */
private Session session;
/**
* Connect to Cassandra Cluster specified by provided node IP
* address and port number.
*
* @param node Cluster node IP address.
* @param port Port of cluster host.
*/
public void connect(final String node, final int port)
{
this.cluster = Cluster.builder().addContactPoint(node).withPort(port).build();
final Metadata metadata = cluster.getMetadata();
out.printf("Connected to cluster: %s\n", metadata.getClusterName());
for (final Host host : metadata.getAllHosts())
{
out.printf("Datacenter: %s; Host: %s; Rack: %s\n",
host.getDatacenter(), host.getAddress(), host.getRack());
}
session = cluster.connect();
}
/**
* Provide my Session.
*
* @return My session.
*/
public Session getSession()
{
return this.session;
}
/** Close cluster. */
public void close()
{
cluster.close();
}
}
Вышеупомянутый соединительный класс может быть вызван, как показано в следующем листинге кода.
Код с использованием CassandraConnector
/**
* Main function for demonstrating connecting to Cassandra with host and port.
*
* @param args Command-line arguments; first argument, if provided, is the
* host and second argument, if provided, is the port.
*/
public static void main(final String[] args)
{
final CassandraConnector client = new CassandraConnector();
final String ipAddress = args.length > 0 ? args[0] : "localhost";
final int port = args.length > 1 ? Integer.parseInt(args[1]) : 9042;
out.println("Connecting to IP Address " + ipAddress + ":" + port + "...");
client.connect(ipAddress, port);
client.close();
}
/**
* Main function for demonstrating connecting to Cassandra with host and port.
*
* @param args Command-line arguments; first argument, if provided, is the
* host and second argument, if provided, is the port.
*/
public static void main(final String[] args)
{
final CassandraConnector client = new CassandraConnector();
final String ipAddress = args.length > 0 ? args[0] : "localhost";
final int port = args.length > 1 ? Integer.parseInt(args[1]) : 9042;
out.println("Connecting to IP Address " + ipAddress + ":" + port + "...");
client.connect(ipAddress, port);
client.close();
}
Пример кода в этом последнем листинге кода указывает узел по умолчанию, а также порт localhost
и порт 9042
. Этот номер порта указан в файле cassandra.yaml, расположенном в каталоге apache-cassandra / conf . Документация Cassandra 1.2 содержит страницу в файле конфигурации cassandra.yaml, в которой файл cassandra.yaml описывается как «основной файл конфигурации для Cassandra». Кстати, еще один важный файл конфигурации в этом же каталоге — cassandra-env.sh , который определяет многочисленные параметры JVM для базы данных Cassandra на основе Java .
Для примеров в этом посте я буду использовать таблицу MOVIES, созданную на следующем языке запросов Cassandra (CQL):
createMovie.cql
CREATE TABLE movies
(
title varchar,
year int,
description varchar,
mmpa_rating varchar,
dustin_rating varchar,
PRIMARY KEY (title, year)
);
Вышеупомянутый файл может быть выполнен в cqlsh с помощью команды source 'C:\cassandra\cql\examples\createMovie.cql'
( конечно, при условии, что файл находится в указанном каталоге), и это продемонстрировано на следующем снимке экрана.
Здесь стоит подчеркнуть одну вещь: столбцы, созданные как varchar
типы данных , описываются как text
типы данных командой cqlsh description . Хотя я и создал эту таблицу напрямую cqlsh
, я также мог бы создать таблицу на Java, как показано в следующем листинге кода и соответствующем снимке экрана, который следует за листингом кода.
Создание таблицы Кассандры с драйвером Java
final String createMovieCql =
"CREATE TABLE movies_keyspace.movies (title varchar, year int, description varchar, "
+ "mmpa_rating varchar, dustin_rating varchar, PRIMARY KEY (title, year))";
client.getSession().execute(createMovieCql);
Приведенный выше код обращается к переменной экземпляра client
. Класс с этой переменной экземпляра, в которой он может существовать, показан ниже.
Оболочка MoviePersistence.java
package dustin.examples.cassandra;
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.Row;
import java.util.Optional;
import static java.lang.System.out;
/**
* Handles movie persistence access.
*/
public class MoviePersistence
{
private final CassandraConnector client = new CassandraConnector();
public MoviePersistence(final String newHost, final int newPort)
{
out.println("Connecting to IP Address " + newHost + ":" + newPort + "...");
client.connect(newHost, newPort);
}
/**
* Close my underlying Cassandra connection.
*/
private void close()
{
client.close();
}
}
MOVIES
таблицей, созданной как показано выше (или с помощью
cqlsh
или с клиентским кодом Java), следующие шаги должны манипулировать данными, связанными с этой таблицей. В следующем листинге кода показан метод, который можно использовать для записи новых строк в
MOVIES
таблицу.
/**
* Persist provided movie information.
*
* @param title Title of movie to be persisted.
* @param year Year of movie to be persisted.
* @param description Description of movie to be persisted.
* @param mmpaRating MMPA rating.
* @param dustinRating Dustin's rating.
*/
public void persistMovie(
final String title, final int year, final String description,
final String mmpaRating, final String dustinRating)
{
client.getSession().execute(
"INSERT INTO movies_keyspace.movies (title, year, description, mmpa_rating, dustin_rating) VALUES (?, ?, ?, ?, ?)",
title, year, description, mmpaRating, dustinRating);
}
С данными, вставленными в MOVIES
таблицу, мы должны иметь возможность запросить их. В следующем листинге кода показана одна потенциальная реализация запроса фильма по названию и году.
Запросы с помощью драйвера Java Cassandra
/**
* Returns movie matching provided title and year.
*
* @param title Title of desired movie.
* @param year Year of desired movie.
* @return Desired movie if match is found; Optional.empty() if no match is found.
*/
public Optional<Movie> queryMovieByTitleAndYear(final String title, final int year)
{
final ResultSet movieResults = client.getSession().execute(
"SELECT * from movies_keyspace.movies WHERE title = ? AND year = ?", title, year);
final Row movieRow = movieResults.one();
final Optional<Movie> movie =
movieRow != null
? Optional.of(new Movie(
movieRow.getString("title"),
movieRow.getInt("year"),
movieRow.getString("description"),
movieRow.getString("mmpa_rating"),
movieRow.getString("dustin_rating")))
: Optional.empty();
return movie;
}
/**
* Returns movie matching provided title and year.
*
* @param title Title of desired movie.
* @param year Year of desired movie.
* @return Desired movie if match is found; Optional.empty() if no match is found.
*/
public Optional<Movie> queryMovieByTitleAndYear(final String title, final int year)
{
final ResultSet movieResults = client.getSession().execute(
"SELECT * from movies_keyspace.movies WHERE title = ? AND year = ?", title, year);
final Row movieRow = movieResults.one();
final Optional<Movie> movie =
movieRow != null
? Optional.of(new Movie(
movieRow.getString("title"),
movieRow.getInt("year"),
movieRow.getString("description"),
movieRow.getString("mmpa_rating"),
movieRow.getString("dustin_rating")))
: Optional.empty();
return movie;
}
Если нам нужно удалить данные, уже хранящиеся в базе данных Cassandra, это легко сделать, как показано в следующем листинге кода.
Удаление с помощью драйвера Cassandra Java
/**
* Deletes the movie with the provided title and release year.
*
* @param title Title of movie to be deleted.
* @param year Year of release of movie to be deleted.
*/
public void deleteMovieWithTitleAndYear(final String title, final int year)
{
final String deleteString = "DELETE FROM movies_keyspace.movies WHERE title = ? and year = ?";
client.getSession().execute(deleteString, title, year);
}
/**
* Deletes the movie with the provided title and release year.
*
* @param title Title of movie to be deleted.
* @param year Year of release of movie to be deleted.
*/
public void deleteMovieWithTitleAndYear(final String title, final int year)
{
final String deleteString = "DELETE FROM movies_keyspace.movies WHERE title = ? and year = ?";
client.getSession().execute(deleteString, title, year);
}
Как показали примеры из этого поста в блоге, к Cassandra легко получить доступ из приложений Java с помощью драйвера Java. Стоит отметить, что Кассандра написана на Java . Преимущество этого для разработчиков Java состоит в том, что многие значения конфигурации Cassandra являются параметрами JVM, с которыми разработчики Java уже знакомы. cassandra-env.sh
Файл в Cassandra conf
каталоге позволяет указать стандартные параметры виртуальной машины Java , используемые Кассандры (например, куча размеров параметров -Xms
, -Xmx
, и -Xmn
), HotSpot специфические параметры виртуальной машины Java (например -XX:-HeapDumpOnOutOfMemoryError
, -XX:HeapDumpPath
, параметры настройки сборки мусора , а также параметры сбора мусора лесозаготовок ), позволяя утверждения ( -ea
) и предоставление Cassandra для удаленного управления JMX .
Говоря о Cassandra и JMX, Cassandra можно отслеживать через JMX, как описано в разделе «Мониторинг с помощью JConsole» в разделе « Мониторинг кластера Cassandra» . В отрывке из книги «Основы мониторинга Кассандры» также обсуждается использование JMX для мониторинга Кассандры. Поскольку разработчики Java с большей вероятностью знакомы с клиентами JMX, такими как JConsole и VisualVM , это интуитивно понятный подход к мониторингу Cassandra для разработчиков Java.
Другое преимущество Java-корней Cassandra заключается в том, что классы Java, используемые Cassandra, могут быть расширены, а Cassandra может быть настроена с помощью Java. Например, пользовательские типы данных могут быть реализованы путем расширения класса AbstractType .
Вывод
Драйвер Java Cassandra упрощает доступ к Cassandra из приложений Java. Cassandra также обладает значительной конфигурацией и мониторингом на основе Java и может даже настраиваться с помощью Java.