Repository: ignite
Updated Branches:
  refs/heads/ignite-5368 [created] 485191f36


ignite-5368


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/d44fdd45
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/d44fdd45
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/d44fdd45

Branch: refs/heads/ignite-5368
Commit: d44fdd452125a7735ec4718b18a7dcea5a95f471
Parents: fbcd474
Author: Igor Rudyak <irud...@gmail.com>
Authored: Fri Jun 2 22:54:15 2017 -0700
Committer: Igor Rudyak <irud...@gmail.com>
Committed: Fri Jun 2 22:54:15 2017 -0700

----------------------------------------------------------------------
 .../cassandra/common/PropertyMappingHelper.java |  73 +++-----
 .../persistence/KeyPersistenceSettings.java     | 155 +++++-----------
 .../persistence/PersistenceSettings.java        |  83 ++++++++-
 .../store/cassandra/persistence/PojoField.java  | 129 +++++++------
 .../persistence/PojoFieldAccessor.java          | 162 ++++++++++++++++
 .../cassandra/persistence/PojoKeyField.java     |  13 +-
 .../cassandra/persistence/PojoValueField.java   |  12 +-
 .../persistence/ValuePersistenceSettings.java   |  50 +----
 .../store/cassandra/utils/DDLGenerator.java     |   9 +-
 .../tests/CassandraDirectPersistenceTest.java   |  73 +++++++-
 .../apache/ignite/tests/DDLGeneratorTest.java   |   4 +
 .../ignite/tests/IgnitePersistentStoreTest.java |  85 ++++++++-
 .../apache/ignite/tests/pojos/SimplePerson.java | 186 +++++++++++++++++++
 .../ignite/tests/pojos/SimplePersonId.java      |  89 +++++++++
 .../apache/ignite/tests/utils/TestsHelper.java  |  97 +++++++++-
 .../tests/persistence/pojo/ignite-config.xml    |  36 ++++
 .../persistence/pojo/persistence-settings-5.xml |  21 +++
 .../persistence/pojo/persistence-settings-6.xml | 174 +++++++++++++++++
 18 files changed, 1158 insertions(+), 293 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/d44fdd45/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/common/PropertyMappingHelper.java
----------------------------------------------------------------------
diff --git 
a/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/common/PropertyMappingHelper.java
 
b/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/common/PropertyMappingHelper.java
index cb89bf0..66d7294 100644
--- 
a/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/common/PropertyMappingHelper.java
+++ 
b/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/common/PropertyMappingHelper.java
@@ -20,17 +20,17 @@ package org.apache.ignite.cache.store.cassandra.common;
 import com.datastax.driver.core.DataType;
 import com.datastax.driver.core.Row;
 import java.beans.PropertyDescriptor;
+import java.lang.reflect.Field;
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.net.InetAddress;
 import java.nio.ByteBuffer;
-import java.util.ArrayList;
 import java.util.Date;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.ignite.cache.store.cassandra.persistence.PojoFieldAccessor;
 import org.apache.ignite.cache.store.cassandra.serializer.Serializer;
 
 /**
@@ -77,63 +77,38 @@ public class PropertyMappingHelper {
     }
 
     /**
-     * Returns property descriptor by class property name.
+     * Returns property accessor by class property name.
      *
-     * @param clazz class from which to get property descriptor.
+     * @param clazz class from which to get property accessor.
      * @param prop name of the property.
      *
-     * @return property descriptor.
+     * @return property accessor.
      */
-    public static PropertyDescriptor getPojoPropertyDescriptor(Class clazz, 
String prop) {
-        List<PropertyDescriptor> descriptors = 
getPojoPropertyDescriptors(clazz, false);
-
-        if (descriptors == null || descriptors.isEmpty())
-            throw new IllegalArgumentException("POJO class " + clazz.getName() 
+ " doesn't have '" + prop + "' property");
-
-        for (PropertyDescriptor descriptor : descriptors) {
-            if (descriptor.getName().equals(prop))
-                return descriptor;
-        }
-
-        throw new IllegalArgumentException("POJO class " + clazz.getName() + " 
doesn't have '" + prop + "' property");
-    }
-
-    /**
-     * Extracts all property descriptors from a class.
-     *
-     * @param clazz class which property descriptors should be extracted.
-     * @param primitive boolean flag indicating that only property descriptors 
for primitive properties
-     *      should be extracted.
-     *
-     * @return list of class property descriptors
-     */
-    public static List<PropertyDescriptor> getPojoPropertyDescriptors(Class 
clazz, boolean primitive) {
+    public static PojoFieldAccessor getPojoFieldAccessor(Class clazz, String 
prop) {
         PropertyDescriptor[] descriptors = 
PropertyUtils.getPropertyDescriptors(clazz);
 
-        List<PropertyDescriptor> list = new ArrayList<>(descriptors == null ? 
1 : descriptors.length);
+        if (descriptors != null) {
+            for (PropertyDescriptor descriptor : descriptors) {
+                if (descriptor.getName().equals(prop)) {
+                    Field field = null;
 
-        if (descriptors == null || descriptors.length == 0)
-            return list;
+                    try {
+                        field = clazz.getDeclaredField(prop);
+                    }
+                    catch (Throwable ignore) {
+                    }
 
-        for (PropertyDescriptor descriptor : descriptors) {
-            if (descriptor.getReadMethod() == null || (primitive && 
!isPrimitivePropertyDescriptor(descriptor)))
-                continue;
-
-            list.add(descriptor);
+                    return new PojoFieldAccessor(descriptor, field);
+                }
+            }
         }
 
-        return list;
-    }
-
-    /**
-     * Checks if property descriptor describes primitive property (int, 
boolean, long and etc.)
-     *
-     * @param desc property descriptor.
-     *
-     * @return {@code true} property is primitive
-     */
-    public static boolean isPrimitivePropertyDescriptor(PropertyDescriptor 
desc) {
-        return 
PropertyMappingHelper.JAVA_TO_CASSANDRA_MAPPING.containsKey(desc.getPropertyType());
+        try {
+            return new PojoFieldAccessor(clazz.getDeclaredField(prop));
+        }
+        catch (Throwable e) {
+            throw new IllegalArgumentException("POJO class " + clazz.getName() 
+ " doesn't have '" + prop + "' property");
+        }
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/d44fdd45/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/persistence/KeyPersistenceSettings.java
----------------------------------------------------------------------
diff --git 
a/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/persistence/KeyPersistenceSettings.java
 
b/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/persistence/KeyPersistenceSettings.java
index c12c3e8..2f2e18e 100644
--- 
a/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/persistence/KeyPersistenceSettings.java
+++ 
b/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/persistence/KeyPersistenceSettings.java
@@ -17,12 +17,10 @@
 
 package org.apache.ignite.cache.store.cassandra.persistence;
 
-import java.beans.PropertyDescriptor;
 import java.util.LinkedList;
 import java.util.List;
 
-import org.apache.ignite.IgniteException;
-import org.apache.ignite.cache.store.cassandra.common.PropertyMappingHelper;
+import org.apache.ignite.cache.affinity.AffinityKeyMapped;
 import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
 
@@ -62,26 +60,53 @@ public class KeyPersistenceSettings extends 
PersistenceSettings {
             return;
         }
 
-        NodeList keyElem = el.getElementsByTagName(PARTITION_KEY_ELEMENT);
+        Element node = el.getElementsByTagName(PARTITION_KEY_ELEMENT) != null ?
+                
(Element)el.getElementsByTagName(PARTITION_KEY_ELEMENT).item(0) : null;
 
-        Element partKeysNode = keyElem != null ? (Element) keyElem.item(0) : 
null;
+        NodeList partKeysNodes = node == null ? null : 
node.getElementsByTagName(FIELD_ELEMENT);
 
-        Element clusterKeysNode = el.getElementsByTagName(CLUSTER_KEY_ELEMENT) 
!= null ?
-            (Element)el.getElementsByTagName(CLUSTER_KEY_ELEMENT).item(0) : 
null;
+        node = el.getElementsByTagName(CLUSTER_KEY_ELEMENT) != null ?
+                (Element)el.getElementsByTagName(CLUSTER_KEY_ELEMENT).item(0) 
: null;
 
-        if (partKeysNode == null && clusterKeysNode != null) {
+        NodeList clusterKeysNodes = node == null ? null : 
node.getElementsByTagName(FIELD_ELEMENT);
+
+        if ((partKeysNodes == null || partKeysNodes.getLength() == 0) &&
+                clusterKeysNodes != null && clusterKeysNodes.getLength() > 0) {
             throw new IllegalArgumentException("It's not allowed to specify 
cluster key fields mapping, but " +
                 "doesn't specify partition key mappings");
         }
 
-        partKeyFields = detectFields(partKeysNode, 
getPartitionKeyDescriptors());
+        // Detecting partition key fields
+        partKeyFields = detectPojoFields(partKeysNodes);
 
         if (partKeyFields == null || partKeyFields.isEmpty()) {
             throw new IllegalStateException("Failed to initialize partition 
key fields for class '" +
-                getJavaClass().getName() + "'");
+                    getJavaClass().getName() + "'");
+        }
+
+        List<PojoField> filteredFields = new LinkedList<>();
+
+        // Find all fields annotated by @AffinityKeyMapped
+        for (PojoField field : partKeyFields) {
+            if (field.getAnnotation(AffinityKeyMapped.class) != null)
+                filteredFields.add(field);
         }
 
-        clusterKeyFields = detectFields(clusterKeysNode, 
getClusterKeyDescriptors(partKeyFields));
+        // If there are any fields annotated by @AffinityKeyMapped then all 
other fields are part of cluster key
+        partKeyFields = !filteredFields.isEmpty() ? filteredFields : 
partKeyFields;
+
+        // Detecting cluster key fields
+        clusterKeyFields = detectPojoFields(clusterKeysNodes);
+
+        filteredFields = new LinkedList<>();
+
+        // Removing out all fields which are already in partition key fields 
list
+        for (PojoField field : clusterKeyFields) {
+            if (!PojoField.containsField(partKeyFields, field.getName()))
+                filteredFields.add(field);
+        }
+
+        clusterKeyFields = filteredFields;
 
         fields = new LinkedList<>();
         fields.addAll(partKeyFields);
@@ -97,6 +122,16 @@ public class KeyPersistenceSettings extends 
PersistenceSettings {
         return fields;
     }
 
+    /** {@inheritDoc} */
+    @Override protected PojoField createPojoField(Element el, Class clazz) {
+        return new PojoKeyField(el, clazz);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected PojoField createPojoField(PojoFieldAccessor accessor) {
+        return new PojoKeyField(accessor);
+    }
+
     /**
      * Returns Cassandra DDL for primary key.
      *
@@ -196,102 +231,4 @@ public class KeyPersistenceSettings extends 
PersistenceSettings {
 
         return cols;
     }
-
-    /**
-     * Extracts POJO fields specified in XML element.
-     *
-     * @param el XML element describing fields.
-     * @param descriptors POJO fields descriptors.
-     * @return List of {@code This} fields.
-     */
-    private List<PojoField> detectFields(Element el, List<PropertyDescriptor> 
descriptors) {
-        List<PojoField> list = new LinkedList<>();
-
-        if (el == null && (descriptors == null || descriptors.isEmpty()))
-            return list;
-
-        if (el == null) {
-            for (PropertyDescriptor desc : descriptors) {
-                // Skip POJO field if it's read-only
-                if (desc.getWriteMethod() != null)
-                    list.add(new PojoKeyField(desc));
-            }
-
-            return list;
-        }
-
-        NodeList nodes = el.getElementsByTagName(FIELD_ELEMENT);
-
-        int cnt = nodes == null ? 0 : nodes.getLength();
-
-        if (cnt == 0) {
-            throw new IllegalArgumentException("Incorrect configuration of 
Cassandra key persistence settings, " +
-                "no key fields specified inside '" + PARTITION_KEY_ELEMENT + 
"/" +
-                CLUSTER_KEY_ELEMENT + "' element");
-        }
-
-        for (int i = 0; i < cnt; i++) {
-            PojoKeyField field = new PojoKeyField((Element)nodes.item(i), 
getJavaClass());
-
-            PropertyDescriptor desc = findPropertyDescriptor(descriptors, 
field.getName());
-
-            if (desc == null) {
-                throw new IllegalArgumentException("Specified POJO field '" + 
field.getName() +
-                    "' doesn't exist in '" + getJavaClass().getName() + "' 
class");
-            }
-
-            list.add(field);
-        }
-
-        return list;
-    }
-
-    /**
-     * @return POJO field descriptors for partition key.
-     */
-    private List<PropertyDescriptor> getPartitionKeyDescriptors() {
-        List<PropertyDescriptor> primitivePropDescriptors = 
PropertyMappingHelper.getPojoPropertyDescriptors(
-            getJavaClass(), true);
-
-        boolean valid = false;
-
-        for (PropertyDescriptor desc : primitivePropDescriptors) {
-            if (desc.getWriteMethod() != null) {
-                valid = true;
-
-                break;
-            }
-        }
-
-        if (!valid) {
-            throw new IgniteException("Partition key can't have only 
calculated read-only fields, there should be " +
-                    "some fields with setter method");
-        }
-
-        return primitivePropDescriptors;
-    }
-
-    /**
-     * @param partKeyFields List of fields.
-     * @return POJO field descriptors for cluster key.
-     */
-    private List<PropertyDescriptor> getClusterKeyDescriptors(List<PojoField> 
partKeyFields) {
-        List<PropertyDescriptor> primitivePropDescriptors =
-            PropertyMappingHelper.getPojoPropertyDescriptors(getJavaClass(), 
true);
-
-        if (primitivePropDescriptors == null || 
primitivePropDescriptors.isEmpty() ||
-            partKeyFields.size() == primitivePropDescriptors.size())
-            return null;
-
-        for (PojoField field : partKeyFields) {
-            for (int i = 0; i < primitivePropDescriptors.size(); i++) {
-                if 
(primitivePropDescriptors.get(i).getName().equals(field.getName())) {
-                    primitivePropDescriptors.remove(i);
-                    break;
-                }
-            }
-        }
-
-        return primitivePropDescriptors;
-    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/d44fdd45/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/persistence/PersistenceSettings.java
----------------------------------------------------------------------
diff --git 
a/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/persistence/PersistenceSettings.java
 
b/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/persistence/PersistenceSettings.java
index f22c0a4..220ef1f 100644
--- 
a/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/persistence/PersistenceSettings.java
+++ 
b/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/persistence/PersistenceSettings.java
@@ -20,19 +20,19 @@ package org.apache.ignite.cache.store.cassandra.persistence;
 import com.datastax.driver.core.DataType;
 import java.beans.PropertyDescriptor;
 import java.io.Serializable;
+import java.lang.reflect.Field;
 import java.nio.ByteBuffer;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
-import java.util.Collections;
+import java.util.*;
 
+import org.apache.commons.beanutils.PropertyUtils;
 import org.apache.ignite.IgniteException;
+import org.apache.ignite.cache.query.annotations.QuerySqlField;
 import org.apache.ignite.cache.store.cassandra.common.CassandraHelper;
 import org.apache.ignite.cache.store.cassandra.common.PropertyMappingHelper;
 import org.apache.ignite.cache.store.cassandra.serializer.JavaSerializer;
 import org.apache.ignite.cache.store.cassandra.serializer.Serializer;
 import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
 
 /**
  * Stores persistence settings, which describes how particular key/value
@@ -327,6 +327,21 @@ public abstract class PersistenceSettings implements 
Serializable {
     protected abstract String defaultColumnName();
 
     /**
+     * Creates instance of {@link PojoField} based on it's description in XML 
element.
+     *
+     * @param el XML element describing POJO field
+     * @param clazz POJO java class.
+     */
+    protected abstract PojoField createPojoField(Element el, Class clazz);
+
+    /**
+     * Creates instance of {@link PojoField} from its field accessor.
+     *
+     * @param accessor field accessor.
+     */
+    protected abstract PojoField createPojoField(PojoFieldAccessor accessor);
+
+    /**
      * Class instance initialization.
      */
     protected void init() {
@@ -395,6 +410,63 @@ public abstract class PersistenceSettings implements 
Serializable {
     }
 
     /**
+     * Extracts POJO fields from a list of corresponding XML field nodes.
+     *
+     * @param fieldNodes Field nodes to process.
+     * @return POJO fields list.
+     */
+    protected List<PojoField> detectPojoFields(NodeList fieldNodes) {
+        List<PojoField> detectedFields = new LinkedList<>();
+
+        if (fieldNodes != null && fieldNodes.getLength() != 0) {
+            int cnt = fieldNodes.getLength();
+
+            for (int i = 0; i < cnt; i++) {
+                PojoField field = createPojoField((Element)fieldNodes.item(i), 
getJavaClass());
+
+                // Just checking that such field exists in the class
+                PropertyMappingHelper.getPojoFieldAccessor(getJavaClass(), 
field.getName());
+
+                detectedFields.add(field);
+            }
+
+            return detectedFields;
+        }
+
+        PropertyDescriptor[] descriptors = 
PropertyUtils.getPropertyDescriptors(getJavaClass());
+
+        // Collecting Java Beans property descriptors
+        if (descriptors != null) {
+            for (PropertyDescriptor desc : descriptors) {
+                // Skip POJO field if it's read-only
+                if (desc.getWriteMethod() != null) {
+                    Field field = null;
+
+                    try {
+                        field = 
getJavaClass().getDeclaredField(desc.getName());
+                    }
+                    catch (Throwable ignore) {
+                    }
+
+                    detectedFields.add(createPojoField(new 
PojoFieldAccessor(desc, field)));
+                }
+            }
+        }
+
+        Field[] fields = getJavaClass().getDeclaredFields();
+
+        // Collecting all fields annotated with @QuerySqlField
+        if (fields != null) {
+            for (Field field : fields) {
+                if (field.getAnnotation(QuerySqlField.class) != null && 
!PojoField.containsField(detectedFields, field.getName()))
+                    detectedFields.add(createPojoField(new 
PojoFieldAccessor(field)));
+            }
+        }
+
+        return detectedFields;
+    }
+
+    /**
      * Instantiates Class object for particular class
      *
      * @param clazz class name
@@ -442,5 +514,4 @@ public abstract class PersistenceSettings implements 
Serializable {
             throw new IgniteException("Failed to instantiate class '" + clazz 
+ "' using default constructor", e);
         }
     }
-
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/d44fdd45/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/persistence/PojoField.java
----------------------------------------------------------------------
diff --git 
a/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/persistence/PojoField.java
 
b/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/persistence/PojoField.java
index 566c0b9..386628b 100644
--- 
a/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/persistence/PojoField.java
+++ 
b/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/persistence/PojoField.java
@@ -19,10 +19,12 @@ package org.apache.ignite.cache.store.cassandra.persistence;
 
 import com.datastax.driver.core.DataType;
 import com.datastax.driver.core.Row;
-import java.beans.PropertyDescriptor;
 import java.io.Serializable;
-import org.apache.ignite.IgniteException;
+import java.lang.annotation.Annotation;
+import java.util.List;
+
 import org.apache.ignite.cache.store.cassandra.common.PropertyMappingHelper;
+import org.apache.ignite.cache.query.annotations.QuerySqlField;
 import org.apache.ignite.cache.store.cassandra.serializer.Serializer;
 import org.w3c.dom.Element;
 
@@ -40,9 +42,6 @@ public abstract class PojoField implements Serializable {
     /** Field name. */
     private String name;
 
-    /** Java class to which the field belongs. */
-    private Class objJavaCls;
-
     /** Field column name in Cassandra table. */
     private String col;
 
@@ -52,8 +51,27 @@ public abstract class PojoField implements Serializable {
     /** Indicator for calculated field. */
     private Boolean calculated;
 
-    /** Field property descriptor. */
-    private transient PropertyDescriptor desc;
+    /** Field property accessor. */
+    private transient PojoFieldAccessor accessor;
+
+    /**
+     *  Checks if list contains POJO field with the specified name.
+     *
+     * @param fields list of POJO fields.
+     * @param fieldName field name.
+     * @return true if list contains field or false otherwise.
+     */
+    public static boolean containsField(List<PojoField> fields, String 
fieldName) {
+        if (fields == null || fields.isEmpty())
+            return false;
+
+        for (PojoField field : fields) {
+            if (field.getName().equals(fieldName))
+                return true;
+        }
+
+        return false;
+    }
 
     /**
      * Creates instance of {@link PojoField} based on it's description in XML 
element.
@@ -73,20 +91,23 @@ public abstract class PojoField implements Serializable {
         this.name = el.getAttribute(NAME_ATTR).trim();
         this.col = el.hasAttribute(COLUMN_ATTR) ? 
el.getAttribute(COLUMN_ATTR).trim() : name.toLowerCase();
 
-        init(PropertyMappingHelper.getPojoPropertyDescriptor(pojoCls, name));
+        init(PropertyMappingHelper.getPojoFieldAccessor(pojoCls, name));
     }
 
     /**
-     * Creates instance of {@link PojoField}  from its property descriptor.
+     * Creates instance of {@link PojoField} from its field accessor.
      *
-     * @param desc Field property descriptor.
+     * @param accessor field accessor.
      */
-    public PojoField(PropertyDescriptor desc) {
-        this.name = desc.getName();
+    public PojoField(PojoFieldAccessor accessor) {
+        this.name = accessor.getName();
 
-        col = name.toLowerCase();
+        QuerySqlField sqlField = 
(QuerySqlField)accessor.getAnnotation(QuerySqlField.class);
 
-        init(desc);
+        col = sqlField != null && sqlField.name() != null && 
!sqlField.name().isEmpty() ?
+                sqlField.name() : name.toLowerCase();
+
+        init(accessor);
     }
 
     /**
@@ -102,7 +123,7 @@ public abstract class PojoField implements Serializable {
      * @return Java class.
      */
     public Class getJavaClass() {
-        return propDesc().getPropertyType();
+        return accessor.getFieldType();
     }
 
     /**
@@ -131,7 +152,7 @@ public abstract class PojoField implements Serializable {
         if (calculated != null)
             return calculated;
 
-        return calculated = propDesc().getWriteMethod() == null;
+        return calculated = accessor.isReadOnly();
     }
 
     /**
@@ -143,28 +164,31 @@ public abstract class PojoField implements Serializable {
      * @return Object to store in Cassandra table column.
      */
     public Object getValueFromObject(Object obj, Serializer serializer) {
-        try {
-            Object val = propDesc().getReadMethod().invoke(obj);
-
-            if (val == null)
-                return null;
+        Object val = accessor.getValue(obj);
 
-            DataType.Name cassandraType = 
PropertyMappingHelper.getCassandraType(val.getClass());
+        if (val == null)
+            return null;
 
-            if (cassandraType != null)
-                return val;
+        DataType.Name cassandraType = 
PropertyMappingHelper.getCassandraType(val.getClass());
 
-            if (serializer == null) {
-                throw new IllegalStateException("Can't serialize value from 
object '" +
-                    val.getClass().getName() + "' field '" + name + "', cause 
there is no BLOB serializer specified");
-            }
+        if (cassandraType != null)
+            return val;
 
-            return serializer.serialize(val);
-        }
-        catch (Throwable e) {
-            throw new IgniteException("Failed to get value of the field '" + 
name + "' from the instance " +
-                " of '" + obj.getClass().toString() + "' class", e);
+        if (serializer == null) {
+            throw new IllegalStateException("Can't serialize value from object 
'" +
+                val.getClass().getName() + "' field '" + name + "', cause 
there is no BLOB serializer specified");
         }
+
+        return serializer.serialize(val);
+    }
+
+    /**
+     * Returns POJO field annotation.
+     *
+     * @return annotation.
+     */
+    public Annotation getAnnotation(Class clazz) {
+        return accessor.getAnnotation(clazz);
     }
 
     /**
@@ -178,49 +202,22 @@ public abstract class PojoField implements Serializable {
         if (calculatedField())
             return;
 
-        Object val = PropertyMappingHelper.getCassandraColumnValue(row, col, 
propDesc().getPropertyType(), serializer);
+        Object val = PropertyMappingHelper.getCassandraColumnValue(row, col, 
accessor.getFieldType(), serializer);
 
-        try {
-            propDesc().getWriteMethod().invoke(obj, val);
-        }
-        catch (Throwable e) {
-            throw new IgniteException("Failed to set value of the field '" + 
name + "' of the instance " +
-                " of '" + obj.getClass().toString() + "' class", e);
-        }
+        accessor.setValue(obj, val);
     }
 
     /**
      * Initializes field info from property descriptor.
      *
-     * @param desc {@link PropertyDescriptor} descriptor.
+     * @param accessor {@link PojoFieldAccessor} accessor.
      */
-    protected void init(PropertyDescriptor desc) {
-        if (desc.getReadMethod() == null) {
-            throw new IllegalArgumentException("Field '" + desc.getName() +
-                "' of the class instance '" + desc.getPropertyType().getName() 
+
-                "' doesn't provide getter method");
-        }
-
-        if (!desc.getReadMethod().isAccessible())
-            desc.getReadMethod().setAccessible(true);
-
-        if (desc.getWriteMethod() != null && 
!desc.getWriteMethod().isAccessible())
-            desc.getWriteMethod().setAccessible(true);
-
-        DataType.Name cassandraType = 
PropertyMappingHelper.getCassandraType(desc.getPropertyType());
+    private void init(PojoFieldAccessor accessor) {
+        DataType.Name cassandraType = 
PropertyMappingHelper.getCassandraType(accessor.getFieldType());
         cassandraType = cassandraType == null ? DataType.Name.BLOB : 
cassandraType;
 
-        this.objJavaCls = desc.getReadMethod().getDeclaringClass();
-        this.desc = desc;
         this.colDDL = "\"" + col + "\" " + cassandraType.toString();
-    }
 
-    /**
-     * Returns property descriptor of the POJO field
-     *
-     * @return Property descriptor
-     */
-    private PropertyDescriptor propDesc() {
-        return desc != null ? desc : (desc = 
PropertyMappingHelper.getPojoPropertyDescriptor(objJavaCls, name));
+        this.accessor = accessor;
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/d44fdd45/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/persistence/PojoFieldAccessor.java
----------------------------------------------------------------------
diff --git 
a/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/persistence/PojoFieldAccessor.java
 
b/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/persistence/PojoFieldAccessor.java
new file mode 100644
index 0000000..f3d8a76
--- /dev/null
+++ 
b/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/persistence/PojoFieldAccessor.java
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.cache.store.cassandra.persistence;
+
+import org.apache.ignite.IgniteException;
+
+import java.beans.PropertyDescriptor;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.util.List;
+
+/**
+ * Property accessor provides read/write access to POJO object properties 
defined through:
+ *  1) Getter/setter methods
+ *  2) Raw class members
+ */
+public class PojoFieldAccessor {
+    /** Java Bean property descriptor */
+    private PropertyDescriptor desc;
+
+    /** Object field associated with property descriptor. Used just to get 
annotations which
+     * applied not to property descriptor, but directly to object field 
associated with the property. */
+    private Field descField;
+
+    /** Object field */
+    private Field field;
+
+    /**
+     * Constructs object instance from Java Bean property descriptor, 
providing access to getter/setter.
+     *
+     * @param desc Java Bean property descriptor.
+     * @param field object field associated with property descriptor.
+     */
+    public PojoFieldAccessor(PropertyDescriptor desc, Field field) {
+        if (desc.getReadMethod() == null) {
+            throw new IllegalArgumentException("Field '" + desc.getName() +
+                    "' of the class instance '" + 
desc.getPropertyType().getName() +
+                    "' doesn't provide getter method");
+        }
+
+        desc.getReadMethod().setAccessible(true);
+
+        if (desc.getWriteMethod() != null)
+            desc.getWriteMethod().setAccessible(true);
+
+        this.desc = desc;
+        this.descField = field;
+    }
+
+    /**
+     * Constructs object instance from Field, providing direct access to class 
member.
+     *
+     * @param field Field descriptor.
+     */
+    public PojoFieldAccessor(Field field) {
+        field.setAccessible(true);
+        this.field = field;
+    }
+
+    /**
+     * Returns POJO field name.
+     *
+     * @return field name.
+     */
+    public String getName() {
+        return desc != null ? desc.getName() : field.getName();
+    }
+
+    /**
+     * Indicates if it's read-only field.
+     *
+     * @return true if field read-only, false if not.
+     */
+    public boolean isReadOnly() {
+        return desc != null && desc.getWriteMethod() == null;
+    }
+
+    /**
+     * Returns POJO field annotation.
+     *
+     * @return annotation.
+     */
+    public Annotation getAnnotation(Class clazz) {
+        if (field != null)
+            return field.getAnnotation(clazz);
+
+        Annotation ann = desc.getReadMethod().getAnnotation(clazz);
+
+        if (ann != null)
+            return ann;
+
+        ann = desc.getWriteMethod() == null ? null : 
desc.getWriteMethod().getAnnotation(clazz);
+
+        if (ann != null)
+            return ann;
+
+        return descField == null ? null : descField.getAnnotation(clazz);
+    }
+
+    /**
+     * Returns field value for the object instance.
+     *
+     * @param obj object instance.
+     * @return field value.
+     */
+    public Object getValue(Object obj) {
+        try {
+            return desc != null ? desc.getReadMethod().invoke(obj) : 
field.get(obj);
+        }
+        catch (Throwable e) {
+            throw new IgniteException("Failed to get value of the field '" + 
getName() + "' from the instance " +
+                    " of '" + obj.getClass().toString() + "' class", e);
+        }
+    }
+
+    /**
+     * Assigns value for the object field.
+     *
+     * @param obj object instance.
+     * @param val value to assign.
+     */
+    public void setValue(Object obj, Object val) {
+        if (isReadOnly())
+            throw new IgniteException("Can't assign value to read-only field 
'" + getName() + "' of the instance " +
+                    " of '" + obj.getClass().toString() + "' class");
+
+        try {
+            if (desc != null)
+                desc.getWriteMethod().invoke(obj, val);
+            else
+                field.set(obj, val);
+        }
+        catch (Throwable e) {
+            throw new IgniteException("Failed to set value of the field '" + 
getName() + "' of the instance " +
+                    " of '" + obj.getClass().toString() + "' class", e);
+        }
+    }
+
+    /**
+     * Returns field type.
+     *
+     * @return field type.
+     */
+    public Class getFieldType() {
+        return desc != null ? desc.getPropertyType() : field.getType();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d44fdd45/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/persistence/PojoKeyField.java
----------------------------------------------------------------------
diff --git 
a/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/persistence/PojoKeyField.java
 
b/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/persistence/PojoKeyField.java
index bf1d40e..52b4584 100644
--- 
a/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/persistence/PojoKeyField.java
+++ 
b/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/persistence/PojoKeyField.java
@@ -17,7 +17,7 @@
 
 package org.apache.ignite.cache.store.cassandra.persistence;
 
-import java.beans.PropertyDescriptor;
+import org.apache.ignite.cache.query.annotations.QuerySqlField;
 import org.w3c.dom.Element;
 
 /**
@@ -63,10 +63,15 @@ public class PojoKeyField extends PojoField {
     /**
      * Constructs Ignite cache key POJO object descriptor.
      *
-     * @param desc property descriptor.
+     * @param accessor property descriptor.
      */
-    public PojoKeyField(PropertyDescriptor desc) {
-        super(desc);
+    public PojoKeyField(PojoFieldAccessor accessor) {
+        super(accessor);
+
+        QuerySqlField sqlField = 
(QuerySqlField)accessor.getAnnotation(QuerySqlField.class);
+
+        if (sqlField != null && sqlField.descending())
+            sortOrder = SortOrder.DESC;
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/d44fdd45/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/persistence/PojoValueField.java
----------------------------------------------------------------------
diff --git 
a/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/persistence/PojoValueField.java
 
b/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/persistence/PojoValueField.java
index 9d25b60..36bcd0c 100644
--- 
a/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/persistence/PojoValueField.java
+++ 
b/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/persistence/PojoValueField.java
@@ -17,7 +17,7 @@
 
 package org.apache.ignite.cache.store.cassandra.persistence;
 
-import java.beans.PropertyDescriptor;
+import org.apache.ignite.cache.query.annotations.QuerySqlField;
 import org.w3c.dom.Element;
 
 /**
@@ -80,10 +80,14 @@ public class PojoValueField extends PojoField {
     /**
      * Constructs Ignite cache value field descriptor.
      *
-     * @param desc field property descriptor.
+     * @param accessor field property accessor.
      */
-    public PojoValueField(PropertyDescriptor desc) {
-        super(desc);
+    public PojoValueField(PojoFieldAccessor accessor) {
+        super(accessor);
+
+        QuerySqlField sqlField = 
(QuerySqlField)accessor.getAnnotation(QuerySqlField.class);
+
+        isIndexed = sqlField != null && sqlField.index();
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/d44fdd45/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/persistence/ValuePersistenceSettings.java
----------------------------------------------------------------------
diff --git 
a/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/persistence/ValuePersistenceSettings.java
 
b/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/persistence/ValuePersistenceSettings.java
index b737e2c..5824b6f 100644
--- 
a/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/persistence/ValuePersistenceSettings.java
+++ 
b/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/persistence/ValuePersistenceSettings.java
@@ -17,12 +17,10 @@
 
 package org.apache.ignite.cache.store.cassandra.persistence;
 
-import java.beans.PropertyDescriptor;
 import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
 
-import org.apache.ignite.cache.store.cassandra.common.PropertyMappingHelper;
 import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
 
@@ -52,7 +50,7 @@ public class ValuePersistenceSettings extends 
PersistenceSettings {
 
         NodeList nodes = el.getElementsByTagName(FIELD_ELEMENT);
 
-        fields = detectFields(nodes);
+        fields = detectPojoFields(nodes);
 
         if (fields.isEmpty())
             throw new IllegalStateException("Failed to initialize value fields 
for class '" + getJavaClass().getName() + "'");
@@ -74,45 +72,13 @@ public class ValuePersistenceSettings extends 
PersistenceSettings {
         return "value";
     }
 
-    /**
-     * Extracts POJO fields from a list of corresponding XML field nodes.
-     *
-     * @param fieldNodes Field nodes to process.
-     * @return POJO fields list.
-     */
-    private List<PojoField> detectFields(NodeList fieldNodes) {
-        List<PojoField> list = new LinkedList<>();
-
-        if (fieldNodes == null || fieldNodes.getLength() == 0) {
-            List<PropertyDescriptor> primitivePropDescriptors =
-                
PropertyMappingHelper.getPojoPropertyDescriptors(getJavaClass(), true);
-
-            for (PropertyDescriptor desc : primitivePropDescriptors) {
-                // Skip POJO field if it's read-only
-                if (desc.getWriteMethod() != null)
-                    list.add(new PojoValueField(desc));
-            }
-
-            return list;
-        }
-
-        List<PropertyDescriptor> allPropDescriptors = 
PropertyMappingHelper.getPojoPropertyDescriptors(getJavaClass(), false);
-
-        int cnt = fieldNodes.getLength();
-
-        for (int i = 0; i < cnt; i++) {
-            PojoValueField field = new 
PojoValueField((Element)fieldNodes.item(i), getJavaClass());
-
-            PropertyDescriptor desc = 
findPropertyDescriptor(allPropDescriptors, field.getName());
-
-            if (desc == null) {
-                throw new IllegalArgumentException("Specified POJO field '" + 
field.getName() +
-                    "' doesn't exist in '" + getJavaClass().getName() + "' 
class");
-            }
-
-            list.add(field);
-        }
+    /** {@inheritDoc} */
+    @Override protected PojoField createPojoField(Element el, Class clazz) {
+        return new PojoValueField(el, clazz);
+    }
 
-        return list;
+    /** {@inheritDoc} */
+    @Override protected PojoField createPojoField(PojoFieldAccessor accessor) {
+        return new PojoValueField(accessor);
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/d44fdd45/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/utils/DDLGenerator.java
----------------------------------------------------------------------
diff --git 
a/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/utils/DDLGenerator.java
 
b/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/utils/DDLGenerator.java
index e3ec391..569c65d 100644
--- 
a/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/utils/DDLGenerator.java
+++ 
b/modules/cassandra/store/src/main/java/org/apache/ignite/cache/store/cassandra/utils/DDLGenerator.java
@@ -35,9 +35,12 @@ public class DDLGenerator {
         if (args == null || args.length == 0)
             return;
 
+        boolean success = true;
+
         for (String arg : args) {
             File file = new File(arg);
             if (!file.isFile()) {
+                success = false;
                 
System.out.println("-------------------------------------------------------------");
                 System.out.println("Incorrect file specified: " + arg);
                 
System.out.println("-------------------------------------------------------------");
@@ -66,11 +69,15 @@ public class DDLGenerator {
                 }
             }
             catch (Throwable e) {
+                success = false;
                 
System.out.println("-------------------------------------------------------------");
-                System.out.println("Incorrect file specified: " + arg);
+                System.out.println("Invalid file specified: " + arg);
                 
System.out.println("-------------------------------------------------------------");
                 e.printStackTrace();
             }
         }
+
+        if (!success)
+            throw new RuntimeException("Failed to process some of the 
specified files");
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/d44fdd45/modules/cassandra/store/src/test/java/org/apache/ignite/tests/CassandraDirectPersistenceTest.java
----------------------------------------------------------------------
diff --git 
a/modules/cassandra/store/src/test/java/org/apache/ignite/tests/CassandraDirectPersistenceTest.java
 
b/modules/cassandra/store/src/test/java/org/apache/ignite/tests/CassandraDirectPersistenceTest.java
index f9e9649..5cce9df 100644
--- 
a/modules/cassandra/store/src/test/java/org/apache/ignite/tests/CassandraDirectPersistenceTest.java
+++ 
b/modules/cassandra/store/src/test/java/org/apache/ignite/tests/CassandraDirectPersistenceTest.java
@@ -23,10 +23,7 @@ import java.util.Map;
 import org.apache.ignite.cache.store.CacheStore;
 import org.apache.ignite.internal.processors.cache.CacheEntryImpl;
 import org.apache.ignite.internal.util.typedef.internal.U;
-import org.apache.ignite.tests.pojos.Person;
-import org.apache.ignite.tests.pojos.PersonId;
-import org.apache.ignite.tests.pojos.Product;
-import org.apache.ignite.tests.pojos.ProductOrder;
+import org.apache.ignite.tests.pojos.*;
 import org.apache.ignite.tests.utils.CacheStoreHelper;
 import org.apache.ignite.tests.utils.CassandraHelper;
 import org.apache.ignite.tests.utils.TestCacheSession;
@@ -432,6 +429,74 @@ public class CassandraDirectPersistenceTest {
     /** */
     @Test
     @SuppressWarnings("unchecked")
+    public void pojoStrategySimpleObjectsTest() {
+        CacheStore store5 = CacheStoreHelper.createCacheStore("persons5",
+                new 
ClassPathResource("org/apache/ignite/tests/persistence/pojo/persistence-settings-5.xml"),
+                CassandraHelper.getAdminDataSrc());
+
+        CacheStore store6 = CacheStoreHelper.createCacheStore("persons6",
+                new 
ClassPathResource("org/apache/ignite/tests/persistence/pojo/persistence-settings-6.xml"),
+                CassandraHelper.getAdminDataSrc());
+
+        Collection<CacheEntryImpl<SimplePersonId, SimplePerson>> entries5 = 
TestsHelper.generateSimplePersonIdsPersonsEntries();
+        Collection<CacheEntryImpl<SimplePersonId, SimplePerson>> entries6 = 
TestsHelper.generateSimplePersonIdsPersonsEntries();
+
+        LOGGER.info("Running POJO strategy write tests for simple objects");
+
+        LOGGER.info("Running single write operation tests");
+        store5.write(entries5.iterator().next());
+        store6.write(entries6.iterator().next());
+        LOGGER.info("Single write operation tests passed");
+
+        LOGGER.info("Running bulk write operation tests");
+        store5.writeAll(entries5);
+        store6.writeAll(entries6);
+        LOGGER.info("Bulk write operation tests passed");
+
+        LOGGER.info("POJO strategy write tests for simple objects passed");
+
+        LOGGER.info("Running POJO simple objects strategy read tests");
+
+        LOGGER.info("Running single read operation tests");
+
+        SimplePerson person = 
(SimplePerson)store5.load(entries5.iterator().next().getKey());
+        if 
(!entries5.iterator().next().getValue().equalsPrimitiveFields(person))
+            throw new RuntimeException("SimplePerson values were incorrectly 
deserialized from Cassandra");
+
+        person = 
(SimplePerson)store6.load(entries6.iterator().next().getKey());
+        if 
(!entries6.iterator().next().getValue().equalsPrimitiveFields(person))
+            throw new RuntimeException("SimplePerson values were incorrectly 
deserialized from Cassandra");
+
+        LOGGER.info("Single read operation tests passed");
+
+        LOGGER.info("Running bulk read operation tests");
+
+        Map persons = store5.loadAll(TestsHelper.getKeys(entries5));
+        if (!TestsHelper.checkSimplePersonCollectionsEqual(persons, entries5, 
true))
+            throw new RuntimeException("SimplePerson values were incorrectly 
deserialized from Cassandra");
+
+        persons = store6.loadAll(TestsHelper.getKeys(entries6));
+        if (!TestsHelper.checkSimplePersonCollectionsEqual(persons, entries6, 
true))
+            throw new RuntimeException("SimplePerson values were incorrectly 
deserialized from Cassandra");
+
+        LOGGER.info("Bulk read operation tests passed");
+
+        LOGGER.info("POJO strategy read tests for simple objects passed");
+
+        LOGGER.info("Running POJO strategy delete tests for simple objects");
+
+        store5.delete(entries5.iterator().next().getKey());
+        store5.deleteAll(TestsHelper.getKeys(entries5));
+
+        store6.delete(entries6.iterator().next().getKey());
+        store6.deleteAll(TestsHelper.getKeys(entries6));
+
+        LOGGER.info("POJO strategy delete tests for simple objects passed");
+    }
+
+    /** */
+    @Test
+    @SuppressWarnings("unchecked")
     public void pojoStrategyTransactionTest() {
         Map<Object, Object> sessionProps = U.newHashMap(1);
         Transaction sessionTx = new TestTransaction();

http://git-wip-us.apache.org/repos/asf/ignite/blob/d44fdd45/modules/cassandra/store/src/test/java/org/apache/ignite/tests/DDLGeneratorTest.java
----------------------------------------------------------------------
diff --git 
a/modules/cassandra/store/src/test/java/org/apache/ignite/tests/DDLGeneratorTest.java
 
b/modules/cassandra/store/src/test/java/org/apache/ignite/tests/DDLGeneratorTest.java
index e982e16..048f0f7 100644
--- 
a/modules/cassandra/store/src/test/java/org/apache/ignite/tests/DDLGeneratorTest.java
+++ 
b/modules/cassandra/store/src/test/java/org/apache/ignite/tests/DDLGeneratorTest.java
@@ -28,8 +28,12 @@ public class DDLGeneratorTest {
     /** */
     private static final String[] RESOURCES = new String[] {
         
"org/apache/ignite/tests/persistence/primitive/persistence-settings-1.xml",
+        "org/apache/ignite/tests/persistence/pojo/persistence-settings-1.xml",
+        "org/apache/ignite/tests/persistence/pojo/persistence-settings-2.xml",
         "org/apache/ignite/tests/persistence/pojo/persistence-settings-3.xml",
         "org/apache/ignite/tests/persistence/pojo/persistence-settings-4.xml",
+        "org/apache/ignite/tests/persistence/pojo/persistence-settings-5.xml",
+        "org/apache/ignite/tests/persistence/pojo/persistence-settings-6.xml",
         "org/apache/ignite/tests/persistence/pojo/product.xml",
         "org/apache/ignite/tests/persistence/pojo/order.xml"
     };

http://git-wip-us.apache.org/repos/asf/ignite/blob/d44fdd45/modules/cassandra/store/src/test/java/org/apache/ignite/tests/IgnitePersistentStoreTest.java
----------------------------------------------------------------------
diff --git 
a/modules/cassandra/store/src/test/java/org/apache/ignite/tests/IgnitePersistentStoreTest.java
 
b/modules/cassandra/store/src/test/java/org/apache/ignite/tests/IgnitePersistentStoreTest.java
index feccb24..21f28e0 100644
--- 
a/modules/cassandra/store/src/test/java/org/apache/ignite/tests/IgnitePersistentStoreTest.java
+++ 
b/modules/cassandra/store/src/test/java/org/apache/ignite/tests/IgnitePersistentStoreTest.java
@@ -32,10 +32,7 @@ import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.internal.binary.BinaryMarshaller;
 import org.apache.ignite.internal.processors.cache.CacheEntryImpl;
 import org.apache.ignite.internal.util.typedef.internal.U;
-import org.apache.ignite.tests.pojos.Person;
-import org.apache.ignite.tests.pojos.PersonId;
-import org.apache.ignite.tests.pojos.Product;
-import org.apache.ignite.tests.pojos.ProductOrder;
+import org.apache.ignite.tests.pojos.*;
 import org.apache.ignite.tests.utils.CacheStoreHelper;
 import org.apache.ignite.tests.utils.CassandraHelper;
 import org.apache.ignite.tests.utils.TestsHelper;
@@ -423,6 +420,86 @@ public class IgnitePersistentStoreTest {
 
     /** */
     @Test
+    public void pojoStrategySimpleObjectsTest() {
+        Ignition.stopAll(true);
+
+        LOGGER.info("Running POJO strategy write tests for simple objects");
+
+        Map<SimplePersonId, SimplePerson> personMap5 = 
TestsHelper.generateSimplePersonIdsPersonsMap();
+        Map<SimplePersonId, SimplePerson> personMap6 = 
TestsHelper.generateSimplePersonIdsPersonsMap();
+
+        try (Ignite ignite = 
Ignition.start("org/apache/ignite/tests/persistence/pojo/ignite-config.xml")) {
+            IgniteCache<SimplePersonId, SimplePerson> personCache5 = 
ignite.getOrCreateCache(new CacheConfiguration<SimplePersonId, 
SimplePerson>("cache5"));
+            IgniteCache<SimplePersonId, SimplePerson> personCache6 = 
ignite.getOrCreateCache(new CacheConfiguration<SimplePersonId, 
SimplePerson>("cache6"));
+
+            LOGGER.info("Running single operation write tests");
+
+            SimplePersonId id = TestsHelper.generateRandomSimplePersonId();
+            personCache5.put(id, 
TestsHelper.generateRandomSimplePerson(id.personNum));
+            personCache6.put(id, 
TestsHelper.generateRandomSimplePerson(id.personNum));
+
+            LOGGER.info("Single operation write tests passed");
+
+            LOGGER.info("Running bulk operation write tests");
+            personCache5.putAll(personMap5);
+            personCache6.putAll(personMap6);
+            LOGGER.info("Bulk operation write tests passed");
+        }
+
+        LOGGER.info("POJO strategy write tests for simple objects passed");
+
+        Ignition.stopAll(true);
+
+        try (Ignite ignite = 
Ignition.start("org/apache/ignite/tests/persistence/pojo/ignite-config.xml")) {
+            LOGGER.info("Running POJO strategy read tests for simple objects");
+
+            IgniteCache<SimplePersonId, SimplePerson> personCache5 = 
ignite.getOrCreateCache(new CacheConfiguration<SimplePersonId, 
SimplePerson>("cache5"));
+            IgniteCache<SimplePersonId, SimplePerson> personCache6 = 
ignite.getOrCreateCache(new CacheConfiguration<SimplePersonId, 
SimplePerson>("cache6"));
+
+            LOGGER.info("Running single operation read tests");
+
+            SimplePersonId id = personMap5.keySet().iterator().next();
+
+            SimplePerson person = personCache5.get(id);
+            if (!person.equalsPrimitiveFields(personMap5.get(id)))
+                throw new RuntimeException("SimplePerson value was incorrectly 
deserialized from Cassandra");
+
+            id = personMap6.keySet().iterator().next();
+
+            person = personCache6.get(id);
+            if (!person.equals(personMap6.get(id)))
+                throw new RuntimeException("SimplePerson value was incorrectly 
deserialized from Cassandra");
+
+            LOGGER.info("Single operation read tests passed");
+
+            LOGGER.info("Running bulk operation read tests");
+
+            Map<SimplePersonId, SimplePerson> persons5 = 
personCache5.getAll(personMap5.keySet());
+            if (!TestsHelper.checkSimplePersonMapsEqual(persons5, personMap5, 
true))
+                throw new RuntimeException("SimplePerson values batch was 
incorrectly deserialized from Cassandra");
+
+            Map<SimplePersonId, SimplePerson> persons6 = 
personCache6.getAll(personMap6.keySet());
+            if (!TestsHelper.checkSimplePersonMapsEqual(persons6, personMap6, 
false))
+                throw new RuntimeException("SimplePerson values batch was 
incorrectly deserialized from Cassandra");
+
+            LOGGER.info("Bulk operation read tests passed");
+
+            LOGGER.info("POJO strategy read tests for simple objects passed");
+
+            LOGGER.info("Running POJO strategy delete tests for simple 
objects");
+
+            personCache5.remove(id);
+            personCache5.removeAll(personMap5.keySet());
+
+            personCache6.remove(id);
+            personCache6.removeAll(personMap6.keySet());
+
+            LOGGER.info("POJO strategy delete tests for simple objects 
passed");
+        }
+    }
+
+    /** */
+    @Test
     public void pojoStrategyTransactionTest() {
         CassandraHelper.dropTestKeyspaces();
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/d44fdd45/modules/cassandra/store/src/test/java/org/apache/ignite/tests/pojos/SimplePerson.java
----------------------------------------------------------------------
diff --git 
a/modules/cassandra/store/src/test/java/org/apache/ignite/tests/pojos/SimplePerson.java
 
b/modules/cassandra/store/src/test/java/org/apache/ignite/tests/pojos/SimplePerson.java
new file mode 100644
index 0000000..0d24ea6
--- /dev/null
+++ 
b/modules/cassandra/store/src/test/java/org/apache/ignite/tests/pojos/SimplePerson.java
@@ -0,0 +1,186 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.tests.pojos;
+
+import org.apache.ignite.cache.query.annotations.QuerySqlField;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Simple POJO without getters/setters which could be stored as a value in 
Ignite cache
+ */
+public class SimplePerson implements Externalizable {
+    /** */
+    @QuerySqlField(name = "person_num")
+    private long personNum;
+
+    /** */
+    @QuerySqlField(name = "first_name")
+    private String firstName;
+
+    /** */
+    @QuerySqlField(name = "last_name")
+    private String lastName;
+
+    /** */
+    @QuerySqlField(name = "age")
+    private int age;
+
+    /** */
+    @QuerySqlField(name = "married", index = true)
+    private boolean married;
+
+    /** */
+    @QuerySqlField(name = "height")
+    private long height;
+
+    /** */
+    @QuerySqlField(name = "weight")
+    private float weight;
+
+    /** */
+    @QuerySqlField(name = "birth_date")
+    private Date birthDate;
+
+    /** */
+    @QuerySqlField(name = "phones")
+    private List<String> phones;
+
+    /** */
+    @SuppressWarnings("UnusedDeclaration")
+    public SimplePerson() {
+    }
+
+    /** */
+    public SimplePerson(Person person) {
+        this.personNum = person.getPersonNumber();
+        this.firstName = person.getFirstName();
+        this.lastName = person.getLastName();
+        this.age = person.getAge();
+        this.married = person.getMarried();
+        this.height = person.getHeight();
+        this.weight = person.getWeight();
+        this.birthDate = person.getBirthDate();
+        this.phones = person.getPhones();
+    }
+
+    /** */
+    public SimplePerson(long personNum, String firstName, String lastName, int 
age, boolean married,
+                        long height, float weight, Date birthDate, 
List<String> phones) {
+        this.personNum = personNum;
+        this.firstName = firstName;
+        this.lastName = lastName;
+        this.age = age;
+        this.married = married;
+        this.height = height;
+        this.weight = weight;
+        this.birthDate = birthDate;
+        this.phones = phones;
+    }
+
+
+    /** {@inheritDoc} */
+    @Override public void writeExternal(ObjectOutput out) throws IOException {
+        out.writeLong(personNum);
+        out.writeObject(firstName);
+        out.writeObject(lastName);
+        out.writeInt(age);
+        out.writeBoolean(married);
+        out.writeLong(height);
+        out.writeFloat(weight);
+        out.writeObject(birthDate);
+        out.writeObject(phones);
+    }
+
+    /** {@inheritDoc} */
+    @SuppressWarnings("unchecked")
+    @Override public void readExternal(ObjectInput in) throws IOException, 
ClassNotFoundException {
+        personNum = in.readLong();
+        firstName = (String)in.readObject();
+        lastName = (String)in.readObject();
+        age = in.readInt();
+        married = in.readBoolean();
+        height = in.readLong();
+        weight = in.readFloat();
+        birthDate = (Date)in.readObject();
+        phones = (List<String>)in.readObject();
+    }
+
+    /** {@inheritDoc} */
+    @SuppressWarnings("SimplifiableIfStatement")
+    @Override public boolean equals(Object obj) {
+        if (obj == null || !(obj instanceof SimplePerson))
+            return false;
+
+        SimplePerson person = (SimplePerson)obj;
+
+        if (personNum != person.personNum)
+            return false;
+
+        if ((firstName != null && !firstName.equals(person.firstName)) ||
+            (person.firstName != null && !person.firstName.equals(firstName)))
+            return false;
+
+        if ((lastName != null && !lastName.equals(person.lastName)) ||
+            (person.lastName != null && !person.lastName.equals(lastName)))
+            return false;
+
+        if ((birthDate != null && !birthDate.equals(person.birthDate)) ||
+            (person.birthDate != null && !person.birthDate.equals(birthDate)))
+            return false;
+
+        if ((phones != null && !phones.equals(person.phones)) ||
+            (person.phones != null && !person.phones.equals(phones)))
+            return false;
+
+        return age == person.age && married == person.married &&
+            height == person.height && weight == person.weight;
+    }
+
+    /** */
+    @SuppressWarnings("SimplifiableIfStatement")
+    public boolean equalsPrimitiveFields(Object obj) {
+        if (obj == null || !(obj instanceof SimplePerson))
+            return false;
+
+        SimplePerson person = (SimplePerson)obj;
+
+        if (personNum != person.personNum)
+            return false;
+
+        if ((firstName != null && !firstName.equals(person.firstName)) ||
+            (person.firstName != null && !person.firstName.equals(firstName)))
+            return false;
+
+        if ((lastName != null && !lastName.equals(person.lastName)) ||
+            (person.lastName != null && !person.lastName.equals(lastName)))
+            return false;
+
+        if ((birthDate != null && !birthDate.equals(person.birthDate)) ||
+            (person.birthDate != null && !person.birthDate.equals(birthDate)))
+            return false;
+
+        return age == person.age && married == person.married &&
+            height == person.height && weight == person.weight;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d44fdd45/modules/cassandra/store/src/test/java/org/apache/ignite/tests/pojos/SimplePersonId.java
----------------------------------------------------------------------
diff --git 
a/modules/cassandra/store/src/test/java/org/apache/ignite/tests/pojos/SimplePersonId.java
 
b/modules/cassandra/store/src/test/java/org/apache/ignite/tests/pojos/SimplePersonId.java
new file mode 100644
index 0000000..8dfbb2c
--- /dev/null
+++ 
b/modules/cassandra/store/src/test/java/org/apache/ignite/tests/pojos/SimplePersonId.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.tests.pojos;
+
+import org.apache.ignite.cache.affinity.AffinityKeyMapped;
+import org.apache.ignite.cache.query.annotations.QuerySqlField;
+
+import java.io.Serializable;
+
+/**
+ * Simple POJO without getters/setters which could be stored as a key in 
Ignite cache
+ */
+public class SimplePersonId implements Serializable {
+    /** */
+    @AffinityKeyMapped
+    @QuerySqlField(name = "company_code")
+    public String companyCode;
+
+    /** */
+    @AffinityKeyMapped
+    @QuerySqlField(name = "department_code")
+    public String departmentCode;
+
+    /** */
+    @QuerySqlField(name = "person_num")
+    public long personNum;
+
+    /** */
+    @SuppressWarnings("UnusedDeclaration")
+    public SimplePersonId() {
+    }
+
+    /** */
+    public SimplePersonId(PersonId personId) {
+        this.companyCode = personId.getCompanyCode();
+        this.departmentCode = personId.getDepartmentCode();
+        this.personNum = personId.getPersonNumber();
+    }
+
+    /** */
+    public SimplePersonId(String companyCode, String departmentCode, long 
personNum) {
+        this.companyCode = companyCode;
+        this.departmentCode = departmentCode;
+        this.personNum = personNum;
+    }
+
+    /** {@inheritDoc} */
+    @SuppressWarnings("SimplifiableIfStatement")
+    @Override public boolean equals(Object obj) {
+        if (obj == null || !(obj instanceof SimplePersonId))
+            return false;
+
+        SimplePersonId id = (SimplePersonId)obj;
+
+        if ((companyCode != null && !companyCode.equals(id.companyCode)) ||
+            (id.companyCode != null && !id.companyCode.equals(companyCode)))
+            return false;
+
+        if ((companyCode != null && !companyCode.equals(id.companyCode)) ||
+            (id.companyCode != null && !id.companyCode.equals(companyCode)))
+            return false;
+
+        return personNum == id.personNum;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        String code = (companyCode == null ? "" : companyCode) +
+            (departmentCode == null ? "" : departmentCode) +
+                personNum;
+
+        return code.hashCode();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d44fdd45/modules/cassandra/store/src/test/java/org/apache/ignite/tests/utils/TestsHelper.java
----------------------------------------------------------------------
diff --git 
a/modules/cassandra/store/src/test/java/org/apache/ignite/tests/utils/TestsHelper.java
 
b/modules/cassandra/store/src/test/java/org/apache/ignite/tests/utils/TestsHelper.java
index 24d64c9..5d21613 100644
--- 
a/modules/cassandra/store/src/test/java/org/apache/ignite/tests/utils/TestsHelper.java
+++ 
b/modules/cassandra/store/src/test/java/org/apache/ignite/tests/utils/TestsHelper.java
@@ -21,10 +21,7 @@ package org.apache.ignite.tests.utils;
 import org.apache.ignite.cache.store.cassandra.common.SystemHelper;
 import org.apache.ignite.internal.processors.cache.CacheEntryImpl;
 import org.apache.ignite.tests.load.Generator;
-import org.apache.ignite.tests.pojos.Person;
-import org.apache.ignite.tests.pojos.PersonId;
-import org.apache.ignite.tests.pojos.Product;
-import org.apache.ignite.tests.pojos.ProductOrder;
+import org.apache.ignite.tests.pojos.*;
 import org.springframework.core.io.ClassPathResource;
 
 import java.util.Collection;
@@ -283,6 +280,24 @@ public class TestsHelper {
     }
 
     /** */
+    public static Map<SimplePersonId, SimplePerson> 
generateSimplePersonIdsPersonsMap() {
+        return generateSimplePersonIdsPersonsMap(BULK_OPERATION_SIZE);
+    }
+
+    /** */
+    public static Map<SimplePersonId, SimplePerson> 
generateSimplePersonIdsPersonsMap(int cnt) {
+        Map<SimplePersonId, SimplePerson> map = new HashMap<>();
+
+        for (int i = 0; i < cnt; i++) {
+            PersonId id = generateRandomPersonId();
+
+            map.put(new SimplePersonId(id), new 
SimplePerson(generateRandomPerson(id.getPersonNumber())));
+        }
+
+        return map;
+    }
+
+    /** */
     public static Map<PersonId, Person> generatePersonIdsPersonsMap() {
         return generatePersonIdsPersonsMap(BULK_OPERATION_SIZE);
     }
@@ -301,6 +316,24 @@ public class TestsHelper {
     }
 
     /** */
+    public static Collection<CacheEntryImpl<SimplePersonId, SimplePerson>> 
generateSimplePersonIdsPersonsEntries() {
+        return generateSimplePersonIdsPersonsEntries(BULK_OPERATION_SIZE);
+    }
+
+    /** */
+    public static Collection<CacheEntryImpl<SimplePersonId, SimplePerson>> 
generateSimplePersonIdsPersonsEntries(int cnt) {
+        Collection<CacheEntryImpl<SimplePersonId, SimplePerson>> entries = new 
LinkedList<>();
+
+        for (int i = 0; i < cnt; i++) {
+            PersonId id = generateRandomPersonId();
+
+            entries.add(new CacheEntryImpl<>(new SimplePersonId(id), new 
SimplePerson(generateRandomPerson(id.getPersonNumber()))));
+        }
+
+        return entries;
+    }
+
+    /** */
     public static Collection<CacheEntryImpl<PersonId, Person>> 
generatePersonIdsPersonsEntries() {
         return generatePersonIdsPersonsEntries(BULK_OPERATION_SIZE);
     }
@@ -443,6 +476,24 @@ public class TestsHelper {
     }
 
     /** */
+    public static SimplePerson generateRandomSimplePerson(long personNum) {
+        int phonesCnt = RANDOM.nextInt(4);
+
+        List<String> phones = new LinkedList<>();
+
+        for (int i = 0; i < phonesCnt; i++)
+            phones.add(randomNumber(4));
+
+        return new SimplePerson(personNum, randomString(4), randomString(4), 
RANDOM.nextInt(100),
+                RANDOM.nextBoolean(), RANDOM.nextLong(), RANDOM.nextFloat(), 
new Date(), phones);
+    }
+
+    /** */
+    public static SimplePersonId generateRandomSimplePersonId() {
+        return new SimplePersonId(randomString(4), randomString(4), 
RANDOM.nextInt(100));
+    }
+
+    /** */
     public static Person generateRandomPerson(long personNum) {
         int phonesCnt = RANDOM.nextInt(4);
 
@@ -517,6 +568,26 @@ public class TestsHelper {
     }
 
     /** */
+    public static <K> boolean checkSimplePersonMapsEqual(Map<K, SimplePerson> 
map1, Map<K, SimplePerson> map2,
+                                                   boolean 
primitiveFieldsOnly) {
+        if (map1 == null || map2 == null || map1.size() != map2.size())
+            return false;
+
+        for (K key : map1.keySet()) {
+            SimplePerson person1 = map1.get(key);
+            SimplePerson person2 = map2.get(key);
+
+            boolean equals = person1 != null && person2 != null &&
+                    (primitiveFieldsOnly ? 
person1.equalsPrimitiveFields(person2) : person1.equals(person2));
+
+            if (!equals)
+                return false;
+        }
+
+        return true;
+    }
+
+    /** */
     public static <K> boolean checkPersonMapsEqual(Map<K, Person> map1, Map<K, 
Person> map2,
         boolean primitiveFieldsOnly) {
         if (map1 == null || map2 == null || map1.size() != map2.size())
@@ -537,6 +608,24 @@ public class TestsHelper {
     }
 
     /** */
+    public static <K> boolean checkSimplePersonCollectionsEqual(Map<K, 
SimplePerson> map, Collection<CacheEntryImpl<K, SimplePerson>> col,
+                                                          boolean 
primitiveFieldsOnly) {
+        if (map == null || col == null || map.size() != col.size())
+            return false;
+
+        for (CacheEntryImpl<K, SimplePerson> entry : col) {
+            boolean equals = primitiveFieldsOnly ?
+                    
entry.getValue().equalsPrimitiveFields(map.get(entry.getKey())) :
+                    entry.getValue().equals(map.get(entry.getKey()));
+
+            if (!equals)
+                return false;
+        }
+
+        return true;
+    }
+
+    /** */
     public static <K> boolean checkPersonCollectionsEqual(Map<K, Person> map, 
Collection<CacheEntryImpl<K, Person>> col,
         boolean primitiveFieldsOnly) {
         if (map == null || col == null || map.size() != col.size())

http://git-wip-us.apache.org/repos/asf/ignite/blob/d44fdd45/modules/cassandra/store/src/test/resources/org/apache/ignite/tests/persistence/pojo/ignite-config.xml
----------------------------------------------------------------------
diff --git 
a/modules/cassandra/store/src/test/resources/org/apache/ignite/tests/persistence/pojo/ignite-config.xml
 
b/modules/cassandra/store/src/test/resources/org/apache/ignite/tests/persistence/pojo/ignite-config.xml
index af4ffef..75041fd 100644
--- 
a/modules/cassandra/store/src/test/resources/org/apache/ignite/tests/persistence/pojo/ignite-config.xml
+++ 
b/modules/cassandra/store/src/test/resources/org/apache/ignite/tests/persistence/pojo/ignite-config.xml
@@ -46,6 +46,16 @@
         <constructor-arg type="org.springframework.core.io.Resource" 
value="classpath:org/apache/ignite/tests/persistence/pojo/persistence-settings-4.xml"
 />
     </bean>
 
+    <!-- Persistence settings for 'cache5' -->
+    <bean id="cache5_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/pojo/persistence-settings-5.xml"
 />
+    </bean>
+
+    <!-- Persistence settings for 'cache6' -->
+    <bean id="cache6_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/pojo/persistence-settings-6.xml"
 />
+    </bean>
+
     <!-- Persistence settings for 'product' -->
     <bean id="product_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/pojo/product.xml" />
@@ -112,6 +122,32 @@
                     </property>
                 </bean>
 
+                <!-- Configuring persistence for "cache5" cache -->
+                <bean 
class="org.apache.ignite.configuration.CacheConfiguration">
+                    <property name="name" value="cache5"/>
+                    <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="cache5_persistence_settings"/>
+                        </bean>
+                    </property>
+                </bean>
+
+                <!-- Configuring persistence for "cache6" cache -->
+                <bean 
class="org.apache.ignite.configuration.CacheConfiguration">
+                    <property name="name" value="cache6"/>
+                    <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="cache6_persistence_settings"/>
+                        </bean>
+                    </property>
+                </bean>
+
                 <!-- Configuring persistence for "product" cache -->
                 <bean 
class="org.apache.ignite.configuration.CacheConfiguration">
                     <property name="name" value="product"/>

http://git-wip-us.apache.org/repos/asf/ignite/blob/d44fdd45/modules/cassandra/store/src/test/resources/org/apache/ignite/tests/persistence/pojo/persistence-settings-5.xml
----------------------------------------------------------------------
diff --git 
a/modules/cassandra/store/src/test/resources/org/apache/ignite/tests/persistence/pojo/persistence-settings-5.xml
 
b/modules/cassandra/store/src/test/resources/org/apache/ignite/tests/persistence/pojo/persistence-settings-5.xml
new file mode 100644
index 0000000..f4210b8
--- /dev/null
+++ 
b/modules/cassandra/store/src/test/resources/org/apache/ignite/tests/persistence/pojo/persistence-settings-5.xml
@@ -0,0 +1,21 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<persistence keyspace="test1" table="pojo_test5">
+    <keyPersistence class="org.apache.ignite.tests.pojos.SimplePersonId" 
strategy="POJO"/>
+    <valuePersistence class="org.apache.ignite.tests.pojos.SimplePerson" 
strategy="POJO"/>
+</persistence>

http://git-wip-us.apache.org/repos/asf/ignite/blob/d44fdd45/modules/cassandra/store/src/test/resources/org/apache/ignite/tests/persistence/pojo/persistence-settings-6.xml
----------------------------------------------------------------------
diff --git 
a/modules/cassandra/store/src/test/resources/org/apache/ignite/tests/persistence/pojo/persistence-settings-6.xml
 
b/modules/cassandra/store/src/test/resources/org/apache/ignite/tests/persistence/pojo/persistence-settings-6.xml
new file mode 100644
index 0000000..340f646
--- /dev/null
+++ 
b/modules/cassandra/store/src/test/resources/org/apache/ignite/tests/persistence/pojo/persistence-settings-6.xml
@@ -0,0 +1,174 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<!--
+Root container for persistence settings configuration.
+
+Note: required element
+
+Attributes:
+  1) keyspace [required] - keyspace for Cassandra tables which should be used 
to store key/value pairs
+  2) table    [required] - Cassandra tables which should be used to store 
key/value pairs
+  3) ttl      [optional] - expiration period for the table rows (in seconds)
+-->
+<persistence keyspace="test1" table="pojo_test6" ttl="86400">
+    <!--
+    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>
+
+    <!--
+    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>
+
+    <!--
+    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 
which controls how object
+        should be persisted/loaded to/from Cassandra table:
+            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.apache.ignite.tests.pojos.SimplePersonId" 
strategy="POJO">
+        <!--
+        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>
+            <!--
+             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" />
+            <field name="departmentCode" column="department" />
+        </partitionKey>
+
+        <!--
+        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>
+            <!--
+             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="personNum" column="number" sort="desc"/>
+        </clusterKey>
+    </keyPersistence>
+
+    <!--
+    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 
which controls how object
+        should be persisted/loaded to/from Cassandra table:
+            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.apache.ignite.tests.pojos.SimplePerson"
+                      strategy="POJO"
+                      
serializer="org.apache.ignite.cache.store.cassandra.serializer.JavaSerializer">
+        <!--
+         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, in case 
you want to use custom index
+           6) indexOptions [optional] - custom index options
+        -->
+        <field name="personNum" column="number" />
+        <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>

Reply via email to