Сегодня я возвращаюсь к большей интеграции Cassandra и Java, сосредоточившись на использовании драйвера Java Datastax, а не Spring Data Cassandra, о котором я уже много писал. Драйвер Datastax фактически используется Spring Data для взаимодействия с Cassandra, но поставляется с некоторыми дополнительными функциями, созданными поверх него. Но мы не хотим ничего из этого сегодня! Мы собираемся использовать драйвер Datastax напрямую, и в конце статьи, как только мы увидим, как его использовать, мы сравним его со Spring Data.
В этом посте предполагается, что вы уже знакомы с Cassandra и, возможно, Spring Data Cassandra. Поскольку я уже написал немало постов на эту тему, я лишь коснулся того, как работает Кассандра там, где требуется контекст. Если у вас нет этой справочной информации, я рекомендую прочитать « Начало работы с Spring Data Cassandra», где я, очевидно, говорил об использовании Spring Data Cassandra, но также более подробно объяснил, как работает Cassandra, чем я в этом посте. Существует также Академия Datastax, которая предоставляет некоторые очень полезные ресурсы для изучения того, как использовать Cassandra самостоятельно.
Перво-наперво, зависимости.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
< dependencies > < dependency > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-starter</ artifactId > </ dependency > < dependency > < groupId >com.datastax.cassandra</ groupId > < artifactId >cassandra-driver-core</ artifactId > < version >3.4.0</ version > </ dependency > < dependency > < groupId >com.datastax.cassandra</ groupId > < artifactId >cassandra-driver-mapping</ artifactId > < version >3.4.0</ version > </ dependency > < dependency > < groupId >commons-io</ groupId > < artifactId >commons-io</ artifactId > < version >2.4</ version > </ dependency > < dependency > < groupId >org.apache.commons</ groupId > < artifactId >commons-lang3</ artifactId > < version >3.7</ version > </ dependency > </ dependencies > |
Как всегда, я использую Spring Boot, просто потому, что мы лишаем себя Spring Data, не означает, что нам нужно полностью отказаться от всех библиотек Spring. Связанные с Datastax зависимости здесь — это cassandra-driver-core
и cassandra-driver-mapping
. cassandra-driver-core
, как следует из названия, обеспечивает основные функциональные возможности для взаимодействия с Cassandra, такие как настройка сеанса и написание запросов. cassandra-driver-mapping
не требуется для запроса Cassandra, но обеспечивает некоторое сопоставление объектов, в сочетании с основным драйвером теперь он будет служить ORM, а не только позволять нам выполнять операторы CQL.
Теперь у нас отсортированы зависимости, следующий шаг — подключиться к Cassandra, чтобы мы могли начать его запрашивать.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
@Configuration public class CassandraConfig { @Bean public Cluster cluster( @Value ( "${cassandra.host:127.0.0.1}" ) String host, @Value ( "${cassandra.cluster.name:cluster}" ) String clusterName, @Value ( "${cassandra.port:9042}" ) int port) { return Cluster.builder() .addContactPoint(host) .withPort(port) .withClusterName(clusterName) .build(); } @Bean public Session session(Cluster cluster, @Value ( "${cassandra.keyspace}" ) String keyspace) throws IOException { final Session session = cluster.connect(); setupKeyspace(session, keyspace); return session; } private void setupKeyspace(Session session, String keyspace) throws IOException { final Map<String, Object> replication = new HashMap<>(); replication.put( "class" , "SimpleStrategy" ); replication.put( "replication_factor" , 1 ); session.execute(createKeyspace(keyspace).ifNotExists().with().replication(replication)); session.execute( "USE " + keyspace); // String[] statements = split(IOUtils.toString(getClass().getResourceAsStream("/cql/setup.cql")), ";"); // Arrays.stream(statements).map(statement -> normalizeSpace(statement) + ";").forEach(session::execute); } @Bean public MappingManager mappingManager(Session session) { final PropertyMapper propertyMapper = new DefaultPropertyMapper() .setNamingStrategy( new DefaultNamingStrategy(LOWER_CAMEL_CASE, LOWER_SNAKE_CASE)); final MappingConfiguration configuration = MappingConfiguration.builder().withPropertyMapper(propertyMapper).build(); return new MappingManager(session, configuration); } } |
Здесь немного больше ядра по сравнению с аналогичной установкой, использующей Spring Data (этот класс даже не нужен в сочетании с автоконфигурацией Spring Boot), но сам класс довольно прост. Базовая настройка bean-компонентов Cluster
и Session
показанных здесь, является минимальным необходимым для работы приложения и, вероятно, останется неизменной для любого приложения, которое вы пишете. Предусмотрено больше методов, так что вы можете добавить любую дополнительную конфигурацию, чтобы сделать их подходящими для вашего варианта использования.
Используя значения из application.properties
мы устанавливаем адрес хоста, имя кластера и порт Cluster
. Затем Cluster
используется для создания Session
. При этом можно выбрать один из двух вариантов: задавать пространство клавиш по умолчанию или нет. Если вы хотите установить пространство клавиш по умолчанию, тогда все, что вам нужно сделать, это использовать приведенный ниже код.
1
2
3
4
5
6
|
@Bean public Session session(Cluster cluster, @Value ( "${cassandra.keyspace}" ) String keyspace) throws IOException { final Session session = cluster.connect(keyspace); // any other setup return session; } |
Пространство ключей передается в метод connect
который создает Session
и затем выполняет USE <keyspace>
устанавливая пространство ключей по умолчанию. Это зависит от пространства ключей, существующего до создания сеанса, в противном случае произойдет сбой при выполнении оператора USE
.
Если вы не знаете, существует ли пространство ключей при запуске, или знаете, что вы определенно хотите создать его динамически на основе значения пространства ключей из файла свойств, то вам нужно будет вызвать connect
без указания пространства ключей. Затем вам нужно будет создать его самостоятельно, чтобы у вас было что использовать. Для этого используйте метод createKeyspace
предоставленный SchemaBuilder
. Ниже приведен оператор CQL для создания пространства ключей.
1
|
CREATE KEYSPACE IF NOT EXISTS <keyspace> WITH REPLICATION = { 'class' : 'SimpleStrategy' , 'replication_factor' :1 }; |
Я также добавил код клавиши ниже, так как теперь он немного далек.
1
2
3
4
5
6
7
|
private void setupKeyspace(Session session, String keyspace) throws IOException { final Map<String, Object> replication = new HashMap<>(); replication.put( "class" , "SimpleStrategy" ); replication.put( "replication_factor" , 1 ); session.execute(createKeyspace(keyspace).ifNotExists().with().replication(replication)); session.execute( "USE " + keyspace); } |
SchemaBuilder
приятен и прост в использовании и выглядит очень похожим на CQL. Мы добавляем предложение ifNotExists
и устанавливаем коэффициент репликации, сначала вызывая with
а затем передавая Map<String, Object>
в replicationMethod
. Эта карта должна содержать класс и коэффициент репликации, в основном используйте ключи, показанные здесь, но измените отображаемые значения так, как вам нужно. Не забудьте execute
инструкцию, а затем указать сеансу использовать только что созданное пространство ключей. К сожалению, нет лучшего способа установить пространство ключей по умолчанию вручную, и выполнение оператора USE
— единственный вариант.
В продолжение двух предыдущих опций, касающихся установки пространства клавиш по умолчанию. Если мы решим вообще не задавать пространство ключей по умолчанию, тогда нам нужно добавить пространство клавиш на каждую таблицу, которую мы создаем, и на каждый выполняемый запрос. Это не так сложно сделать, поскольку Datastax предоставляет способы добавления имен пространств ключей к запросам, а также к сущностям для отображения. Я не буду вдаваться в подробности этого вопроса, но знаю, что отсутствие настройки пространства клавиш не помешает работе вашего приложения, если вы все правильно настроили.
Как только пространство ключей установлено, мы можем приступить к созданию таблиц. Есть два возможных способа сделать это. Во-первых, выполнить несколько операторов CQL, будь то строки в вашем коде Java или чтение из внешнего сценария CQL. SchemaBuilder
, используйте SchemaBuilder
для их создания.
Давайте сначала посмотрим на выполнение операторов CQL или, точнее, на их выполнение из файла CQL. Вы могли заметить, что я оставил некоторый закомментированный код в исходном примере, когда без комментариев этот код найдет файл с именем setup.cql
, прочитает одну инструкцию CQL, выполнит ее и затем перейдет к следующей инструкции. Здесь это снова.
1
2
|
String[] statements = split(IOUtils.toString(getClass().getResourceAsStream( "/cql/setup.cql" )), ";" ); Arrays.stream(statements).map(statement -> normalizeSpace(statement) + ";" ).forEach(session::execute); |
Ниже приведен CQL, содержащийся в файле для создания таблицы Cassandra.
01
02
03
04
05
06
07
08
09
10
|
REATE TABLE IF NOT EXISTS people_by_country( country TEXT, first_name TEXT, last_name TEXT, id UUID, age INT , profession TEXT, salary INT , PRIMARY KEY ((country), first_name, last_name, id) ); |
Первичный ключ состоит из country
, имени, last_name
и поля id
. Ключ раздела состоит только из поля country
а столбцы кластеризации являются оставшимися ключами в ключе, id
включен только для уникальности, поскольку вы, очевидно, можете иметь людей с одинаковыми именами. Я более подробно расскажу о первичных ключах в моем предыдущем посте « Начало работы с Spring Data Cassandra» .
Этот код использует зависимости commons-io
и commons-lang3
. Если мы не выполняем CQL таким образом, эти зависимости могут быть удалены (в контексте этого поста).
Как насчет использования SchemaBuilder
? Я не включил никакого кода для создания таблицы в исходный фрагмент, потому что я играл и пытался найти лучшее место для его размещения, а пока я вставил его в репозиторий, но я все еще не уверен, что это идеальное место для этого. В любом случае, я вставлю сюда код, чтобы мы могли посмотреть на него сейчас, а затем пропустить его позже, когда он появится снова.
01
02
03
04
05
06
07
08
09
10
11
12
|
private void createTable(Session session) { session.execute( SchemaBuilder.createTable(TABLE) .ifNotExists() .addPartitionKey( "country" , text()) .addClusteringColumn( "first_name" , text()) .addClusteringColumn( "last_name" , text()) .addClusteringColumn( "id" , uuid()) .addColumn( "age" , cint()) .addColumn( "profession" , text()) .addColumn( "salary" , cint())); } |
Это очень хорошо согласуется с CQL, показанным выше. Мы можем определить различные типы столбцов, используя addPartitionKey
и addClusteringColumn
чтобы создать наш первичный ключ и addColumn
для стандартных полей. Существует множество других методов, таких как addStaticColumn
и withOptions
позволяют вам затем вызывать clusteringOrder
для определения направления сортировки ваших столбцов кластеризации. Порядок, в котором вы вызываете эти методы, очень важен, так как ключ раздела и столбцы кластеризации будут создаваться в порядке вызова их соответствующих методов. Datastax также предоставляет класс DataType
чтобы упростить определение типов столбцов, например, совпадения text
с TEXT
и cint
с INT
. Как и в прошлый раз, когда мы используем SchemaBuilder
, когда мы довольны дизайном таблицы, нам нужно ее execute
.
В MappingManager
приведен фрагмент для создания компонента.
1
2
3
4
5
6
7
8
9
|
@Bean public MappingManager mappingManager(Session session) { final PropertyMapper propertyMapper = new DefaultPropertyMapper() .setNamingStrategy( new DefaultNamingStrategy(LOWER_CAMEL_CASE, LOWER_SNAKE_CASE)); final MappingConfiguration configuration = MappingConfiguration.builder().withPropertyMapper(propertyMapper).build(); return new MappingManager(session, configuration); } |
MappingManager
компонент MappingManager
происходит из зависимости MappingManager
cassandra-driver-mapping
и сопоставляет ResultSet
с сущностью (о которой мы рассмотрим позже). На данный момент нам просто нужно создать бин. Если нас не устраивает стратегия присвоения имен по умолчанию, заключающаяся в преобразовании регистра верблюда Java во все строчные буквы без разделителей в Cassandra, нам нужно установить наш собственный. Для этого мы можем передать DefaultNamingStrategy
чтобы определить случай, который мы используем в наших классах Java и что мы используем в Cassandra. Поскольку в Java типично использовать случай верблюда, мы передаем в LOWER_CAMEL_CASE
и так как я люблю использовать случай змеи в Cassandra, мы можем использовать LOWER_SNAKE_CASE
(они находятся в классе NamingConventions
). Ссылка на lower указывает регистр первого символа в строке, поэтому LOWER_CAMEL_CASE
представляет firstName
а UPPER_CAMEL_CASE
представляет FirstName
. DefaultPropertyMapper
поставляется с дополнительными методами для более конкретной конфигурации, но у MappingConfiguration
есть только одна задача — взять PropertyMapper
для передачи в MappingManager
.
Следующее, на что мы должны обратить внимание — это объект, который будет сохранен и получен из Cassandra, что избавит нас от необходимости вручную устанавливать значения для вставок и преобразовывать результаты из операций чтения. Драйвер Datastax предоставляет нам относительно простой способ сделать это, используя аннотации для пометки свойств, таких как имя таблицы, в которую он отображается, какое поле соответствует тому, из каких столбцов Cassandra и из каких полей состоит первичный ключ.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
@Table (name = "people_by_country" ) public class Person { @PartitionKey private String country; @ClusteringColumn private String firstName; @ClusteringColumn ( 1 ) private String lastName; @ClusteringColumn ( 2 ) private UUID id; private int age; private String profession; private int salary; private Person() { } public Person(String country, String firstName, String lastName, UUID id, int age, String profession, int salary) { this .country = country; this .firstName = firstName; this .lastName = lastName; this .id = id; this .age = age; this .profession = profession; this .salary = salary; } // getters and setters for each property // equals, hashCode, toString } |
Этот объект представляет таблицу people_by_country
обозначенную @Table
. Я поставил CQL таблицы ниже для справки.
01
02
03
04
05
06
07
08
09
10
|
CREATE TABLE IF NOT EXISTS people_by_country( country TEXT, first_name TEXT, last_name TEXT, id UUID, age INT , profession TEXT, salary INT , PRIMARY KEY ((country), first_name, last_name, id) ); |
Аннотация @Table
должна указывать имя таблицы, которую представляет объект, она также поставляется с различными другими опциями, в зависимости от ваших требований, такими как keyspace
если вы не хотите использовать пространство ключей по умолчанию, для которого настроен компонент Session
и caseSensitiveTable
что самоочевидно.
Как насчет первичного ключа? Как уже упоминалось выше, первичный ключ состоит из ключа раздела, который сам содержит один или несколько столбцов и / или столбцов кластеризации. Чтобы соответствовать таблице Cassandra, определенной выше, мы добавили аннотации @PartitionKey
и @ClusteringColumn
в обязательные поля. Обе аннотации имеют одно свойство, value
которого указывает порядок появления столбца в первичном ключе. Значение по умолчанию равно 0
поэтому некоторые аннотации не содержат значения.
Последними требованиями для работы этой сущности являются геттеры, сеттеры и конструктор по умолчанию, чтобы маппер мог это делать. Конструктор по умолчанию может быть закрытым, если вы не хотите, чтобы кто-то обращался к нему, так как картограф использует отражение для его получения. Возможно, вы не захотите, чтобы на вашей сущности были сеттеры, поскольку вы хотели бы, чтобы объект был неизменным, к сожалению, вы ничего не можете с этим поделать, и вам просто придется уступить в этом бою. Хотя я лично считаю, что это нормально, поскольку вы можете (и, возможно, должны) преобразовать сущность в другой объект, который можно передавать вокруг вашего приложения без каких-либо аннотаций сущности и, следовательно, без знания самой базы данных. Затем объект можно оставить как изменяемый, а другой объект, который вы передаете, может работать именно так, как вы хотите.
И последнее, что я хочу упомянуть, прежде чем мы продолжим. Помните DefaultNamingConvention
мы определили ранее? Это означает, что наши поля сопоставляются с правильными столбцами без какой-либо дополнительной работы в сущности. Если вы этого не сделали или хотите указать другое имя поля, отличное от имени столбца, вы можете использовать аннотацию @Column
и указать его там.
У нас есть почти все компоненты, необходимые для создания нашего примера приложения. Предпоследний компонент создает репозиторий, который будет содержать всю логику для сохранения и чтения данных в Cassandra и из нее. Мы будем использовать MappingManager
компонент MappingManager
который мы создали ранее, и аннотации, которые мы помещаем в сущность, чтобы преобразовать ResultSet
в сущность без необходимости что-либо делать самостоятельно.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
@Repository public class PersonRepository { private Mapper<Person> mapper; private Session session; private static final String TABLE = "people_by_country" ; public PersonRepository(MappingManager mappingManager) { createTable(mappingManager.getSession()); this .mapper = mappingManager.mapper(Person. class ); this .session = mappingManager.getSession(); } private void createTable(Session session) { // use SchemaBuilder to create table } public Person find(String country, String firstName, String secondName, UUID id) { return mapper.get(country, firstName, secondName, id); } public List<Person> findAll() { final ResultSet result = session.execute(select().all().from(TABLE)); return mapper.map(result).all(); } public List<Person> findAllByCountry(String country) { final ResultSet result = session.execute(select().all().from(TABLE).where(eq( "country" , country))); return mapper.map(result).all(); } public void delete(String country, String firstName, String secondName, UUID id) { mapper.delete(country, firstName, secondName, id); } public Person save(Person person) { mapper.save(person); return person; } } |
MappingManager
через конструктор и вызвав метод mapper
для класса Person
, мы возвращаемся с Mapper<Person>
который будет лично обрабатывать все наши потребности в отображении. Нам также необходимо извлечь Session
чтобы иметь возможность выполнять запросы, которые приятно содержатся в MappingManager
нами MappingManager
.
Для трех запросов мы напрямую полагаемся на картограф, чтобы взаимодействовать с Cassandra, но это работает только для одной записи. get
, save
и delete
каждую работу, приняв значения, составляющие первичный ключ сущности Person
, и они должны быть введены в правильном порядке, иначе вы получите непредвиденные результаты, или будут выданы исключения.
В других ситуациях требуется, чтобы запрос был выполнен до того, как может быть вызван преобразователь для преобразования возвращенного ResultSet
в сущность или коллекцию сущностей. Я использовал QueryBuilder
для написания запросов, и я также выбрал для этого поста не писать готовые операторы. Хотя в большинстве случаев вам следует использовать подготовленные заявления, я подумал, что в будущем я QueryBuilder
них в отдельном посте, хотя они достаточно похожи, и QueryBuilder
все еще можно использовать, поэтому я уверен, что вы сможете разобраться с этим самостоятельно, если это необходимо.
QueryBuilder
предоставляет статические методы для создания операторов select
, insert
, update
и delete
которые затем могут быть объединены в цепочку (я знаю, это звучит очевидно) для построения запроса. Используемый здесь QueryBuilder
также является тем же, который вы можете использовать в Spring Data Cassandra, когда вам нужно вручную создавать свои собственные запросы, а не полагаться на предполагаемые запросы, поступающие из репозиториев Cassandra.
Последний шаг к созданию этого маленького приложения — это его запуск. Поскольку мы используем Spring Boot, мы просто добавляем стандартное @SpringBootApplication
и запускаем класс. Я сделал это ниже, а также использовал CommandLineRunner
для выполнения методов в репозитории, чтобы мы могли проверить, что они делают то, что мы ожидаем.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
@SpringBootApplication public class Application implements CommandLineRunner { @Autowired private PersonRepository personRepository; public static void main(String args[]) { SpringApplication.run(Application. class ); } @Override public void run(String... args) { final Person bob = new Person( "UK" , "Bob" , "Bobbington" , UUID.randomUUID(), 50 , "Software Developer" , 50000 ); final Person john = new Person( "UK" , "John" , "Doe" , UUID.randomUUID(), 30 , "Doctor" , 100000 ); personRepository.save(bob); personRepository.save(john); System.out.println( "Find all" ); personRepository.findAll().forEach(System.out::println); System.out.println( "Find one record" ); System.out.println(personRepository.find(john.getCountry(), john.getFirstName(), john.getLastName(), john.getId())); System.out.println( "Find all by country" ); personRepository.findAllByCountry( "UK" ).forEach(System.out::println); john.setProfession( "Unemployed" ); john.setSalary( 0 ); personRepository.save(john); System.out.println( "Demonstrating updating a record" ); System.out.println(personRepository.find(john.getCountry(), john.getFirstName(), john.getLastName(), john.getId())); personRepository.delete(john.getCountry(), john.getFirstName(), john.getLastName(), john.getId()); System.out.println( "Demonstrating deleting a record" ); System.out.println(personRepository.find(john.getCountry(), john.getFirstName(), john.getLastName(), john.getId())); } } |
Метод run
содержит несколько строк печати, поэтому мы можем видеть, что происходит, ниже показано, что они выводят.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
Find all Person{country= 'US' , firstName= 'Alice' , lastName= 'Cooper' , id =e113b6c2-5041-4575-9b0b-a0726710e82d, age=45, profession= 'Engineer' , salary=1000000} Person{country= 'UK' , firstName= 'Bob' , lastName= 'Bobbington' , id =d6af6b9a-341c-4023-acb5-8c22e0174da7, age=50, profession= 'Software Developer' , salary=50000} Person{country= 'UK' , firstName= 'John' , lastName= 'Doe' , id =f7015e45-34d7-4f25-ab25-ca3727df7759, age=30, profession= 'Doctor' , salary=100000} Find one record Person{country= 'UK' , firstName= 'John' , lastName= 'Doe' , id =f7015e45-34d7-4f25-ab25-ca3727df7759, age=30, profession= 'Doctor' , salary=100000} Find all by country Person{country= 'UK' , firstName= 'Bob' , lastName= 'Bobbington' , id =d6af6b9a-341c-4023-acb5-8c22e0174da7, age=50, profession= 'Software Developer' , salary=50000} Person{country= 'UK' , firstName= 'John' , lastName= 'Doe' , id =f7015e45-34d7-4f25-ab25-ca3727df7759, age=30, profession= 'Doctor' , salary=100000} Demonstrating updating a record Person{country= 'UK' , firstName= 'John' , lastName= 'Doe' , id =f7015e45-34d7-4f25-ab25-ca3727df7759, age=30, profession= 'Unemployed' , salary=0} Demonstrating deleting a record null |
Мы можем видеть, что findAll
возвратил все записи, а find
только извлек запись, которая соответствует входным значениям первичного ключа. findAllByCountry
исключил Алису и нашел только записи из Великобритании. Повторный вызов save
для существующей записи обновит запись, а не вставит. В конце концов delete
удалит данные человека из базы данных (например, удаление facebook?!?!).
И это упаковка.
Я постараюсь написать несколько последующих постов на эту тему в будущем, поскольку есть еще несколько интересных вещей, которые мы можем сделать с драйвером Datastax, которые мы не рассмотрели в этом посте. То, что мы рассмотрели здесь, должно быть достаточно, чтобы сделать первые шаги в использовании драйвера и начать запрашивать Cassandra из вашего приложения.
Прежде чем мы начнем, я хотел бы сделать несколько сравнений между драйвером Datastax и Spring Data Cassandra.
Поддержка создания таблиц отсутствует в драйвере Datastax (на мой взгляд) по сравнению с Spring Data Cassandra. Тот факт, что Spring Data может создавать ваши таблицы исключительно на основе ваших сущностей, устраняет все эти дополнительные усилия по переписыванию того, что вы уже написали. Очевидно, что если вы не хотите использовать аннотации сущностей, тогда разница исчезнет, поскольку вам нужно будет вручную создавать таблицы как в Datastax, так и в Spring Data.
Способ создания сущностей и используемые аннотации также весьма различны. Этот момент тесно связан с предыдущим пунктом, который я высказал. Поскольку Spring Data может создавать ваши таблицы для вас, у него больше потребность в более точных аннотациях, которые позволяют вам указывать структуру ваших таблиц, например порядок сортировки столбцов кластеризации. Это, очевидно, может загромождать класс множеством аннотаций, которые обычно не одобряются.
Spring Data также обеспечивает лучшую поддержку стандартных запросов, таких как findAll
и вставка коллекции сущностей. Очевидно, это еще не конец света, и для их реализации потребуется совсем немного усилий, но это в значительной степени подводит итог основного различия между драйвером Datastax и Spring Data Cassandra.
Spring Data проще в использовании. Я не думаю, что на самом деле есть что-то еще, чтобы сказать по этому вопросу. Поскольку Spring Data Cassandra построен на драйвере Datastax, он, очевидно, может делать все, что может драйвер, и если чего-то не хватает, то вы можете просто получить доступ к классам Datastax и делать то, что вам нужно. Но удобство, которое предоставляет Spring Data, не должно рассматриваться, и я не думаю, что я даже рассмотрел некоторые из наиболее полезных частей, которые он предоставляет, так как этот пост охватывает только основы. Даже не начинайте рассказывать о том, насколько проще, когда вы используете автоконфигурацию Spring Boot и предполагаемые запросы, которые генерируют для вас репозитории Cassandra.
Я должен остановиться … Это превращается в напыщенную речь.
В заключение, использование драйвера Datastax для подключения и запроса к базе данных Cassandra относительно простое. Установите соединение с Cassandra, создайте нужные вам сущности и напишите репозитории, использующие первое, тогда у вас есть все, что вам нужно для работы. Мы также сравнили драйвер Datastax с Spring Data Cassandra, к которому в значительной степени сводятся. Datastax сделает то, что вам нужно, но Spring Data сделает это проще.
Код, используемый в этом посте, можно найти на моем GitHub .
Если вы нашли этот пост полезным и хотите быть в курсе моих последних сообщений, вы можете подписаться на меня в твиттере на @LankyDanDev .
Опубликовано на Java Code Geeks с разрешения Дэна Ньютона, партнера нашей программы JCG . Смотрите оригинальную статью здесь: Взаимодействие с Cassandra с помощью драйвера Java Datastax
Мнения, высказанные участниками Java Code Geeks, являются их собственными. |