This is an automated email from the ASF dual-hosted git repository. dmagda pushed a commit to branch IGNITE-7595 in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/IGNITE-7595 by this push: new 0cb8389 Ported the Cassandra integration's documentation from readme.io to the new docs engine new fdef11c Merge remote-tracking branch 'origin/IGNITE-7595' into IGNITE-7595 0cb8389 is described below commit 0cb83898200e81c05fd6e90fb2b82473df3aba61 Author: Denis Magda <dma...@gridgain.com> AuthorDate: Wed Sep 30 16:39:41 2020 -0700 Ported the Cassandra integration's documentation from readme.io to the new docs engine --- docs/_data/toc.yaml | 10 + .../cassandra/configuration.adoc | 574 +++++++++++++++++ .../cassandra/ddl-generator.adoc | 85 +++ .../cassandra/overview.adoc | 40 ++ .../cassandra/usage-examples.adoc | 677 +++++++++++++++++++++ docs/_docs/persistence/external-storage.adoc | 10 +- 6 files changed, 1391 insertions(+), 5 deletions(-) diff --git a/docs/_data/toc.yaml b/docs/_data/toc.yaml index c68e4e8..6bd41f0 100644 --- a/docs/_data/toc.yaml +++ b/docs/_data/toc.yaml @@ -421,6 +421,16 @@ url: extensions-and-integrations/streaming/zeromq-streamer - title: Twitter Streamer url: extensions-and-integrations/streaming/twitter-streamer + - title: Cassandra Integration + items: + - title: Overview + url: extensions-and-integrations/cassandra/overview + - title: Configuration + url: extensions-and-integrations/cassandra/configuration + - title: Usage Examples + url: extensions-and-integrations/cassandra/usage-examples + - title: DDL Generator + url: extensions-and-integrations/cassandra/ddl-generator - title: C# and .NET Specific items: - title: Configuration Options diff --git a/docs/_docs/extensions-and-integrations/cassandra/configuration.adoc b/docs/_docs/extensions-and-integrations/cassandra/configuration.adoc new file mode 100644 index 0000000..d35d32d --- /dev/null +++ b/docs/_docs/extensions-and-integrations/cassandra/configuration.adoc @@ -0,0 +1,574 @@ += Ignite Cassandra Integration Configuration + += Overview + +To setup Cassandra as a persistent store, you need to set `CacheStoreFactory` for your Ignite caches to +`org.apache.ignite.cache.store.cassandra.CassandraCacheStoreFactory`. + +This could be done using Spring context configuration like this: + +[tabs] +-- +tab:XML[] +[source, xml] +---- +<bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration"> + <property name="cacheConfiguration"> + <list> + ... + <!-- Configuring persistence for "cache1" cache --> + <bean class="org.apache.ignite.configuration.CacheConfiguration"> + <property name="name" value="cache1"/> + <!-- Tune on Read-Through and Write-Through mode --> + <property name="readThrough" value="true"/> + <property name="writeThrough" value="true"/> + <!-- Specifying CacheStoreFactory --> + <property name="cacheStoreFactory"> + <bean class="org.apache.ignite.cache.store.cassandra.CassandraCacheStoreFactory"> + <!-- Datasource configuration bean which is responsible for Cassandra connection details --> + <property name="dataSourceBean" value="cassandraDataSource"/> + <!-- Persistent settings bean which is responsible for the details of how objects will be persisted to Cassandra --> + <property name="persistenceSettingsBean" value="cache1_persistence_settings"/> + </bean> + </property> + </bean> + ... + </list> + ... + </property> +</bean> +---- +-- + +There are two main properties which should be specified for `CassandraCacheStoreFactory`: + +* `dataSourceBean` - instance of the `org.apache.ignite.cache.store.cassandra.datasource.DataSource` class responsible for +all the aspects of Cassandra database connection (credentials, contact points, read/write consistency level, load balancing policy and etc...) +* `persistenceSettingsBean` - instance of the `org.apache.ignite.cache.store.cassandra.persistence.KeyValuePersistenceSettings` +class responsible for all the aspects of how objects should be persisted into Cassandra (keyspace and its options, table +and its options, partition and cluster key options, POJO object fields mapping, secondary indexes, serializer for BLOB objects and etc...) + +In the below section these two beans and their configuration settings will be described in details. + +== DataSourceBean + +This bean stores all the details required for Cassandra database connection and CRUD operations. In the table below you can find all the bean properties: + +[cols="20%,70%,10%",opts="header"] +|=== +| Property | Description | Default +| `user`| User name used to connect to Cassandra| +| `password`| User password used to connect to Cassandra| +| `credentials`| Credentials bean providing `username` and `password`| +| `authProvider`| Use the specified AuthProvider when connecting to Cassandra. Use this method when a custom authentication scheme is in place.| +| `port`| Port to use to connect to Cassandra (if it's not provided in connection point specification)| +| `contactPoints`| Array of contact points (`hostaname:[port]`) to use for Cassandra connection| +| `maxSchemaAgreementWaitSeconds`| Maximum time to wait for schema agreement before returning from a DDL query| `10` seconds +| `protocolVersion`| Specifies what version of Cassandra driver protocol should be used (could be helpful for backward compatibility with old versions of Cassandra)| `3` +| `compression`| Compression to use for the transport. Supported compressions: `snappy`, `lz4`| +| `useSSL`| Enables the use of SSL| `false` +| `sslOptions`| Enables the use of SSL using the provided options|`false` +| `collectMetrix`| Enables metrics collection|`false` +| `jmxReporting`| Enables JMX reporting of the metrics|`false` +| `fetchSize`| Specifies query fetch size. Fetch size controls how much resulting rows will be retrieved simultaneously.| +| `readConsistency`| Specifies consistency level for READ queries| +| `writeConsistency`| Specifies consistency level for WRITE/DELETE/UPDATE queries| +| `loadBalancingPolicy`| Specifies load balancing policy to use| `TokenAwarePolicy` +| `reconnectionPolicy`| Specifies reconnection policy to use| `ExponentialReconnectionPolicy` +| `retryPolicy`| Specifies retry policy to use| `DefaultRetryPolicy` +| `addressTranslater`| Specifies address translater to use| `IdentityTranslater` +| `speculativeExecutionPolicy`| Specifies speculative execution policy to use| `NoSpeculativeExecutionPolicy` +| `poolingOptions`| Specifies connection pooling options| +| `socketOptions`| Specifies low-level socket options for the connections kept to the Cassandra hosts| +| `nettyOptions`| Hooks that allow clients to customize Cassandra driver's underlying Netty layer| +|=== + + +== PersistenceSettingsBean + +This bean stores all the details(keyspace, table, partition options, POJO fields mapping and etc...) of how objects +(keys and values) should be persisted into Cassandra database. + +The constructor of `org.apache.ignite.cache.store.cassandra.persistence.KeyValuePersistenceSettings` allows to create such +a bean from a string which contains XML configuration document of specific structure (see below) or from the resource pointing to XML document. + +Here is the generic example of an XML configuration document (*persistence descriptor*) which specifies how Ignite cache +keys and values should be serialized/deserialized to/from Cassandra: + +[tabs] +-- +tab:XML[] +[source, xml] +---- +<!-- +Root container for persistence settings configuration. + +Note: required element + +Attributes: + 1) keyspace [required] - specifies keyspace for Cassandra tables which should be used to store key/value pairs + 2) table [required] - specifies Cassandra table which should be used to store key/value pairs + 3) ttl [optional] - specifies expiration period for the table rows (in seconds) +--> +<persistence keyspace="my_keyspace" table="my_table" ttl="86400"> + <!-- + Specifies Cassandra keyspace options which should be used to create provided keyspace if it doesn't exist. + + Note: optional element + --> + <keyspaceOptions> + REPLICATION = {'class' : 'SimpleStrategy', 'replication_factor' : 3} + AND DURABLE_WRITES = true + </keyspaceOptions> + + <!-- + Specifies Cassandra table options which should be used to create provided table if it doesn't exist. + + Note: optional element + --> + <tableOptions> + comment = 'A most excellent and useful table' + AND read_repair_chance = 0.2 + </tableOptions> + + <!-- + Specifies persistent settings for Ignite cache keys. + + Note: required element + + Attributes: + 1) class [required] - java class name for Ignite cache key + 2) strategy [required] - one of three possible persistent strategies: + a) PRIMITIVE - stores key value as is, by mapping it to Cassandra table column with corresponding type. + Should be used only for simple java types (int, long, String, double, Date) which could be mapped + to corresponding Cassadra types. + b) BLOB - stores key value as BLOB, by mapping it to Cassandra table column with blob type. + Could be used for any java object. Conversion of java object to BLOB is handled by "serializer" + which could be specified in serializer attribute (see below). + c) POJO - stores each field of an object as a column having corresponding type in Cassandra table. + Provides ability to utilize Cassandra secondary indexes for object fields. + 3) serializer [optional] - specifies serializer class for BLOB strategy. Shouldn't be used for PRIMITIVE and + POJO strategies. Available implementations: + a) org.apache.ignite.cache.store.cassandra.serializer.JavaSerializer - uses standard Java + serialization framework + b) org.apache.ignite.cache.store.cassandra.serializer.KryoSerializer - uses Kryo + serialization framework + 4) column [optional] - specifies column name for PRIMITIVE and BLOB strategies where to store key value. + If not specified column having 'key' name will be used. Shouldn't be used for POJO strategy. + --> + <keyPersistence class="org.mycompany.MyKeyClass" strategy="..." serializer="..." column="..."> + <!-- + Specifies partition key fields if POJO strategy used. + + Note: optional element, only required for POJO strategy in case you want to manually specify + POJO fields to Cassandra columns mapping, instead of relying on dynamic discovering of + POJO fields and mapping them to the same columns of Cassandra table. + --> + <partitionKey> + <!-- + Specifies mapping from POJO field to Cassandra table column. + + Note: required element + + Attributes: + 1) name [required] - POJO field name + 2) column [optional] - Cassandra table column name. If not specified lowercase + POJO field name will be used. + --> + <field name="companyCode" column="company" /> + ... + ... + </partitionKey> + + <!-- + Specifies cluster key fields if POJO strategy used. + + Note: optional element, only required for POJO strategy in case you want to manually specify + POJO fields to Cassandra columns mapping, instead of relying on dynamic discovering of + POJO fields and mapping them to the same columns of Cassandra table. + --> + <clusterKey> + <!-- + Specifies mapping from POJO field to Cassandra table column. + + Note: required element + + Attributes: + 1) name [required] - POJO field name + 2) column [optional] - Cassandra table column name. If not specified lowercase + POJO field name will be used. + 3) sort [optional] - specifies sort order (asc or desc) + --> + <field name="personNumber" column="number" sort="desc"/> + ... + ... + </clusterKey> + </keyPersistence> + + <!-- + Specifies persistent settings for Ignite cache values. + + Note: required element + + Attributes: + 1) class [required] - java class name for Ignite cache value + 2) strategy [required] - one of three possible persistent strategies: + a) PRIMITIVE - stores key value as is, by mapping it to Cassandra table column with corresponding type. + Should be used only for simple java types (int, long, String, double, Date) which could be mapped + to corresponding Cassadra types. + b) BLOB - stores key value as BLOB, by mapping it to Cassandra table column with blob type. + Could be used for any java object. Conversion of java object to BLOB is handled by "serializer" + which could be specified in serializer attribute (see below). + c) POJO - stores each field of an object as a column having corresponding type in Cassandra table. + Provides ability to utilize Cassandra secondary indexes for object fields. + 3) serializer [optional] - specifies serializer class for BLOB strategy. Shouldn't be used for PRIMITIVE and + POJO strategies. Available implementations: + a) org.apache.ignite.cache.store.cassandra.serializer.JavaSerializer - uses standard Java + serialization framework + b) org.apache.ignite.cache.store.cassandra.serializer.KryoSerializer - uses Kryo + serialization framework + 4) column [optional] - specifies column name for PRIMITIVE and BLOB strategies where to store value. + If not specified column having 'value' name will be used. Shouldn't be used for POJO strategy. + --> + <valuePersistence class="org.mycompany.MyValueClass" strategy="..." serializer="..." column=""> + <!-- + Specifies mapping from POJO field to Cassandra table column. + + Note: required element + + Attributes: + 1) name [required] - POJO field name + 2) column [optional] - Cassandra table column name. If not specified lowercase + POJO field name will be used. + 3) static [optional] - boolean flag which specifies that column is static withing a given partition + 4) index [optional] - boolean flag specifying that secondary index should be created for the field + 5) indexClass [optional] - custom index java class name if you want to use custom index + 6) indexOptions [optional] - custom index options + --> + <field name="firstName" column="first_name" static="..." index="..." indexClass="..." indexOptions="..."/> + ... + ... + </valuePersistence> +</persistence> +---- +-- + +Below are provided all the details about persistence descriptor configuration and its elements: + +=== persistence + +[CAUTION] +==== +[discrete] +=== ! Required Element +Root container for persistence settings configuration. +==== + +[cols="20%,20%,60%",opts="header"] +|=== +| Attribute | Required | Description +| `keyspace`| yes | Keyspace for Cassandra tables which should be used to store key/value pairs. If keyspace doesn't +exist it will be created (if specified Cassandra account has appropriate permissions). +| `table`| no | Cassandra table which should be used to store key/value pairs. If table doesn't exist it will be created +(if specified Cassandra account has appropriate permissions). If table name doesn't specified Ignite cache name will be used as a table name. +| `ttl`| no | Expiration period for the table rows (in seconds). +|=== + +In the next chapters you'll find what child elements could be placed inside persistence settings container. + +=== keyspaceOptions + +[NOTE] +==== +[discrete] +=== Optional Element +Options to create Cassandra keyspace specified in the `keyspace` attribute of persistence settings container. +==== + +Keyspace will be created only if it doesn't exist and if an account used to connect to Cassandra has appropriate permissions. + +The text specified in this XML element is just a chunk of +http://docs.datastax.com/en/cql/3.0/cql/cql_reference/create_keyspace_r.html[CREATE KEYSPACE, window=_blank] Cassandra DDL statement which goes after *WITH* keyword. + +=== tableOptions + +[NOTE] +==== +[discrete] +=== Optional Element +Options to create Cassandra table specified in the table attribute of persistence settings container. +==== + +A table will be created only if it doesn't exist and if an account used to connect to Cassandra has appropriate permissions. + +The text specified in this XML element is just a chunk of +http://docs.datastax.com/en/cql/3.0/cql/cql_reference/create_table_r.html[CREATE TABLE, window=_blank] Cassandra DDL statement which goes after *WITH* keyword. + +=== keyPersistence + +[CAUTION] +==== +[discrete] +=== ! Required Element +Persistent settings for Ignite cache keys. +==== + +These settings specify how key objects from Ignite cache should be stored/loaded to/from Cassandra table: + +[cols="20%,20%,60%",opts="header"] +|=== +| Attribute | Required | Description + +| `class` +| yes +| Java class name for Ignite cache keys. + +| `strategy` +| yes +| Specifies one of three possible persistent strategies (see below) which controls how object should be persisted/loaded to/from Cassandra table. + +| `serializer` +| no +| Serializer class for BLOB strategy (see below for available implementations). Shouldn't be used for PRIMITIVE and POJO strategies. + +| `column` +| no +| Column name for PRIMITIVE and BLOB strategies where to store key. If not specified, column having 'key' name will be +used. Attribute shouldn't be specified for POJO strategy. +|=== + +Persistence strategies: + +[cols="1,3",opts="header"] +|=== +| Name | Description + +| `PRIMITIVE` +| Stores object as is, by mapping it to Cassandra table column with corresponding type. Should be used only for simple java types +(int, long, String, double, Date) which could be directly mapped to corresponding Cassadra types. Use this +https://docs.datastax.com/en/developer/java-driver/4.4/manual/core/#cql-to-java-type-mapping[link, window=_blank] to figure out Java to Cassandra types mapping. + +| `BLOB` +| Stores object as BLOB, by mapping it to Cassandra table column with blob type. Could be used for any java object. +Conversion of java object to BLOB is handled by "serializer" which could be specified in serializer attribute of *keyPersistence* container. + +| `POJO` +| Stores each field of an object as a column having corresponding type in Cassandra table. Provides ability to utilize +Cassandra secondary indexes for object fields. Could be used only for POJO objects following Java Beans convention and +having their fields of https://docs.datastax.com/en/developer/java-driver/4.4/manual/core/#cql-to-java-type-mapping[simple java type which could be directly mapped to corresponding Cassandra types, window=_blank]. +|=== + +Available serializer implementations: + +[cols="1,3",opts="header"] +|=== +| Class | Description + +| `org.apache.ignite.cache.store.cassandra.serializer.JavaSerializer` +| Uses standard Java serialization framework + +| `org.apache.ignite.cache.store.cassandra.serializer.KryoSerializer` +| Uses Kryo serialization framework +|=== + +If you are using `PRIMITIVE` or `BLOB` persistence strategy you don't need to specify internal elements of `keyPersistence` +tag, cause the idea of these two strategies is that the whole object should be persisted into one column of Cassandra table +(which could be specified by `column` attribute). + +If you are using the `POJO` persistence strategy you have two option: + +* Leave `keyPersistence` tag empty - in a such case, all the fields of POJO object class will be detected automatically using such rules: + ** Only fields having simple java types which could be directly mapped to +http://docs.datastax.com/en/developer/java-driver/1.0/java-driver/reference/javaClass2Cql3Datatypes_r.html[appropriate Cassandra types, window=_blank] +will be detected. + ** Fields discovery mechanism takes into account `@QuerySqlField` annotation: + *** If `name` attribute is specified it will be used as a column name for Cassandra table. Otherwise field name in a lowercase will be used as a column name. + *** If `descending` attribute is specified for a field mapped to *cluster key* column, it will be used to set sort order for the column. + ** Fields discovery mechanism takes into account `@AffinityKeyMapped` annotation. All the fields marked by this annotation +will be treated as http://docs.datastax.com/en/cql/3.0/cql/ddl/ddl_compound_keys_c.html[partition key, window=_blank] +fields (in an order as they are declared in a class). All other fields will be treated as +http://docs.datastax.com/en/cql/3.0/cql/ddl/ddl_compound_keys_c.html[cluster key] fields. + ** If there are no fields annotated with `@AffinityKeyMapped` all the discovered fields will be treated as +http://docs.datastax.com/en/cql/3.0/cql/ddl/ddl_compound_keys_c.html[partition key, window=_blank] fields. +* Specify persistence details inside `keyPersistence` tag - in such case, you have to specify *partition key* fields +mapping to Cassandra table columns inside `partitionKey` tag. This tag is used just as a container for mapping settings +and doesn't have any attributes. Optionally (if you are going to use cluster key) you can also specify *cluster key* +fields mapping to appropriate Cassandra table columns inside `clusterKey` tag. This tag is used just as a container for +mapping settings and doesn't have any attributes. + +Next two sections are providing a detailed specification for `partition` and `cluster` key fields mappings (which makes +sense if you choose the second option from the list above). + +=== partitionKey + +[NOTE] +==== +[discrete] +=== Optional Element +Container for `field` elements specifying Cassandra partition key. +==== + +Defines the Ignite cache KEY object fields (inside it), which should be used as a *partition key* fields in Cassandra +table and specifies fields mappings to table columns. + +Mappings are specified by using `<field>` tag having such attributes: + +[cols="20%,20%,60%",opts="header"] +|=== +| Attribute | Required | Description + +| `name` +| yes +| POJO object field name. + +| `column` +| no +| Cassandra table column name. If not specified lowercase POJO field name will be used. +|=== + +=== clusterKey + +[NOTE] +==== +[discrete] +=== Optional Element +Container for `field` elements specifying Cassandra cluster key. +==== + +Defines the Ignite cache KEY object fields (inside it), which should be used as a *cluster key* fields in Cassandra +table and specifies fields mappings to table columns. + +Mapping are specified by using `<field>` tag having such attributes: + +[cols="20%,20%,60%",opts="header"] +|=== +| Attribute | Required | Description + +| `name` +| yes +| POJO object field name. + +| `column` +| no +| Cassandra table column name. If not specified lowercase POJO field name will be used. + + +| `sort` +| no +| Specifies sort order for the field (`asc` or `desc`). +|=== + +=== valuePersistence + +[CAUTION] +==== +[discrete] +=== ! Required Element +Persistent settings for Ignite cache values. +==== + +These settings specify how value objects from Ignite cache should be stored/loaded to/from Cassandra table. The settings attributes +look very similar to corresponding settings for Ignite cache keys: + +[cols="20%,20%,60%",opts="header"] +|=== +| Attribute | Required | Description + +| `class` +| yes +| Java class name for Ignite cache values. + +| `strategy` +| yes +| Specifies one of three possible persistent strategies (see below) which controls how object should be persisted/loaded to/from Cassandra table. + +| `serializer` +| no +| Serializer class for BLOB strategy (see below for available implementations). Shouldn't be used for `PRIMITIVE` and `POJO` strategies. + +| `column` +| no +| Column name for `PRIMITIVE` and `BLOB` strategies where to store value. If not specified, column having `value` name will be used. +Attribute shouldn't be specified for POJO strategy. +|=== + +Persistence strategies (same as for key persistence settings): + +[cols="1,3",opts="header"] +|=== +| Name | Description + +| `PRIMITIVE` +| Stores object as is, by mapping it to Cassandra table column with corresponding type. Should be used only for simple java types +(int, long, String, double, Date) which could be directly mapped to corresponding Cassadra types. Use this +http://docs.datastax.com/en/developer/java-driver/2.0/java-driver/reference/javaClass2Cql3Datatypes_r.html[link, window=_blank] to figure out Java to Cassandra types mapping. + +| `BLOB` +| Stores object as `BLOB`, by mapping it to Cassandra table column with blob type. Could be used for any java object. Conversion of +java object to `BLOB` is handled by "serializer" which could be specified in serializer attribute of `keyPersistence` container. + +| `POJO` +| Stores each field of an object as a column having a corresponding type in Cassandra table. Provides ability to utilize Cassandra +secondary indexes for object fields. Could be used only for POJO objects following Java Beans convention and having their fields +of http://docs.datastax.com/en/developer/java-driver/1.0/java-driver/reference/javaClass2Cql3Datatypes_r.html[simple java type which could be directly mapped to corresponding Cassandra types, window=_blank]. +|=== + +Available serializer implementations (same as for key persistence settings): + +[cols="1,3",opts="header"] +|=== +| Class | Description + +| `org.apache.ignite.cache.store.cassandra.serializer.JavaSerializer` +| Uses standard Java serialization framework. + +| `org.apache.ignite.cache.store.cassandra.serializer.KryoSerializer` +| Uses Kryo serialization framework. +|=== + +If you are using `PRIMITIVE` or `BLOB` persistence strategy you don't need to specify internal elements of `valuePersistence` +tag, cause the idea of these two strategies is that the whole object should be persisted into one column of Cassandra table +(which could be specified by `column` attribute). + +If you are using `POJO` persistence strategy you have two option (similar to the same options for keys): + +* Leave `valuePersistence` tag empty - in such a case, all the fields of POJO object class will be detected automatically using such rules: + ** Only fields having simple java types which could be directly mapped to +http://docs.datastax.com/en/developer/java-driver/1.0/java-driver/reference/javaClass2Cql3Datatypes_r.html[appropriate Cassandra types, window=_blank] will be detected. + ** Fields discovery mechanism takes into account `@QuerySqlField` annotation: + *** If `name` attribute is specified it will be used as a column name for Cassandra table. Otherwise, field name in a lower case will be used as a column name. + *** If `index` attribute is specified, secondary index will be created for a corresponding column in Cassandra table (if such table doesn't exist). +* Specify persistence details inside `valuePersistence` tag - in such a case, you have to specify your POJO fields mapping to Cassandra table columns +inside `valuePersistence` tag. + +If you selected the second option from the list above, you have to use `<field>` tag to specify POJO fields to Cassandra +table columns mapping. The tag has following attributes: + +[cols="20%,20%,60%",opts="header"] +|=== +| Attribute | Required | Description + +| `name` +| yes +| POJO object field name. + +| `column` +| no +| Cassandra table column name. If not specified lowercase POJO field name will be used. + +| `static` +| no +| Boolean flag which specifies that column is static withing a given partition. + +| `index` +| no +| Boolean flag specifying that secondary index should be created for the field. + +| `indexClass` +| no +| Custom index java class name, in case you want to use custom index. + +| `indexOptions` +| no +| Custom index options. +|=== diff --git a/docs/_docs/extensions-and-integrations/cassandra/ddl-generator.adoc b/docs/_docs/extensions-and-integrations/cassandra/ddl-generator.adoc new file mode 100644 index 0000000..4935648 --- /dev/null +++ b/docs/_docs/extensions-and-integrations/cassandra/ddl-generator.adoc @@ -0,0 +1,85 @@ += DDL Generator + +== Overview + +One of the benefits of the Ignite Cassandra integration is that you don't need to care about Cassandra DDL syntax for +table creation and Java to Cassandra type mapping details. + +You just need to create an XML configuration which specifies how Ignite cache keys and values should be serialized/deserialized to/from Cassandra. +Based on this settings all the absent Cassandra keyspaces and tables will be created automatically. The only requirement for all this "magic" to work: + +[CAUTION] +==== +[discrete] +=== +In connection settings for Cassandra, you should specify user having enough permissions to create keyspaces/tables +==== + +However, for some of the deployments it's not possible because of a very strict security policy. Thus the only solution in +a such situation is to provide DDL scripts for DevOps team to create all the necessary Cassandra keyspaces/tables in advance. + +That's the exact use-case for DDL generator utility that generates DDLs from +link:extensions-and-integrations/cassandra/configuration#persistencesettingsbean[PersistenceSettingsBean settings]. + +Below is a sample syntax for the Cassandra DDL generation: + +[tabs] +-- +tab:Shell[] +[source, shell] +---- +java org.apache.ignite.cache.store.cassandra.utils.DDLGenerator /opt/dev/ignite/persistence-settings-1.xml /opt/dev/ignite/persistence-settings-2.xml +---- +-- + +The generated DDL can look as follows: + +[tabs] +-- +tab:Generated Cassandra DDL[] +[source, sql] +---- +------------------------------------------------------------- +DDL for keyspace/table from file: /opt/dev/ignite/persistence-settings-1.xml +------------------------------------------------------------- + +create keyspace if not exists test1 +with replication = {'class' : 'SimpleStrategy', 'replication_factor' : 3} and durable_writes = true; + +create table if not exists test1.primitive_test1 +( + key int, + value int, + primary key ((key)) +); + +------------------------------------------------------------- +DDL for keyspace/table from file: /opt/dev/ignite/persistence-settings-2.xml +------------------------------------------------------------- + +create keyspace if not exists test1 +with REPLICATION = {'class' : 'SimpleStrategy', 'replication_factor' : 3} AND DURABLE_WRITES = true; + +create table if not exists test1.pojo_test3 +( + company text, + department text, + number int, + first_name text, + last_name text, + age int, + married boolean, + height bigint, + weight float, + birth_date timestamp, + phones blob, + primary key ((company, department), number) +) +with comment = 'A most excellent and useful table' AND read_repair_chance = 0.2 and clustering order by (number desc); +---- +-- + +Just don't forget to set the `CLASSPATH` environment variable correctly: + +. Include the jar file for Ignite Cassandra module (`ignite-cassandra-<version-number>.jar`) in your `CLASSPATH`. +. If you are using `POJO` persistence strategy for some of your custom java classes you need to include jars with these classes in your CLASSPATH as well. diff --git a/docs/_docs/extensions-and-integrations/cassandra/overview.adoc b/docs/_docs/extensions-and-integrations/cassandra/overview.adoc new file mode 100644 index 0000000..cbe3935 --- /dev/null +++ b/docs/_docs/extensions-and-integrations/cassandra/overview.adoc @@ -0,0 +1,40 @@ += Apache Cassandra Acceleration With Apache Ignite + +== Overview + +The Ignite Cassandra integration implements the link:persistence/external-storage#overview[CacheStore] interface allowing +to deploy Ignite as a high-performance caching layer on top of Cassandra. + +Some observations in regards to the integration: + +. The integration uses Cassandra http://www.datastax.com/dev/blog/java-driver-async-queries[asynchronous queries, window=_blank] +for `CacheStore` batch operations such as such as `loadAll()`, `writeAll()` and `deleteAll()` to provide extremely high performance. +. The integration automatically creates all necessary tables (and keyspaces) in Cassandra if they are absent. Also, it +automatically detects all the necessary fields for Ignite key-value tuples that will be stored as POJOs, and creates an +appropriate table structure. Thus you don't need to care about the Cassandra DDL syntax for table creation and Java to +Cassandra type mapping details. +. You can optionally specify the settings (replication factor, replication strategy, bloom filter and etc.) for Cassandra +tables and keyspaces which should be created. +. Combines functionality of BLOB and POJO storage, allowing to specify how you prefer to store (as a BLOB or as a POJO) +key-value tuples from your Ignite cache. +. Supports standard https://docs.oracle.com/javase/tutorial/jndi/objects/serial.html[Java, window=_blank] and +https://github.com/EsotericSoftware/kryo[Kryo, window=_blank] serialization for key-values which should be stored as BLOBs in Cassandra +. Supports Cassandra http://docs.datastax.com/en/cql/3.0/cql/cql_reference/create_index_r.html[secondary indexes, window=_blank] (including custom indexes) +through persistence configuration settings for particular Ignite cache or such settings could be detected automatically +if you configured link:SQL/indexes#configuring-indexes-using-annotations[SQL Indexes by Annotations] by using `@QuerySqlField(index = true)` annotation +. Supports sort order for Cassandra cluster key fields through persistence configuration settings or such settings could be +detected automatically if you are using `@QuerySqlField(descending = true)` annotation. +. Supports link:data-modeling/affinity-collocation[affinity co-location] for the POJO key classes having one of their fields +annotated by `@AffinityKeyMapped`. In such a way, key-values tuples which were stored on one node in an Ignite cache will +be also stored (co-located) on one node in Cassandra. + +[CAUTION] +==== +[discrete] +=== Ignite SQL Queries and Cassandra +Note that in order to execute SQL queries you need to have all the data loaded from Cassandra into an Ignite cluster. +The Ignite SQL engine doesn't assumes that all the records are available in memory and won't try to query Cassandra. + +An alternative would be to use Ignite Native Persistence - a distributed, ACID, and SQL-compliant disk store that allows +performing SQL queries on the data stored in-memory as well as on disk. +==== diff --git a/docs/_docs/extensions-and-integrations/cassandra/usage-examples.adoc b/docs/_docs/extensions-and-integrations/cassandra/usage-examples.adoc new file mode 100644 index 0000000..894228b --- /dev/null +++ b/docs/_docs/extensions-and-integrations/cassandra/usage-examples.adoc @@ -0,0 +1,677 @@ += Ignite Cassandra Integration Usage Examples + +== Overview + +As described in link:extensions-and-integrations/cassandra/configuration[configuration section], to configure Cassandra +as a cache store you need to set `CacheStoreFactory` for your Ignite caches to `org.apache.ignite.cache.store.cassandra.CassandraCacheStoreFactory`. + +Below is an example of a typical configuration for Ignite cache to use Cassandra as a cache store. We will go step-by-step +through all the configuration items, further down. The example is taken from the unit tests resource file +`store/src/test/resources/org/apache/ignite/tests/persistence/blob/ignite-config.xml` of the Cassandra module source code. + +[tabs] +-- +tab:XML[] +[source, xml] +---- +<?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation=" + http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans.xsd"> + + <!-- Cassandra connection settings --> + <import resource="classpath:org/apache/ignite/tests/cassandra/connection-settings.xml" /> + + <!-- Persistence settings for 'cache1' --> + <bean id="cache1_persistence_settings" class="org.apache.ignite.cache.store.cassandra.persistence.KeyValuePersistenceSettings"> + <constructor-arg type="org.springframework.core.io.Resource" value="classpath:org/apache/ignite/tests/persistence/blob/persistence-settings-1.xml" /> + </bean> + + <!-- Persistence settings for 'cache2' --> + <bean id="cache2_persistence_settings" class="org.apache.ignite.cache.store.cassandra.persistence.KeyValuePersistenceSettings"> + <constructor-arg type="org.springframework.core.io.Resource" value="classpath:org/apache/ignite/tests/persistence/blob/persistence-settings-3.xml" /> + </bean> + + <!-- Ignite configuration --> + <bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration"> + <property name="cacheConfiguration"> + <list> + <!-- Configuring persistence for "cache1" cache --> + <bean class="org.apache.ignite.configuration.CacheConfiguration"> + <property name="name" value="cache1"/> + <property name="readThrough" value="true"/> + <property name="writeThrough" value="true"/> + <property name="cacheStoreFactory"> + <bean class="org.apache.ignite.cache.store.cassandra.CassandraCacheStoreFactory"> + <property name="dataSourceBean" value="cassandraAdminDataSource"/> + <property name="persistenceSettingsBean" value="cache1_persistence_settings"/> + </bean> + </property> + </bean> + + <!-- Configuring persistence for "cache2" cache --> + <bean class="org.apache.ignite.configuration.CacheConfiguration"> + <property name="name" value="cache2"/> + <property name="readThrough" value="true"/> + <property name="writeThrough" value="true"/> + <property name="cacheStoreFactory"> + <bean class="org.apache.ignite.cache.store.cassandra.CassandraCacheStoreFactory"> + <property name="dataSourceBean" value="cassandraAdminDataSource"/> + <property name="persistenceSettingsBean" value="cache2_persistence_settings"/> + </bean> + </property> + </bean> + </list> + </property> + + <!-- Explicitly configure TCP discovery SPI to provide list of initial nodes. --> + <property name="discoverySpi"> + <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi"> + <property name="ipFinder"> + <!-- + Ignite provides several options for automatic discovery that can be used + instead os static IP based discovery. For information on all options refer + to our documentation: http://apacheignite.readme.io/docs/cluster-config + --> + <!-- Uncomment static IP finder to enable static-based discovery of initial nodes. --> + <!--<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">--> + <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder"> + <property name="addresses"> + <list> + <!-- In distributed environment, replace with actual host IP address. --> + <value>127.0.0.1:47500..47509</value> + </list> + </property> + </bean> + </property> + </bean> + </property> + </bean> +</beans> +---- +-- + +In the specified example we have two Ignite caches configured: `cache1` and `cache2`. So lets look at the configuration details. + +Lets start from the cache configuration details. They are pretty similar for both caches (`cache1` and `cache2`) and looks like that: + +[tabs] +-- +tab:XML[] +[source, xml] +---- +<bean class="org.apache.ignite.configuration.CacheConfiguration"> + <property name="name" value="cache1"/> + <property name="readThrough" value="true"/> + <property name="writeThrough" value="true"/> + <property name="cacheStoreFactory"> + <bean class="org.apache.ignite.cache.store.cassandra.CassandraCacheStoreFactory"> + <property name="dataSourceBean" value="cassandraAdminDataSource"/> + <property name="persistenceSettingsBean" value="cache1_persistence_settings"/> + </bean> + </property> +</bean> +---- +-- + +First of all we can see that `read-through` and `write-through` options are enabled: + +[tabs] +-- +tab:XML[] +[source, xml] +---- +<property name="readThrough" value="true"/> +<property name="writeThrough" value="true"/> +---- +-- + +which is required for Ignite cache, if you plan to use a persistent store for cache entries which expired. + +You can optionally specify the `write-behind` setting if you prefer persistent store to be updated asynchronously: + +[tabs] +-- +tab:XML[] +[source, xml] +---- +<property name="readThrough" value="true"/> +<property name="writeThrough" value="true"/> +---- +-- + +The next important thing is `CacheStoreFactory` configuration: + +[tabs] +-- +tab:XML[] +[source, xml] +---- +<property name="cacheStoreFactory"> + <bean class="org.apache.ignite.cache.store.cassandra.CassandraCacheStoreFactory"> + <property name="dataSourceBean" value="cassandraAdminDataSource"/> + <property name="persistenceSettingsBean" value="cache1_persistence_settings"/> + </bean> +</property> +---- +-- + +You should use `org.apache.ignite.cache.store.cassandra.CassandraCacheStoreFactory` as a `CacheStoreFactory` for your +Ignite caches to utilize Cassandra as a persistent store. For `CassandraCacheStoreFactory` you should specify two required properties: + +* `dataSourceBean` - name of the Spring bean, which specifies all the details about Cassandra database connection. + +* `persistenceSettingsBean` - name of the Spring bean, which specifies all the details about how objects should be persisted into Cassandra database. + +In the specified example `cassandraAdminDataSource` is a data source bean, which is imported into Ignite cache config file using this directive: + +[tabs] +-- +tab:XML[] +[source, xml] +---- +<import resource="classpath:org/apache/ignite/tests/cassandra/connection-settings.xml" /> +---- +-- + +and `cache1_persistence_settings` is a persistence settings bean, which is defined in Ignite cache config file using such directive: + +[tabs] +-- +tab:XML[] +[source, xml] +---- +<bean id="cache1_persistence_settings" class="org.apache.ignite.cache.store.cassandra.utils.persistence.KeyValuePersistenceSettings"> + <constructor-arg type="org.springframework.core.io.Resource" value="classpath:org/apache/ignite/tests/persistence/blob/persistence-settings-1.xml" /> +</bean> +---- +-- + +Now lets look at the specification of `cassandraAdminDataSource` from `store/src/test/resources/org/apache/ignite/tests/cassandra/connection-settings.xml` +test resource. + +Specifically,`CassandraAdminCredentials` and `CassandraRegularCredentials` are classes which extend +`org.apache.ignite.cache.store.cassandra.datasource.Credentials`. You are welcome to implement these classes and reference them afterwards. + +[tabs] +-- +tab:XML[] +[source, xml] +---- +<?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation=" + http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans.xsd"> + + <bean id="cassandraAdminCredentials" class="org.my.project.CassandraAdminCredentials"/> + <bean id="cassandraRegularCredentials" class="org.my.project.CassandraRegularCredentials"/> + + <bean id="loadBalancingPolicy" class="com.datastax.driver.core.policies.TokenAwarePolicy"> + <constructor-arg type="com.datastax.driver.core.policies.LoadBalancingPolicy"> + <bean class="com.datastax.driver.core.policies.RoundRobinPolicy"/> + </constructor-arg> + </bean> + + <bean id="contactPoints" class="org.apache.ignite.tests.utils.CassandraHelper" factory-method="getContactPointsArray"/> + + <bean id="cassandraAdminDataSource" class="org.apache.ignite.cache.store.cassandra.datasource.DataSource"> + <property name="credentials" ref="cassandraAdminCredentials"/> + <property name="contactPoints" ref="contactPoints"/> + <property name="readConsistency" value="ONE"/> + <property name="writeConsistency" value="ONE"/> + <property name="loadBalancingPolicy" ref="loadBalancingPolicy"/> + </bean> + + <bean id="cassandraRegularDataSource" class="org.apache.ignite.cache.store.cassandra.datasource.DataSource"> + <property name="credentials" ref="cassandraRegularCredentials"/> + <property name="contactPoints" ref="contactPoints"/> + <property name="readConsistency" value="ONE"/> + <property name="writeConsistency" value="ONE"/> + <property name="loadBalancingPolicy" ref="loadBalancingPolicy"/> + </bean> +</beans> +---- +-- + +For more details about Cassandra data source connection configuration visit the link:extensions-and-integrations/cassandra/configuration[integration configuration page]. + +Finally, the last piece which wasn't still described is persistence settings configuration. Lets look at the +`cache1_persistence_settings` from the `org/apache/ignite/tests/persistence/blob/persistence-settings-1.xml` test resource. + +[tabs] +-- +tab:XML[] +[source, xml] +---- +<persistence keyspace="test1" table="blob_test1"> + <keyPersistence class="java.lang.Integer" strategy="PRIMITIVE" /> + <valuePersistence strategy="BLOB"/> +</persistence> +---- +-- + +In the configuration above, we can see that Cassandra `test1.blob_test1` table will be used to store key/value objects for +**cache1** cache. Key objects of the cache will be stored as **integer** in `key` column. Value objects of the cache will be +stored as **blob** in `value` column. For more information about persistence settings configuration visit the +link:extensions-and-integrations/cassandra/configuration[integration configuration page]. + +Next sections will provide examples of persistence settings configuration for different kind of persistence strategies +(see more details about persistence strategies on the link:extensions-and-integrations/cassandra/configuration[integration configuration page]. + +== Example 1 + +Persistence setting for Ignite cache with keys of `Integer` type to be persisted as `int` in Cassandra and values of +`String` type to be persisted as `text` in Cassandra. + +[tabs] +-- +tab:XML[] +[source, xml] +---- +<persistence keyspace="test1" table="my_table"> + <keyPersistence class="java.lang.Integer" strategy="PRIMITIVE" column="my_key"/> + <valuePersistence class="java.lang.String" strategy="PRIMITIVE" /> +</persistence> +---- +-- + +Keys will be stored in `my_key` column. Values will be stored in `value` column (which is used by default if `column` attribute wasn't specified). + +== Example 2 + +Persistence setting for Ignite cache with keys of `Integer` type to be persisted as `int` in Cassandra and values of `any` +type (you don't need to specify the type for **BLOB** persistence strategy) to be persisted as `blob` in Cassandra. +The only solution for this situation is to store value as a `BLOB` in Cassandra table. + +[tabs] +-- +tab:XML[] +[source, xml] +---- +<persistence keyspace="test1" table="my_table"> + <keyPersistence class="java.lang.Integer" strategy="PRIMITIVE" /> + <valuePersistence strategy="BLOB"/> +</persistence> +---- +-- + +Keys will be stored in `key` column (which is used by default if `column` attribute wasn't specified). Values will be stored in `value` column. + +== Example 3 + +Persistence setting for Ignite cache with keys of `Integer` type and values of **any** type, both to be persisted as `BLOB` in Cassandra. + +[tabs] +-- +tab:XML[] +[source, xml] +---- +<persistence keyspace="test1" table="my_table"> + <!-- By default Java standard serialization is going to be used --> + <keyPersistence class="java.lang.Integer" + strategy="BLOB"/> + + <!-- Kryo serialization specified to be used --> + <valuePersistence class="org.apache.ignite.tests.pojos.Person" + strategy="BLOB" + serializer="org.apache.ignite.cache.store.cassandra.serializer.KryoSerializer"/> +</persistence> +---- +-- + +Keys will be stored in `key` column having `blob` type and using +https://docs.oracle.com/javase/tutorial/jndi/objects/serial.html[Java standard serialization, window=_blank]. Values will be stored in +`value` column having `blob` type and using https://github.com/EsotericSoftware/kryo[Kryo serialization, window=_blank]. + +== Example 4 + +Persistence setting for Ignite cache with keys of `Integer` type to be persisted as `int` in Cassandra and values of custom +POJO `org.apache.ignite.tests.pojos.Person` type to be dynamically analyzed and persisted into a set of table columns, +so that each POJO field will be mapped to appropriate table column. For more details about dynamic POJO fields discovery +refer to link:extensions-and-integrations/cassandra/configuration#persistencesettingsbean[PersistenceSettingsBean] documentation section. + +[tabs] +-- +tab:XML[] +[source, xml] +---- +<persistence keyspace="test1" table="my_table"> + <keyPersistence class="java.lang.Integer" strategy="PRIMITIVE"/> + <valuePersistence class="org.apache.ignite.tests.pojos.Person" strategy="POJO"/> +</persistence> +---- +-- + +Keys will be stored in `key` column having `int` type. + +Now lets imagine that the `org.apache.ignite.tests.pojos.Person` class has such an implementation: + +[tabs] +-- +tab:Java[] +[source, java] +---- +public class Person { + private String firstName; + private String lastName; + private int age; + private boolean married; + private long height; + private float weight; + private Date birthDate; + private List<String> phones; + + public void setFirstName(String name) { + firstName = name; + } + + public String getFirstName() { + return firstName; + } + + public void setLastName(String name) { + lastName = name; + } + + public String getLastName() { + return lastName; + } + + public void setAge(int age) { + this.age = age; + } + + public int getAge() { + return age; + } + + public void setMarried(boolean married) { + this.married = married; + } + + public boolean getMarried() { + return married; + } + + public void setHeight(long height) { + this.height = height; + } + + public long getHeight() { + return height; + } + + public void setWeight(float weight) { + this.weight = weight; + } + + public float getWeight() { + return weight; + } + + public void setBirthDate(Date date) { + birthDate = date; + } + + public Date getBirthDate() { + return birthDate; + } + + public void setPhones(List<String> phones) { + this.phones = phones; + } + + public List<String> getPhones() { + return phones; + } +} +---- +-- + +In this case Ignite cache values of the `org.apache.ignite.tests.pojos.Person` type will be persisted into a set of +Cassandra table columns using such dynamically configured mapping rule: + +[opts="header"] +|=== +| POJO field | Table column | Column type +| firstName | firstname | text +| lastName | lastname | text +| age | age | int +| married | married | boolean +| height | height | bigint +| weight | weight | float +| birthDate | birthdate | timestamp +|=== + +As you can see from the table above, `phones` field will not be persisted into table. That's because it's not of simple +java type which could be directly mapped to http://docs.datastax.com/en/developer/java-driver/1.0/java-driver/reference/javaClass2Cql3Datatypes_r.html[appropriate, window=_blank] Cassandra type. +Such kind of fields could be persisted into Cassandra only if you manually specify all mapping details for the object type +and if field type itself is implementing `java.io.Serializable` interface. In a such case field will be persisted into a +separate table column as `blob`. See more details in the next example. + +== Example 5 + +Persistence setting for Ignite cache with keys of custom POJO `org.apache.ignite.tests.pojos.PersonId` and values of +custom POJO `org.apache.ignite.tests.pojos.Person` types, both to be persisted into a set of table columns based on +manually specified mapping rules. + +[tabs] +-- +tab:XML[] +[source, xml] +---- +<persistence keyspace="test1" table="my_table" ttl="86400"> + <!-- Cassandra keyspace options which should be used to create provided keyspace if it doesn't exist --> + <keyspaceOptions> + REPLICATION = {'class' : 'SimpleStrategy', 'replication_factor' : 3} + AND DURABLE_WRITES = true + </keyspaceOptions> + + <!-- Cassandra table options which should be used to create provided table if it doesn't exist --> + <tableOptions> + comment = 'A most excellent and useful table' + AND read_repair_chance = 0.2 + </tableOptions> + + <!-- Persistent settings for Ignite cache keys --> + <keyPersistence class="org.apache.ignite.tests.pojos.PersonId" strategy="POJO"> + <!-- Partition key fields if POJO strategy used --> + <partitionKey> + <!-- Mapping from POJO field to Cassandra table column --> + <field name="companyCode" column="company" /> + <field name="departmentCode" column="department" /> + </partitionKey> + + <!-- Cluster key fields if POJO strategy used --> + <clusterKey> + <!-- Mapping from POJO field to Cassandra table column --> + <field name="personNumber" column="number" sort="desc"/> + </clusterKey> + </keyPersistence> + + <!-- Persistent settings for Ignite cache values --> + <valuePersistence class="org.apache.ignite.tests.pojos.Person" + strategy="POJO" + serializer="org.apache.ignite.cache.store.cassandra.serializer.KryoSerializer"> + <!-- Mapping from POJO field to Cassandra table column --> + <field name="firstName" column="first_name" /> + <field name="lastName" column="last_name" /> + <field name="age" /> + <field name="married" index="true"/> + <field name="height" /> + <field name="weight" /> + <field name="birthDate" column="birth_date" /> + <field name="phones" /> + </valuePersistence> +</persistence> +---- +-- + +These persistence settings looks rather complicated. Lets go step by step and analyse them. + +Lets first look at the root tag: + +[tabs] +-- +tab:XML[] +[source, xml] +---- +<persistence keyspace="test1" table="my_table" ttl="86400"> +---- +-- + +It specifies that Ignite cache keys and values should be stored in `test1.my_table` table and that data in each row +http://docs.datastax.com/en/cql/3.1/cql/cql_using/use_expire_c.html[expires, window=_blank] after `86400` sec which is `24` hours. + +Then we can see the advanced settings for Cassandra keyspace. The setting will be used to create keyspace if it's not exist. + +[tabs] +-- +tab:XML[] +[source, xml] +---- +<keyspaceOptions> + REPLICATION = {'class' : 'SimpleStrategy', 'replication_factor' : 3} + AND DURABLE_WRITES = true +</keyspaceOptions> +---- +-- + +Then by analogy to keyspace setting we can see table advanced setting, which will be used only for table creation. + +[tabs] +-- +tab:XML[] +[source, xml] +---- +<tableOptions> + comment = 'A most excellent and useful table' + AND read_repair_chance = 0.2 +</tableOptions> +---- +-- + +Next section specifies how Ignite cache keys should be persisted: + +[tabs] +-- +tab:XML[] +[source, xml] +---- +<keyPersistence class="org.apache.ignite.tests.pojos.PersonId" strategy="POJO"> + <!-- Partition key fields if POJO strategy used --> + <partitionKey> + <!-- Mapping from POJO field to Cassandra table column --> + <field name="companyCode" column="company" /> + <field name="departmentCode" column="department" /> + </partitionKey> + + <!-- Cluster key fields if POJO strategy used --> + <clusterKey> + <!-- Mapping from POJO field to Cassandra table column --> + <field name="personNumber" column="number" sort="desc"/> + </clusterKey> +</keyPersistence> +---- +-- + +Lets assume that `org.apache.ignite.tests.pojos.PersonId` has such implementation: + +[tabs] +-- +tab:Java[] +[source, java] +---- +public class PersonId { + private String companyCode; + private String departmentCode; + private int personNumber; + + public void setCompanyCode(String code) { + companyCode = code; + } + + public String getCompanyCode() { + return companyCode; + } + + public void setDepartmentCode(String code) { + departmentCode = code; + } + + public String getDepartmentCode() { + return departmentCode; + } + + public void setPersonNumber(int number) { + personNumber = number; + } + + public int getPersonNumber() { + return personNumber; + } +} +---- +-- + +In such case Ignite cache keys of `org.apache.ignite.tests.pojos.PersonId` type will be persisted into a set of Cassandra +table columns representing `PARTITION` and `CLUSTER` key using this mapping rule: + +[opts="header"] +|=== +| POJO field | Table column | Column type +| companyCode | company | text +| departmentCode | department | text +| personNumber | number | int +|=== + +In addition to that, combination of columns `(company, department)` will be used as Cassandra `PARTITION` key and column +`number` will be used as a `CLUSTER` key sorted in descending order. + +Finally lets move to the last section, which specifies persistence settings for Ignite cache values: + +[tabs] +-- +tab:XML[] +[source, xml] +---- +<valuePersistence class="org.apache.ignite.tests.pojos.Person" + strategy="POJO" + serializer="org.apache.ignite.cache.store.cassandra.serializer.KryoSerializer"> + <!-- Mapping from POJO field to Cassandra table column --> + <field name="firstName" column="first_name" /> + <field name="lastName" column="last_name" /> + <field name="age" /> + <field name="married" index="true"/> + <field name="height" /> + <field name="weight" /> + <field name="birthDate" column="birth_date" /> + <field name="phones" /> +</valuePersistence> +---- +-- + +Lets assume `that org.apache.ignite.tests.pojos.Person` class has the same implementation like in link:extensions-and-integrations/cassandra/usage-examples#example-4[Example 4]. +In this case Ignite cache values of `org.apache.ignite.tests.pojos.Person` type will be persisted into a set of Cassandra +table columns using such mapping rule: + +[opts="header"] +|=== +| POJO field | Table column | Column type +| firstName | first_name | text +| lastName | last_name | text +| age | age | int +| married | married | boolean +| height | height | bigint +| weight | weight | float +| birthDate | birth_date | timestamp +| phones | phones | blob +|=== + +Comparing to link:extensions-and-integrations/cassandra/usage-examples#example-4[Example 4] we can see that now `phones` +field will be serialized to `phones` column of `blob` type using https://github.com/EsotericSoftware/kryo[Kryo, window=_blank] serializer. +In addition to that, Cassandra secondary index will be created for the `married` column. diff --git a/docs/_docs/persistence/external-storage.adoc b/docs/_docs/persistence/external-storage.adoc index b163ab8..47188ad2 100644 --- a/docs/_docs/persistence/external-storage.adoc +++ b/docs/_docs/persistence/external-storage.adoc @@ -196,12 +196,12 @@ CAUTION: Even though Ignite supports distributed transactions, it doesn't make y === Cassandra Integration -Ignite provides an out-of-the-box implementation of `CacheStore` that enables you to use Apache Cassandra as a persistent storage. This implementation utilizes Cassandra's link:http://www.datastax.com/dev/blog/java-driver-async-queries[asynchronous queries] to provide high performance batch operations such as `loadAll()`, `writeAll()` and `deleteAll()`, and automatically creates all necessary tables and namespaces in Cassandra. +Ignite provides an out-of-the-box implementation of `CacheStore` that enables you to use Apache Cassandra as a persistent +storage. This implementation utilizes Cassandra's link:http://www.datastax.com/dev/blog/java-driver-async-queries[asynchronous queries, window=_blank] +to provide high performance batch operations such as `loadAll()`, `writeAll()` and `deleteAll()`, and automatically creates +all necessary tables and namespaces in Cassandra. -//// -TODO -Refer to the dedicated section on Cassandra integration for more information. -//// +Refer to link:extensions-and-integrations/cassandra/overview[this documentation section] for configuration and usage guidelines. //// == Implementing Custom CacheStore