В своем посте 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.
