You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sb...@apache.org on 2015/11/24 08:10:57 UTC
[07/19] ignite git commit: IGNITE-1753 Refactored usages of
deprectaed CacheTypeMetadata to JdbcType.
http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStore.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStore.java b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStore.java
index d78ea48..aa013b9 100644
--- a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStore.java
+++ b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStore.java
@@ -21,226 +21,392 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.SQLException;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.cache.CacheException;
import javax.cache.integration.CacheLoaderException;
-import org.apache.ignite.cache.CacheTypeFieldMetadata;
-import org.apache.ignite.cache.CacheTypeMetadata;
+import org.apache.ignite.binary.BinaryObject;
+import org.apache.ignite.binary.BinaryObjectBuilder;
import org.apache.ignite.cache.store.CacheStore;
import org.apache.ignite.configuration.CacheConfiguration;
-import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.jetbrains.annotations.Nullable;
/**
* Implementation of {@link CacheStore} backed by JDBC and POJO via reflection.
*
- * This implementation stores objects in underlying database using java beans mapping description via reflection.
- * <p>
+ * This implementation stores objects in underlying database using java beans mapping description via reflection. <p>
* Use {@link CacheJdbcPojoStoreFactory} factory to pass {@link CacheJdbcPojoStore} to {@link CacheConfiguration}.
*/
public class CacheJdbcPojoStore<K, V> extends CacheAbstractJdbcStore<K, V> {
+ /** POJO methods cache. */
+ private volatile Map<String, Map<String, PojoMethodsCache>> pojosMthds = Collections.emptyMap();
+
/**
- * POJO methods cache.
+ * Get field value from object for use as query parameter.
+ *
+ * @param cacheName Cache name.
+ * @param typeName Type name.
+ * @param fldName Field name.
+ * @param obj Cache object.
+ * @return Field value from object.
+ * @throws CacheException in case of error.
*/
- protected static class PojoMethodsCache {
- /** POJO class. */
- protected final Class<?> cls;
-
- /** Constructor for POJO object. */
- private Constructor ctor;
-
- /** {@code true} if object is a simple type. */
- private final boolean simple;
-
- /** Cached setters for POJO object. */
- private Map<String, Method> getters;
-
- /** Cached getters for POJO object. */
- private Map<String, Method> setters;
-
- /**
- * POJO methods cache.
- *
- * @param clsName Class name.
- * @param fields Fields.
- *
- * @throws CacheException If failed to construct type cache.
- */
- public PojoMethodsCache(String clsName, Collection<CacheTypeFieldMetadata> fields) throws CacheException {
- try {
- cls = Class.forName(clsName);
-
- if (simple = simpleType(cls))
- return;
+ @Override @Nullable protected Object extractParameter(@Nullable String cacheName, String typeName, TypeKind typeKind,
+ String fldName, Object obj) throws CacheException {
+ switch (typeKind) {
+ case BUILT_IN:
+ return obj;
+ case POJO:
+ return extractPojoParameter(cacheName, typeName, fldName, obj);
+ default:
+ return extractBinaryParameter(fldName, obj);
+ }
+ }
- ctor = cls.getDeclaredConstructor();
+ /**
+ * Get field value from POJO for use as query parameter.
+ *
+ * @param cacheName Cache name.
+ * @param typeName Type name.
+ * @param fldName Field name.
+ * @param obj Cache object.
+ * @return Field value from object.
+ * @throws CacheException in case of error.
+ */
+ @Nullable private Object extractPojoParameter(@Nullable String cacheName, String typeName, String fldName,
+ Object obj) throws CacheException {
+ try {
+ Map<String, PojoMethodsCache> cacheMethods = pojosMthds.get(cacheName);
- if (!ctor.isAccessible())
- ctor.setAccessible(true);
- }
- catch (ClassNotFoundException e) {
- throw new CacheException("Failed to find class: " + clsName, e);
- }
- catch (NoSuchMethodException e) {
- throw new CacheException("Failed to find default constructor for class: " + clsName, e);
- }
+ if (cacheMethods == null)
+ throw new CacheException("Failed to find POJO type metadata for cache: " + U.maskName(cacheName));
- setters = U.newHashMap(fields.size());
+ PojoMethodsCache mc = cacheMethods.get(typeName);
- getters = U.newHashMap(fields.size());
+ if (mc == null)
+ throw new CacheException("Failed to find POJO type metadata for type: " + typeName);
- for (CacheTypeFieldMetadata field : fields) {
- String prop = capitalFirst(field.getJavaName());
+ Method getter = mc.getters.get(fldName);
- try {
- getters.put(field.getJavaName(), cls.getMethod("get" + prop));
- }
- catch (NoSuchMethodException ignored) {
- try {
- getters.put(field.getJavaName(), cls.getMethod("is" + prop));
- }
- catch (NoSuchMethodException e) {
- throw new CacheException("Failed to find getter in POJO class [clsName=" + clsName +
- ", prop=" + field.getJavaName() + "]", e);
- }
- }
+ if (getter == null)
+ throw new CacheLoaderException("Failed to find getter in POJO class [class=" + typeName +
+ ", prop=" + fldName + "]");
- try {
- setters.put(field.getJavaName(), cls.getMethod("set" + prop, field.getJavaType()));
- }
- catch (NoSuchMethodException e) {
- throw new CacheException("Failed to find setter in POJO class [clsName=" + clsName +
- ", prop=" + field.getJavaName() + "]", e);
- }
- }
+ return getter.invoke(obj);
}
-
- /**
- * Capitalizes the first character of the given string.
- *
- * @param str String.
- * @return String with capitalized first character.
- */
- @Nullable private String capitalFirst(@Nullable String str) {
- return str == null ? null :
- str.isEmpty() ? "" : Character.toUpperCase(str.charAt(0)) + str.substring(1);
+ catch (Exception e) {
+ throw new CacheException("Failed to read object of class: " + typeName, e);
}
}
- /** Methods cache. */
- protected volatile Map<String, Map<String, PojoMethodsCache>> mtdsCache = Collections.emptyMap();
+ /**
+ * Get field value from Binary object for use as query parameter.
+ *
+ * @param fieldName Field name to extract query parameter for.
+ * @param obj Object to process.
+ * @return Field value from object.
+ * @throws CacheException in case of error.
+ */
+ private Object extractBinaryParameter(String fieldName, Object obj) throws CacheException {
+ if (obj instanceof BinaryObject)
+ return ((BinaryObject)obj).field(fieldName);
+
+ throw new CacheException("Failed to read property value from non binary object [class=" +
+ obj.getClass() + ", property=" + fieldName + "]");
+ }
/** {@inheritDoc} */
- @Override protected void prepareBuilders(@Nullable String cacheName, Collection<CacheTypeMetadata> types)
- throws CacheException {
- Map<String, PojoMethodsCache> typeMethods = U.newHashMap(types.size() * 2);
+ @Override protected <R> R buildObject(@Nullable String cacheName, String typeName, TypeKind typeKind,
+ JdbcTypeField[] flds, Collection<String> hashFlds, Map<String, Integer> loadColIdxs, ResultSet rs)
+ throws CacheLoaderException {
+ switch (typeKind) {
+ case BUILT_IN:
+ return (R)buildBuiltinObject(typeName, flds, loadColIdxs, rs);
+ case POJO:
+ return (R)buildPojoObject(cacheName, typeName, flds, loadColIdxs, rs);
+ default:
+ return (R)buildBinaryObject(typeName, flds, hashFlds, loadColIdxs, rs);
+ }
+ }
- for (CacheTypeMetadata type : types) {
- String keyType = type.getKeyType();
- typeMethods.put(keyType, new PojoMethodsCache(keyType, type.getKeyFields()));
+ /**
+ * Construct Java built in object from query result.
+ *
+ * @param typeName Type name.
+ * @param fields Fields descriptors.
+ * @param loadColIdxs Select query columns indexes.
+ * @param rs ResultSet to take data from.
+ * @return Constructed object.
+ * @throws CacheLoaderException If failed to construct POJO.
+ */
+ private Object buildBuiltinObject(String typeName, JdbcTypeField[] fields, Map<String, Integer> loadColIdxs,
+ ResultSet rs) throws CacheLoaderException {
+ try {
+ JdbcTypeField field = fields[0];
- String valType = type.getValueType();
- typeMethods.put(valType, new PojoMethodsCache(valType, type.getValueFields()));
+ return getColumnValue(rs, loadColIdxs.get(field.getDatabaseFieldName()), field.getJavaFieldType());
}
+ catch (SQLException e) {
+ throw new CacheLoaderException("Failed to read object of class: " + typeName, e);
+ }
+ }
- Map<String, Map<String, PojoMethodsCache>> newMtdsCache = new HashMap<>(mtdsCache);
+ /**
+ * Construct POJO from query result.
+ *
+ * @param cacheName Cache name.
+ * @param typeName Type name.
+ * @param flds Fields descriptors.
+ * @param loadColIdxs Select query columns index.
+ * @param rs ResultSet.
+ * @return Constructed POJO.
+ * @throws CacheLoaderException If failed to construct POJO.
+ */
+ private Object buildPojoObject(@Nullable String cacheName, String typeName,
+ JdbcTypeField[] flds, Map<String, Integer> loadColIdxs, ResultSet rs)
+ throws CacheLoaderException {
- newMtdsCache.put(cacheName, typeMethods);
+ Map<String, PojoMethodsCache> cacheMethods = pojosMthds.get(cacheName);
- mtdsCache = newMtdsCache;
- }
+ if (cacheMethods == null)
+ throw new CacheLoaderException("Failed to find POJO types metadata for cache: " + U.maskName(cacheName));
- /** {@inheritDoc} */
- @Override protected <R> R buildObject(String cacheName, String typeName, Collection<CacheTypeFieldMetadata> fields,
- Map<String, Integer> loadColIdxs, ResultSet rs) throws CacheLoaderException {
- PojoMethodsCache mc = mtdsCache.get(cacheName).get(typeName);
+ PojoMethodsCache mc = cacheMethods.get(typeName);
if (mc == null)
- throw new CacheLoaderException("Failed to find cache type metadata for type: " + typeName);
+ throw new CacheLoaderException("Failed to find POJO type metadata for type: " + typeName);
try {
- if (mc.simple) {
- CacheTypeFieldMetadata field = F.first(fields);
-
- return (R)getColumnValue(rs, loadColIdxs.get(field.getDatabaseName()), mc.cls);
- }
-
Object obj = mc.ctor.newInstance();
- for (CacheTypeFieldMetadata field : fields) {
- String fldJavaName = field.getJavaName();
+ for (JdbcTypeField fld : flds) {
+ String fldJavaName = fld.getJavaFieldName();
Method setter = mc.setters.get(fldJavaName);
if (setter == null)
- throw new IllegalStateException("Failed to find setter in POJO class [clsName=" + typeName +
+ throw new IllegalStateException("Failed to find setter in POJO class [type=" + typeName +
", prop=" + fldJavaName + "]");
- String fldDbName = field.getDatabaseName();
+ String fldDbName = fld.getDatabaseFieldName();
Integer colIdx = loadColIdxs.get(fldDbName);
try {
- setter.invoke(obj, getColumnValue(rs, colIdx, field.getJavaType()));
+ Object colVal = getColumnValue(rs, colIdx, fld.getJavaFieldType());
+
+ try {
+ setter.invoke(obj, colVal);
+ }
+ catch (Exception e) {
+ throw new CacheLoaderException("Failed to set property in POJO class [type=" + typeName +
+ ", prop=" + fldJavaName + ", col=" + colIdx + ", dbName=" + fldDbName + "]", e);
+ }
}
- catch (Exception e) {
- throw new IllegalStateException("Failed to set property in POJO class [clsName=" + typeName +
+ catch (SQLException e) {
+ throw new CacheLoaderException("Failed to read object property [type= " + typeName +
", prop=" + fldJavaName + ", col=" + colIdx + ", dbName=" + fldDbName + "]", e);
}
}
- return (R)obj;
- }
- catch (SQLException e) {
- throw new CacheLoaderException("Failed to read object of class: " + typeName, e);
+ return obj;
}
catch (Exception e) {
throw new CacheLoaderException("Failed to construct instance of class: " + typeName, e);
}
}
- /** {@inheritDoc} */
- @Nullable @Override protected Object extractParameter(String cacheName, String typeName, String fieldName,
- Object obj)
- throws CacheException {
+ /**
+ * Construct binary object from query result.
+ *
+ * @param typeName Type name.
+ * @param fields Fields descriptors.
+ * @param hashFields Collection of fields to build hash for.
+ * @param loadColIdxs Select query columns index.
+ * @param rs ResultSet.
+ * @return Constructed binary object.
+ * @throws CacheLoaderException If failed to construct binary object.
+ */
+ protected Object buildBinaryObject(String typeName, JdbcTypeField[] fields,
+ Collection<String> hashFields, Map<String, Integer> loadColIdxs, ResultSet rs) throws CacheLoaderException {
try {
- PojoMethodsCache mc = mtdsCache.get(cacheName).get(typeName);
+ BinaryObjectBuilder builder = ignite.binary().builder(typeName);
- if (mc == null)
- throw new CacheException("Failed to find cache type metadata for type: " + typeName);
+ boolean calcHash = hashFields != null;
- if (mc.simple)
- return obj;
+ Collection<Object> hashValues = calcHash ? new ArrayList<>(hashFields.size()) : null;
- Method getter = mc.getters.get(fieldName);
+ for (JdbcTypeField field : fields) {
+ Integer colIdx = loadColIdxs.get(field.getDatabaseFieldName());
- if (getter == null)
- throw new CacheLoaderException("Failed to find getter in POJO class [clsName=" + typeName +
- ", prop=" + fieldName + "]");
+ Object colVal = getColumnValue(rs, colIdx, field.getJavaFieldType());
- return getter.invoke(obj);
+ builder.setField(field.getJavaFieldName(), colVal);
+
+ if (calcHash)
+ hashValues.add(colVal);
+ }
+
+ if (calcHash)
+ builder.hashCode(hasher.hashCode(hashValues));
+
+ return builder.build();
}
- catch (Exception e) {
- throw new CacheException("Failed to read object of class: " + typeName, e);
+ catch (SQLException e) {
+ throw new CacheException("Failed to read binary object", e);
}
}
- /** {@inheritDoc} */
- @Override protected Object keyTypeId(Object key) throws CacheException {
- return key.getClass();
+ /**
+ * Calculate type ID for object.
+ *
+ * @param obj Object to calculate type ID for.
+ * @return Type ID.
+ * @throws CacheException If failed to calculate type ID for given object.
+ */
+ @Override protected Object typeIdForObject(Object obj) throws CacheException {
+ if (obj instanceof BinaryObject)
+ return ((BinaryObject)obj).typeId();
+
+ return obj.getClass();
}
/** {@inheritDoc} */
- @Override protected Object keyTypeId(String type) throws CacheException {
+ @Override protected Object typeIdForTypeName(TypeKind kind, String typeName) throws CacheException {
+ if (kind == TypeKind.BINARY)
+ return ignite.binary().typeId(typeName);
+
try {
- return Class.forName(type);
+ return Class.forName(typeName);
}
catch (ClassNotFoundException e) {
- throw new CacheException("Failed to find class: " + type, e);
+ throw new CacheException("Failed to find class: " + typeName, e);
+ }
+ }
+
+ /**
+ * Prepare internal store specific builders for provided types metadata.
+ *
+ * @param cacheName Cache name to prepare builders for.
+ * @param types Collection of types.
+ * @throws CacheException If failed to prepare internal builders for types.
+ */
+ @Override protected void prepareBuilders(@Nullable String cacheName, Collection<JdbcType> types)
+ throws CacheException {
+ Map<String, PojoMethodsCache> pojoMethods = U.newHashMap(types.size() * 2);
+
+ for (JdbcType type : types) {
+ String keyTypeName = type.getKeyType();
+
+ TypeKind keyKind = kindForName(keyTypeName);
+
+ if (keyKind == TypeKind.POJO) {
+ if (pojoMethods.containsKey(keyTypeName))
+ throw new CacheException("Found duplicate key type [cache=" + U.maskName(cacheName) +
+ ", keyType=" + keyTypeName + "]");
+
+ pojoMethods.put(keyTypeName, new PojoMethodsCache(keyTypeName, type.getKeyFields()));
+ }
+
+ String valTypeName = type.getValueType();
+
+ TypeKind valKind = kindForName(valTypeName);
+
+ if (valKind == TypeKind.POJO)
+ pojoMethods.put(valTypeName, new PojoMethodsCache(valTypeName, type.getValueFields()));
+ }
+
+ if (!pojoMethods.isEmpty()) {
+ Map<String, Map<String, PojoMethodsCache>> newPojosMethods = new HashMap<>(pojosMthds);
+
+ newPojosMethods.put(cacheName, pojoMethods);
+
+ pojosMthds = newPojosMethods;
+ }
+ }
+
+ /**
+ * POJO methods cache.
+ */
+ private static class PojoMethodsCache {
+ /** POJO class. */
+ private final Class<?> cls;
+
+ /** Constructor for POJO object. */
+ private Constructor ctor;
+
+ /** Cached setters for POJO object. */
+ private Map<String, Method> getters;
+
+ /** Cached getters for POJO object. */
+ private Map<String, Method> setters;
+
+ /**
+ * POJO methods cache.
+ *
+ * @param clsName Class name.
+ * @param fields Fields.
+ * @throws CacheException If failed to construct type cache.
+ */
+ private PojoMethodsCache(String clsName, JdbcTypeField[] fields) throws CacheException {
+ try {
+ cls = Class.forName(clsName);
+
+ ctor = cls.getDeclaredConstructor();
+
+ if (!ctor.isAccessible())
+ ctor.setAccessible(true);
+ }
+ catch (ClassNotFoundException e) {
+ throw new CacheException("Failed to find class: " + clsName, e);
+ }
+ catch (NoSuchMethodException e) {
+ throw new CacheException("Failed to find default constructor for class: " + clsName, e);
+ }
+
+ setters = U.newHashMap(fields.length);
+
+ getters = U.newHashMap(fields.length);
+
+ for (JdbcTypeField field : fields) {
+ String prop = capitalFirst(field.getJavaFieldName());
+
+ try {
+ getters.put(field.getJavaFieldName(), cls.getMethod("get" + prop));
+ }
+ catch (NoSuchMethodException ignored) {
+ try {
+ getters.put(field.getJavaFieldName(), cls.getMethod("is" + prop));
+ }
+ catch (NoSuchMethodException e) {
+ throw new CacheException("Failed to find getter in POJO class [class=" + clsName +
+ ", prop=" + field.getJavaFieldName() + "]", e);
+ }
+ }
+
+ try {
+ setters.put(field.getJavaFieldName(), cls.getMethod("set" + prop, field.getJavaFieldType()));
+ }
+ catch (NoSuchMethodException e) {
+ throw new CacheException("Failed to find setter in POJO class [class=" + clsName +
+ ", prop=" + field.getJavaFieldName() + "]", e);
+ }
+ }
+ }
+
+ /**
+ * Capitalizes the first character of the given string.
+ *
+ * @param str String.
+ * @return String with capitalized first character.
+ */
+ @Nullable private String capitalFirst(@Nullable String str) {
+ return str == null ? null :
+ str.isEmpty() ? "" : Character.toUpperCase(str.charAt(0)) + str.substring(1);
}
}
-}
\ No newline at end of file
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreFactory.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreFactory.java b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreFactory.java
index c90a69b..ded83ce 100644
--- a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreFactory.java
+++ b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreFactory.java
@@ -34,17 +34,53 @@ import org.apache.ignite.resources.SpringApplicationContextResource;
*
* <h2 class="header">Spring Example</h2>
* <pre name="code" class="xml">
- * <bean id= "simpleDataSource" class="org.h2.jdbcx.JdbcDataSource"/>
+ * <bean id= "myDataSource" class="org.h2.jdbcx.JdbcDataSource"/>
*
* <bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
* ...
* <property name="cacheConfiguration">
* <list>
* <bean class="org.apache.ignite.configuration.CacheConfiguration">
+ * <property name="name" value="myCache" />
* ...
* <property name="cacheStoreFactory">
* <bean class="org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory">
- * <property name="dataSourceBean" value = "simpleDataSource" />
+ * <property name="dataSourceBean" value="myDataSource" />
+ * <property name="types">
+ * <list>
+ * <bean class="org.apache.ignite.cache.store.jdbc.JdbcType">
+ * <property name="cacheName" value="myCache" />
+ * <property name="databaseSchema" value="MY_DB_SCHEMA" />
+ * <property name="databaseTable" value="PERSON" />
+ * <property name="keyType" value="java.lang.Integer" />
+ * <property name="keyFields">
+ * <list>
+ * <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+ * <property name="databaseFieldType" >
+ * <util:constant static-field="java.sql.Types.INTEGER"/>
+ * </property>
+ * <property name="databaseFieldName" value="ID" />
+ * <property name="javaFieldType" value="java.lang.Integer" />
+ * <property name="javaFieldName" value="id" />
+ * </bean>
+ * </list>
+ * </property>
+ * <property name="valueType" value="my.company.Person" />
+ * <property name="valueFields">
+ * <list>
+ * <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+ * <property name="databaseFieldType" >
+ * <util:constant static-field="java.sql.Types.VARCHAR"/>
+ * </property>
+ * <property name="databaseFieldName" value="NAME" />
+ * <property name="javaFieldType" value="java.lang.String" />
+ * <property name="javaFieldName" value="name" />
+ * </bean>
+ * </list>
+ * </property>
+ * </bean>
+ * </list>
+ * </property>
* </bean>
* </property>
* </bean>
@@ -57,47 +93,81 @@ import org.apache.ignite.resources.SpringApplicationContextResource;
* <br>
* For information about Spring framework visit <a href="http://www.springframework.org/">www.springframework.org</a>
*/
-public class CacheJdbcPojoStoreFactory<K, V> implements Factory<CacheJdbcPojoStore<K, V>> {
+public class CacheJdbcPojoStoreFactory<K, V> implements Factory<CacheAbstractJdbcStore<K, V>> {
/** */
private static final long serialVersionUID = 0L;
+ /** Default value for write attempts. */
+ public static final int DFLT_WRITE_ATTEMPTS = 2;
+
+ /** Default batch size for put and remove operations. */
+ public static final int DFLT_BATCH_SIZE = 512;
+
+ /** Default batch size for put and remove operations. */
+ public static final int DFLT_PARALLEL_LOAD_CACHE_MINIMUM_THRESHOLD = 512;
+
+ /** Maximum batch size for writeAll and deleteAll operations. */
+ private int batchSizw = DFLT_BATCH_SIZE;
+
/** Name of data source bean. */
private String dataSrcBean;
- /** Data source. */
- private transient DataSource dataSrc;
-
/** Database dialect. */
private JdbcDialect dialect;
+ /** Max workers thread count. These threads are responsible for load cache. */
+ private int maxPoolSize = Runtime.getRuntime().availableProcessors();
+
+ /** Maximum write attempts in case of database error. */
+ private int maxWriteAttempts = DFLT_WRITE_ATTEMPTS;
+
+ /** Parallel load cache minimum threshold. If {@code 0} then load sequentially. */
+ private int parallelLoadCacheMinThreshold = DFLT_PARALLEL_LOAD_CACHE_MINIMUM_THRESHOLD;
+
+ /** Hash calculator. */
+ private JdbcTypeHasher hasher = JdbcTypeDefaultHasher.INSTANCE;
+
+ /** Types that store could process. */
+ private JdbcType[] types;
+
+ /** Data source. */
+ private transient DataSource dataSrc;
+
/** Application context. */
@SpringApplicationContextResource
- private transient Object appContext;
+ private transient Object appCtx;
/** {@inheritDoc} */
@Override public CacheJdbcPojoStore<K, V> create() {
CacheJdbcPojoStore<K, V> store = new CacheJdbcPojoStore<>();
+ store.setBatchSize(batchSizw);
store.setDialect(dialect);
+ store.setMaximumPoolSize(maxPoolSize);
+ store.setMaximumWriteAttempts(maxWriteAttempts);
+ store.setParallelLoadCacheMinimumThreshold(parallelLoadCacheMinThreshold);
+ store.setTypes(types);
if (dataSrc != null)
store.setDataSource(dataSrc);
- else if (dataSrcBean != null) {
- if (appContext == null)
- throw new IgniteException("Spring application context resource is not injected.");
+ else {
+ if (dataSrcBean != null) {
+ if (appCtx == null)
+ throw new IgniteException("Spring application context resource is not injected.");
- IgniteSpringHelper spring;
+ IgniteSpringHelper spring;
- try {
- spring = IgniteComponentType.SPRING.create(false);
+ try {
+ spring = IgniteComponentType.SPRING.create(false);
- DataSource data = spring.loadBeanFromAppContext(appContext, dataSrcBean);
+ DataSource data = spring.loadBeanFromAppContext(appCtx, dataSrcBean);
- store.setDataSource(data);
- }
- catch (Exception e) {
- throw new IgniteException("Failed to load bean in application context [beanName=" + dataSrcBean +
- ", igniteConfig=" + appContext + ']', e);
+ store.setDataSource(data);
+ }
+ catch (Exception e) {
+ throw new IgniteException("Failed to load bean in application context [beanName=" + dataSrcBean +
+ ", igniteConfig=" + appCtx + ']', e);
+ }
}
}
@@ -105,43 +175,188 @@ public class CacheJdbcPojoStoreFactory<K, V> implements Factory<CacheJdbcPojoSto
}
/**
- * Sets name of the data source bean.
+ * Sets data source. Data source should be fully configured and ready-to-use.
*
- * @param dataSrcBean Data source bean name.
+ * @param dataSrc Data source.
* @return {@code This} for chaining.
* @see CacheJdbcPojoStore#setDataSource(DataSource)
*/
- public CacheJdbcPojoStoreFactory<K, V> setDataSourceBean(String dataSrcBean) {
- this.dataSrcBean = dataSrcBean;
+ public CacheJdbcPojoStoreFactory<K, V> setDataSource(DataSource dataSrc) {
+ this.dataSrc = dataSrc;
return this;
}
/**
- * Sets data source. Data source should be fully configured and ready-to-use.
+ * Get maximum batch size for delete and delete operations.
*
- * @param dataSrc Data source.
+ * @return Maximum batch size.
+ */
+ public int getBatchSize() {
+ return batchSizw;
+ }
+
+ /**
+ * Set maximum batch size for write and delete operations.
+ *
+ * @param batchSize Maximum batch size.
* @return {@code This} for chaining.
- * @see CacheJdbcPojoStore#setDataSource(DataSource)
*/
- public CacheJdbcPojoStoreFactory<K, V> setDataSource(DataSource dataSrc) {
- this.dataSrc = dataSrc;
+ public CacheJdbcPojoStoreFactory setBatchSize(int batchSize) {
+ this.batchSizw = batchSize;
+
+ return this;
+ }
+
+ /**
+ * Gets name of the data source bean.
+ *
+ * @return Data source bean name.
+ */
+ public String getDataSourceBean() {
+ return dataSrcBean;
+ }
+
+ /**
+ * Sets name of the data source bean.
+ *
+ * @param dataSrcBean Data source bean name.
+ * @return {@code This} for chaining.
+ */
+ public CacheJdbcPojoStoreFactory setDataSourceBean(String dataSrcBean) {
+ this.dataSrcBean = dataSrcBean;
return this;
}
/**
+ * Get database dialect.
+ *
+ * @return Database dialect.
+ */
+ public JdbcDialect getDialect() {
+ return dialect;
+ }
+
+ /**
* Set database dialect.
*
* @param dialect Database dialect.
- * @see CacheJdbcPojoStore#setDialect(JdbcDialect)
+ * @return {@code This} for chaining.
*/
- public void setDialect(JdbcDialect dialect) {
+ public CacheJdbcPojoStoreFactory setDialect(JdbcDialect dialect) {
this.dialect = dialect;
+
+ return this;
+ }
+
+ /**
+ * Get maximum workers thread count. These threads are responsible for queries execution.
+ *
+ * @return Maximum workers thread count.
+ */
+ public int getMaximumPoolSize() {
+ return maxPoolSize;
+ }
+
+ /**
+ * Set Maximum workers thread count. These threads are responsible for queries execution.
+ *
+ * @param maxPoolSize Max workers thread count.
+ * @return {@code This} for chaining.
+ */
+ public CacheJdbcPojoStoreFactory setMaximumPoolSize(int maxPoolSize) {
+ this.maxPoolSize = maxPoolSize;
+
+ return this;
+ }
+
+ /**
+ * Gets maximum number of write attempts in case of database error.
+ *
+ * @return Maximum number of write attempts.
+ */
+ public int getMaximumWriteAttempts() {
+ return maxWriteAttempts;
+ }
+
+ /**
+ * Sets maximum number of write attempts in case of database error.
+ *
+ * @param maxWrtAttempts Number of write attempts.
+ * @return {@code This} for chaining.
+ */
+ public CacheJdbcPojoStoreFactory setMaximumWriteAttempts(int maxWrtAttempts) {
+ this.maxWriteAttempts = maxWrtAttempts;
+
+ return this;
+ }
+
+ /**
+ * Parallel load cache minimum row count threshold.
+ *
+ * @return If {@code 0} then load sequentially.
+ */
+ public int getParallelLoadCacheMinimumThreshold() {
+ return parallelLoadCacheMinThreshold;
+ }
+
+ /**
+ * Parallel load cache minimum row count threshold.
+ *
+ * @param parallelLoadCacheMinThreshold Minimum row count threshold. If {@code 0} then load sequentially.
+ * @return {@code This} for chaining.
+ */
+ public CacheJdbcPojoStoreFactory setParallelLoadCacheMinimumThreshold(int parallelLoadCacheMinThreshold) {
+ this.parallelLoadCacheMinThreshold = parallelLoadCacheMinThreshold;
+
+ return this;
+ }
+
+ /**
+ * Gets types known by store.
+ *
+ * @return Types known by store.
+ */
+ public JdbcType[] getTypes() {
+ return types;
+ }
+
+ /**
+ * Sets store configurations.
+ *
+ * @param types Store should process.
+ * @return {@code This} for chaining.
+ */
+ public CacheJdbcPojoStoreFactory setTypes(JdbcType... types) {
+ this.types = types;
+
+ return this;
+ }
+
+ /**
+ * Gets hash code calculator.
+ *
+ * @return Hash code calculator.
+ */
+ public JdbcTypeHasher getHasher() {
+ return hasher;
+ }
+
+ /**
+ * Sets hash code calculator.
+ *
+ * @param hasher Hash code calculator.
+ * @return {@code This} for chaining.
+ */
+ public CacheJdbcPojoStoreFactory setHasher(JdbcTypeHasher hasher) {
+ this.hasher = hasher;
+
+ return this;
}
/** {@inheritDoc} */
@Override public String toString() {
return S.toString(CacheJdbcPojoStoreFactory.class, this);
}
-}
\ No newline at end of file
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcType.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcType.java b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcType.java
new file mode 100644
index 0000000..2107240
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcType.java
@@ -0,0 +1,255 @@
+/*
+ * 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.jdbc;
+
+import java.io.Serializable;
+import org.apache.ignite.internal.util.tostring.GridToStringInclude;
+import org.apache.ignite.internal.util.typedef.internal.S;
+
+/**
+ * Description for type that could be stored into database by store.
+ */
+public class JdbcType implements Serializable {
+ /** */
+ private static final long serialVersionUID = 0L;
+
+ /** Cache name. */
+ private String cacheName;
+
+ /** Schema name in database. */
+ private String dbSchema;
+
+ /** Table name in database. */
+ private String dbTbl;
+
+ /** Key class used to store key in cache. */
+ private String keyType;
+
+ /** List of fields descriptors for key object. */
+ @GridToStringInclude
+ private JdbcTypeField[] keyFields;
+
+ /** Value class used to store value in cache. */
+ private String valType;
+
+ /** List of fields descriptors for value object. */
+ @GridToStringInclude
+ private JdbcTypeField[] valFlds;
+
+ /** Custom type hasher. */
+ private JdbcTypeHasher hasher;
+
+ /**
+ * Empty constructor (all values are initialized to their defaults).
+ */
+ public JdbcType() {
+ /* No-op. */
+ }
+
+ /**
+ * Copy constructor.
+ *
+ * @param type Type to copy.
+ */
+ public JdbcType(JdbcType type) {
+ cacheName = type.getCacheName();
+
+ dbSchema = type.getDatabaseSchema();
+ dbTbl = type.getDatabaseTable();
+
+ keyType = type.getKeyType();
+ keyFields = type.getKeyFields();
+
+ valType = type.getValueType();
+ valFlds = type.getValueFields();
+ }
+
+ /**
+ * Gets associated cache name.
+ *
+ * @return Сache name.
+ */
+ public String getCacheName() {
+ return cacheName;
+ }
+
+ /**
+ * Sets associated cache name.
+ *
+ * @param cacheName Cache name.
+ */
+ public JdbcType setCacheName(String cacheName) {
+ this.cacheName = cacheName;
+
+ return this;
+ }
+
+ /**
+ * Gets database schema name.
+ *
+ * @return Schema name.
+ */
+ public String getDatabaseSchema() {
+ return dbSchema;
+ }
+
+ /**
+ * Sets database schema name.
+ *
+ * @param dbSchema Schema name.
+ */
+ public JdbcType setDatabaseSchema(String dbSchema) {
+ this.dbSchema = dbSchema;
+
+ return this;
+ }
+
+ /**
+ * Gets table name in database.
+ *
+ * @return Table name in database.
+ */
+ public String getDatabaseTable() {
+ return dbTbl;
+ }
+
+ /**
+ * Table name in database.
+ *
+ * @param dbTbl Table name in database.
+ * @return {@code this} for chaining.
+ */
+ public JdbcType setDatabaseTable(String dbTbl) {
+ this.dbTbl = dbTbl;
+
+ return this;
+ }
+
+ /**
+ * Gets key type.
+ *
+ * @return Key type.
+ */
+ public String getKeyType() {
+ return keyType;
+ }
+
+ /**
+ * Sets key type.
+ *
+ * @param keyType Key type.
+ * @return {@code this} for chaining.
+ */
+ public JdbcType setKeyType(String keyType) {
+ this.keyType = keyType;
+
+ return this;
+ }
+
+ /**
+ * Sets key type.
+ *
+ * @param cls Key type class.
+ * @return {@code this} for chaining.
+ */
+ public JdbcType setKeyType(Class<?> cls) {
+ setKeyType(cls.getName());
+
+ return this;
+ }
+
+ /**
+ * Gets value type.
+ *
+ * @return Key type.
+ */
+ public String getValueType() {
+ return valType;
+ }
+
+ /**
+ * Sets value type.
+ *
+ * @param valType Value type.
+ * @return {@code this} for chaining.
+ */
+ public JdbcType setValueType(String valType) {
+ this.valType = valType;
+
+ return this;
+ }
+
+ /**
+ * Sets value type.
+ *
+ * @param cls Value type class.
+ * @return {@code this} for chaining.
+ */
+ public JdbcType setValueType(Class<?> cls) {
+ setValueType(cls.getName());
+
+ return this;
+ }
+
+ /**
+ * Gets optional persistent key fields (needed only if {@link CacheJdbcPojoStore} is used).
+ *
+ * @return Persistent key fields.
+ */
+ public JdbcTypeField[] getKeyFields() {
+ return keyFields;
+ }
+
+ /**
+ * Sets optional persistent key fields (needed only if {@link CacheJdbcPojoStore} is used).
+ *
+ * @param keyFlds Persistent key fields.
+ * @return {@code this} for chaining.
+ */
+ public JdbcType setKeyFields(JdbcTypeField... keyFlds) {
+ this.keyFields = keyFlds;
+
+ return this;
+ }
+
+ /**
+ * Gets optional persistent value fields (needed only if {@link CacheJdbcPojoStore} is used).
+ *
+ * @return Persistent value fields.
+ */
+ public JdbcTypeField[] getValueFields() {
+ return valFlds;
+ }
+
+ /**
+ * Sets optional persistent value fields (needed only if {@link CacheJdbcPojoStore} is used).
+ *
+ * @param valFlds Persistent value fields.
+ * @return {@code this} for chaining.
+ */
+ public JdbcType setValueFields(JdbcTypeField... valFlds) {
+ this.valFlds = valFlds;
+
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(JdbcType.class, this);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypeDefaultHasher.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypeDefaultHasher.java b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypeDefaultHasher.java
new file mode 100644
index 0000000..3baad3b
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypeDefaultHasher.java
@@ -0,0 +1,43 @@
+/*
+ * 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.jdbc;
+
+import java.util.Collection;
+
+/**
+ * Default implementation of {@link JdbcTypeHasher}.
+ *
+ * This implementation ignores type and field names.
+ */
+public class JdbcTypeDefaultHasher implements JdbcTypeHasher {
+ /** */
+ private static final long serialVersionUID = 0L;
+
+ /** Singleton instance to use. */
+ public static final JdbcTypeHasher INSTANCE = new JdbcTypeDefaultHasher();
+
+ /** {@inheritDoc} */
+ @Override public int hashCode(Collection<?> values) {
+ int hash = 0;
+
+ for (Object val : values)
+ hash = 31 * hash + (val != null ? val.hashCode() : 0);
+
+ return hash;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypeField.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypeField.java b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypeField.java
new file mode 100644
index 0000000..3396b81
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypeField.java
@@ -0,0 +1,172 @@
+/*
+ * 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.jdbc;
+
+import java.io.Serializable;
+import org.apache.ignite.internal.util.typedef.internal.S;
+
+/**
+ * Description of how field declared in database and in cache.
+ */
+public class JdbcTypeField implements Serializable {
+ /** */
+ private static final long serialVersionUID = 0L;
+
+ /** Field JDBC type in database. */
+ private int dbFldType;
+
+ /** Field name in database. */
+ private String dbFldName;
+
+ /** Field java type. */
+ private Class<?> javaFldType;
+
+ /** Field name in java object. */
+ private String javaFldName;
+
+ /**
+ * Default constructor.
+ */
+ public JdbcTypeField() {
+ // No-op.
+ }
+
+ /**
+ * Full constructor.
+ *
+ * @param dbFldType Field JDBC type in database.
+ * @param dbFldName Field name in database.
+ * @param javaFldType Field java type.
+ * @param javaFldName Field name in java object.
+ */
+ public JdbcTypeField(int dbFldType, String dbFldName, Class<?> javaFldType, String javaFldName) {
+ this.dbFldType = dbFldType;
+ this.dbFldName = dbFldName;
+ this.javaFldType = javaFldType;
+ this.javaFldName = javaFldName;
+ }
+
+ /**
+ * Copy constructor.
+ *
+ * @param field Field to copy.
+ */
+ public JdbcTypeField(JdbcTypeField field) {
+ this(field.getDatabaseFieldType(), field.getDatabaseFieldName(),
+ field.getJavaFieldType(), field.getJavaFieldName());
+ }
+
+ /**
+ * @return Column JDBC type in database.
+ */
+ public int getDatabaseFieldType() {
+ return dbFldType;
+ }
+
+ /**
+ * @param dbFldType Column JDBC type in database.
+ * @return {@code this} for chaining.
+ */
+ public JdbcTypeField setDatabaseFieldType(int dbFldType) {
+ this.dbFldType = dbFldType;
+
+ return this;
+ }
+
+
+ /**
+ * @return Column name in database.
+ */
+ public String getDatabaseFieldName() {
+ return dbFldName;
+ }
+
+ /**
+ * @param dbFldName Column name in database.
+ * @return {@code this} for chaining.
+ */
+ public JdbcTypeField setDatabaseFieldName(String dbFldName) {
+ this.dbFldName = dbFldName;
+
+ return this;
+ }
+
+ /**
+ * @return Field java type.
+ */
+ public Class<?> getJavaFieldType() {
+ return javaFldType;
+ }
+
+ /**
+ * @param javaFldType Corresponding java type.
+ * @return {@code this} for chaining.
+ */
+ public JdbcTypeField setJavaFieldType(Class<?> javaFldType) {
+ this.javaFldType = javaFldType;
+
+ return this;
+ }
+
+ /**
+ * @return Field name in java object.
+ */
+ public String getJavaFieldName() {
+ return javaFldName;
+ }
+
+ /**
+ * @param javaFldName Field name in java object.
+ * @return {@code this} for chaining.
+ */
+ public JdbcTypeField setJavaFieldName(String javaFldName) {
+ this.javaFldName = javaFldName;
+
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object o) {
+ if (this == o)
+ return true;
+
+ if (!(o instanceof JdbcTypeField))
+ return false;
+
+ JdbcTypeField that = (JdbcTypeField)o;
+
+ return dbFldType == that.dbFldType && dbFldName.equals(that.dbFldName) &&
+ javaFldType == that.javaFldType && javaFldName.equals(that.javaFldName);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ int res = dbFldType;
+ res = 31 * res + dbFldName.hashCode();
+
+ res = 31 * res + javaFldType.hashCode();
+ res = 31 * res + javaFldName.hashCode();
+
+ return res;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(JdbcTypeField.class, this);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypeHasher.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypeHasher.java b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypeHasher.java
new file mode 100644
index 0000000..9d1fcea
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypeHasher.java
@@ -0,0 +1,34 @@
+/*
+ * 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.jdbc;
+
+import java.io.Serializable;
+import java.util.Collection;
+
+/**
+ * API for implementing custom hashing logic for binary objects on server side.
+ */
+public interface JdbcTypeHasher extends Serializable {
+ /**
+ * Calculate hash code for specified object and fields.
+ *
+ * @param values Collection of values that should participate in hash code calculation.
+ * @return Hash code.
+ */
+ public int hashCode(Collection<?> values);
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
index fbe54e0..d0eeeb1 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
@@ -260,6 +260,10 @@ public class GridQueryProcessor extends GridProcessorAdapter {
if (F.isEmpty(meta.getValueType()))
throw new IgniteCheckedException("Value type is not set: " + meta);
+ if (meta.getQueryFields().isEmpty() && meta.getAscendingFields().isEmpty() &&
+ meta.getDescendingFields().isEmpty() && meta.getGroups().isEmpty())
+ continue;
+
TypeDescriptor desc = new TypeDescriptor();
// Key and value classes still can be available if they are primitive or JDK part.
@@ -2314,4 +2318,4 @@ public class GridQueryProcessor extends GridProcessorAdapter {
private enum IndexType {
ASC, DESC, TEXT
}
-}
\ No newline at end of file
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/core/src/main/java/org/apache/ignite/internal/visor/cache/VisorCache.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/visor/cache/VisorCache.java b/modules/core/src/main/java/org/apache/ignite/internal/visor/cache/VisorCache.java
index 6171ff8..1bbcf2f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/visor/cache/VisorCache.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/visor/cache/VisorCache.java
@@ -229,7 +229,9 @@ public class VisorCache implements Serializable {
protected void estimateMemorySize(IgniteEx ignite, GridCacheAdapter ca, int sample) throws IgniteCheckedException {
int size = ca.size();
- Set<GridCacheEntryEx> set = ca.map().entries0();
+ Set<GridCacheEntryEx> set = ca.context().isNear()
+ ? ((GridNearCacheAdapter)ca).dht().map().entries0()
+ : ca.map().entries0();
long memSz = 0;
http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreAbstractSelfTest.java b/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreAbstractSelfTest.java
new file mode 100644
index 0000000..0f40bd9
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreAbstractSelfTest.java
@@ -0,0 +1,395 @@
+/*
+ * 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.jdbc;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Types;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.store.jdbc.dialect.H2Dialect;
+import org.apache.ignite.cache.store.jdbc.model.Person;
+import org.apache.ignite.cache.store.jdbc.model.PersonKey;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.ConnectorConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.marshaller.Marshaller;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.h2.jdbcx.JdbcConnectionPool;
+
+import static org.apache.ignite.cache.CacheAtomicityMode.ATOMIC;
+import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
+import static org.apache.ignite.cache.CacheMode.PARTITIONED;
+
+/**
+ * Class for {@code PojoCacheStore} tests.
+ */
+public abstract class CacheJdbcPojoStoreAbstractSelfTest extends GridCommonAbstractTest {
+ /** IP finder. */
+ protected static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+ /** DB connection URL. */
+ protected static final String DFLT_CONN_URL = "jdbc:h2:mem:TestDatabase;DB_CLOSE_DELAY=-1";
+
+ /** Organization count. */
+ protected static final int ORGANIZATION_CNT = 1000;
+
+ /** Person count. */
+ protected static final int PERSON_CNT = 100000;
+
+ /** Flag indicating that tests should use transactional cache. */
+ protected static boolean transactional;
+
+ /** Flag indicating that tests should use primitive classes like java.lang.Integer for keys. */
+ protected static boolean builtinKeys;
+
+ /** Flag indicating that classes for keys available on class path or not. */
+ protected static boolean noKeyClasses;
+
+ /** Flag indicating that classes for values available on class path or not. */
+ protected static boolean noValClasses;
+
+ /**
+ * @return Connection to test in-memory H2 database.
+ * @throws SQLException
+ */
+ protected Connection getConnection() throws SQLException {
+ return DriverManager.getConnection(DFLT_CONN_URL, "sa", "");
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTest() throws Exception {
+ Connection conn = getConnection();
+
+ Statement stmt = conn.createStatement();
+
+ stmt.executeUpdate("DROP TABLE IF EXISTS Organization");
+ stmt.executeUpdate("DROP TABLE IF EXISTS Person");
+
+ stmt.executeUpdate("CREATE TABLE Organization (" +
+ " id INTEGER PRIMARY KEY," +
+ " name VARCHAR(50)," +
+ " city VARCHAR(50))");
+
+ stmt.executeUpdate("CREATE TABLE Person (" +
+ " id INTEGER PRIMARY KEY," +
+ " org_id INTEGER," +
+ " name VARCHAR(50))");
+
+ conn.commit();
+
+ U.closeQuiet(stmt);
+
+ fillSampleDatabase(conn);
+
+ U.closeQuiet(conn);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTest() throws Exception {
+ stopAllGrids();
+ }
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+ IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+ TcpDiscoverySpi disco = new TcpDiscoverySpi();
+
+ disco.setIpFinder(IP_FINDER);
+
+ cfg.setDiscoverySpi(disco);
+
+ cfg.setCacheConfiguration(cacheConfiguration());
+
+ cfg.setMarshaller(marshaller());
+
+ ConnectorConfiguration connCfg = new ConnectorConfiguration();
+ cfg.setConnectorConfiguration(connCfg);
+
+ return cfg;
+ }
+
+ /**
+ * @return Marshaller to be used in test.
+ */
+ protected abstract Marshaller marshaller();
+
+ /**
+ * @return Types to be used in test.
+ */
+ protected JdbcType[] storeTypes() {
+ JdbcType[] storeTypes = new JdbcType[2];
+
+ storeTypes[0] = new JdbcType();
+ storeTypes[0].setDatabaseSchema("PUBLIC");
+ storeTypes[0].setDatabaseTable("ORGANIZATION");
+
+ if (builtinKeys) {
+ storeTypes[0].setKeyType("java.lang.Integer");
+ storeTypes[0].setKeyFields(new JdbcTypeField(Types.INTEGER, "ID", Integer.class, "id"));
+ }
+ else {
+ storeTypes[0].setKeyType("org.apache.ignite.cache.store.jdbc.model.OrganizationKey" + (noKeyClasses ? "1" : ""));
+ storeTypes[0].setKeyFields(new JdbcTypeField(Types.INTEGER, "ID", Integer.class, "id"));
+ }
+
+ storeTypes[0].setValueType("org.apache.ignite.cache.store.jdbc.model.Organization" + (noValClasses ? "1" : ""));
+ storeTypes[0].setValueFields(
+ new JdbcTypeField(Types.INTEGER, "ID", Integer.class, "id"),
+ new JdbcTypeField(Types.VARCHAR, "NAME", String.class, "name"),
+ new JdbcTypeField(Types.VARCHAR, "CITY", String.class, "city"));
+
+ storeTypes[1] = new JdbcType();
+ storeTypes[1].setDatabaseSchema("PUBLIC");
+ storeTypes[1].setDatabaseTable("PERSON");
+
+ if (builtinKeys) {
+ storeTypes[1].setKeyType("java.lang.Long");
+ storeTypes[1].setKeyFields(new JdbcTypeField(Types.INTEGER, "ID", Long.class, "id"));
+ }
+ else {
+ storeTypes[1].setKeyType("org.apache.ignite.cache.store.jdbc.model.PersonKey" + (noKeyClasses ? "1" : ""));
+ storeTypes[1].setKeyFields(new JdbcTypeField(Types.INTEGER, "ID", Integer.class, "id"));
+ }
+
+ storeTypes[1].setValueType("org.apache.ignite.cache.store.jdbc.model.Person" + (noValClasses ? "1" : ""));
+ storeTypes[1].setValueFields(
+ new JdbcTypeField(Types.INTEGER, "ID", Integer.class, "id"),
+ new JdbcTypeField(Types.INTEGER, "ORG_ID", Integer.class, "orgId"),
+ new JdbcTypeField(Types.VARCHAR, "NAME", String.class, "name"));
+
+ return storeTypes;
+ }
+
+ /**
+ * @return Cache configuration for test.
+ * @throws Exception In case when failed to create cache configuration.
+ */
+ protected CacheConfiguration cacheConfiguration() throws Exception {
+ CacheConfiguration cc = defaultCacheConfiguration();
+
+ cc.setCacheMode(PARTITIONED);
+ cc.setAtomicityMode(transactional ? TRANSACTIONAL : ATOMIC);
+ cc.setSwapEnabled(false);
+ cc.setWriteBehindEnabled(false);
+
+ CacheJdbcPojoStoreFactory<Object, Object> storeFactory = new CacheJdbcPojoStoreFactory<>();
+ storeFactory.setDialect(new H2Dialect());
+ storeFactory.setTypes(storeTypes());
+ storeFactory.setDataSource(JdbcConnectionPool.create(DFLT_CONN_URL, "sa", "")); // H2 DataSource
+
+ cc.setCacheStoreFactory(storeFactory);
+ cc.setReadThrough(true);
+ cc.setWriteThrough(true);
+ cc.setLoadPreviousValue(true);
+
+ return cc;
+ }
+
+ /**
+ * Fill in-memory database with sample data.
+ *
+ * @param conn Connection to database.
+ * @throws SQLException In case of filling database with sample data failed.
+ */
+ protected void fillSampleDatabase(Connection conn) throws SQLException {
+ info("Start to fill sample database...");
+
+ PreparedStatement orgStmt = conn.prepareStatement("INSERT INTO Organization(id, name, city) VALUES (?, ?, ?)");
+
+ for (int i = 0; i < ORGANIZATION_CNT; i++) {
+ orgStmt.setInt(1, i);
+ orgStmt.setString(2, "name" + i);
+ orgStmt.setString(3, "city" + i % 10);
+
+ orgStmt.addBatch();
+ }
+
+ orgStmt.executeBatch();
+
+ U.closeQuiet(orgStmt);
+
+ conn.commit();
+
+ PreparedStatement prnStmt = conn.prepareStatement("INSERT INTO Person(id, org_id, name) VALUES (?, ?, ?)");
+
+ for (int i = 0; i < PERSON_CNT; i++) {
+ prnStmt.setInt(1, i);
+ prnStmt.setInt(2, i % 100);
+ prnStmt.setString(3, "name" + i);
+
+ prnStmt.addBatch();
+ }
+
+ prnStmt.executeBatch();
+
+ conn.commit();
+
+ U.closeQuiet(prnStmt);
+
+ info("Sample database prepared.");
+ }
+
+ /**
+ * Start test grid with specified options.
+ *
+ * @param builtin {@code True} if keys are built in java types.
+ * @param noKeyCls {@code True} if keys classes are not on class path.
+ * @param noValCls {@code True} if values classes are not on class path.
+ * @param trn {@code True} if cache should be started in transactional mode.
+ * @throws Exception
+ */
+ protected void startTestGrid(boolean builtin, boolean noKeyCls, boolean noValCls, boolean trn) throws Exception {
+ builtinKeys = builtin;
+ noKeyClasses = noKeyCls;
+ noValClasses = noValCls;
+ transactional = trn;
+
+ startGrid();
+ }
+
+ /**
+ * Check that data was loaded correctly.
+ */
+ protected void checkCacheContent() {
+ IgniteCache<Object, Object> c1 = grid().cache(null);
+
+ c1.loadCache(null);
+
+ assertEquals(ORGANIZATION_CNT + PERSON_CNT, c1.size());
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testLoadCache() throws Exception {
+ startTestGrid(false, false, false, false);
+
+ checkCacheContent();
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testLoadCacheTx() throws Exception {
+ startTestGrid(false, false, false, true);
+
+ checkCacheContent();
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testLoadCachePrimitiveKeys() throws Exception {
+ startTestGrid(true, false, false, false);
+
+ checkCacheContent();
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testLoadCachePrimitiveKeysTx() throws Exception {
+ startTestGrid(true, false, false, true);
+
+ checkCacheContent();
+ }
+
+ /**
+ * Check put in cache and store it in db.
+ *
+ * @throws Exception If failed.
+ */
+ private void checkPut() throws Exception {
+ IgniteCache<PersonKey, Person> c1 = grid().cache(null);
+
+ Connection conn = getConnection();
+ try {
+ PreparedStatement stmt = conn.prepareStatement("SELECT ID, ORG_ID, NAME FROM PERSON WHERE ID = ?");
+
+ stmt.setInt(1, -1);
+
+ ResultSet rs = stmt.executeQuery();
+
+ assertFalse("Unexpected non empty result set", rs.next());
+
+ U.closeQuiet(rs);
+
+ // Test put-insert.
+ PersonKey key = new PersonKey(-1);
+
+ c1.put(key, new Person(-1, -2, "Person-to-test-put-insert", 999));
+
+ rs = stmt.executeQuery();
+
+ assertTrue("Unexpected empty result set", rs.next());
+
+ assertEquals(-1, rs.getInt(1));
+ assertEquals(-2, rs.getInt(2));
+ assertEquals("Person-to-test-put-insert", rs.getString(3));
+
+ assertFalse("Unexpected more data in result set", rs.next());
+
+ U.closeQuiet(rs);
+
+ // Test put-update.
+ c1.put(key, new Person(-1, -3, "Person-to-test-put-update", 999));
+
+ rs = stmt.executeQuery();
+
+ assertTrue("Unexpected empty result set", rs.next());
+
+ assertEquals(-1, rs.getInt(1));
+ assertEquals(-3, rs.getInt(2));
+ assertEquals("Person-to-test-put-update", rs.getString(3));
+
+ assertFalse("Unexpected more data in result set", rs.next());
+
+ U.closeQuiet(rs);
+ }
+ finally {
+ U.closeQuiet(conn);
+ }
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testPut() throws Exception {
+ startTestGrid(false, false, false, false);
+
+ checkPut();
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testPutTx() throws Exception {
+ startTestGrid(false, false, false, true);
+
+ checkPut();
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreOptimizedMarshallerSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreOptimizedMarshallerSelfTest.java b/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreOptimizedMarshallerSelfTest.java
new file mode 100644
index 0000000..f40f7d7
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreOptimizedMarshallerSelfTest.java
@@ -0,0 +1,31 @@
+/*
+ * 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.jdbc;
+
+import org.apache.ignite.marshaller.Marshaller;
+import org.apache.ignite.marshaller.optimized.OptimizedMarshaller;
+
+/**
+ * Class for {@code PojoCacheStore} tests.
+ */
+public class CacheJdbcPojoStoreOptimizedMarshallerSelfTest extends CacheJdbcPojoStoreAbstractSelfTest {
+ /** {@inheritDoc} */
+ @Override protected Marshaller marshaller(){
+ return new OptimizedMarshaller();
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStorePortableMarshallerSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStorePortableMarshallerSelfTest.java b/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStorePortableMarshallerSelfTest.java
new file mode 100644
index 0000000..39504b1
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStorePortableMarshallerSelfTest.java
@@ -0,0 +1,85 @@
+/*
+ * 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.jdbc;
+
+import org.apache.ignite.marshaller.Marshaller;
+import org.apache.ignite.marshaller.portable.BinaryMarshaller;
+
+/**
+ * Class for {@code PojoCacheStore} tests.
+ */
+public class CacheJdbcPojoStorePortableMarshallerSelfTest extends CacheJdbcPojoStoreAbstractSelfTest {
+ /** {@inheritDoc} */
+ @Override protected Marshaller marshaller(){
+ return new BinaryMarshaller();
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testLoadCacheNoKeyClasses() throws Exception {
+ startTestGrid(false, true, false, false);
+
+ checkCacheContent();
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testLoadCacheNoKeyClassesTx() throws Exception {
+ startTestGrid(false, true, false, true);
+
+ checkCacheContent();
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testLoadCacheNoValueClasses() throws Exception {
+ startTestGrid(false, false, true, false);
+
+ checkCacheContent();
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testLoadCacheNoValueClassesTx() throws Exception {
+ startTestGrid(false, false, true, true);
+
+ checkCacheContent();
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testLoadCacheNoKeyAndValueClasses() throws Exception {
+ startTestGrid(false, true, true, false);
+
+ checkCacheContent();
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testLoadCacheNoKeyAndValueClassesTx() throws Exception {
+ startTestGrid(false, true, true, true);
+
+ checkCacheContent();
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreTest.java b/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreTest.java
index 0ad2cad..d8f75d3 100644
--- a/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreTest.java
@@ -17,23 +17,19 @@
package org.apache.ignite.cache.store.jdbc;
-import java.net.MalformedURLException;
-import java.net.URL;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
+import java.sql.Types;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.UUID;
import java.util.concurrent.ConcurrentLinkedQueue;
import javax.cache.integration.CacheWriterException;
-import org.apache.ignite.IgniteException;
-import org.apache.ignite.cache.CacheTypeMetadata;
-import org.apache.ignite.cache.store.jdbc.dialect.BasicJdbcDialect;
-import org.apache.ignite.cache.store.jdbc.dialect.JdbcDialect;
+
+import org.apache.ignite.cache.store.jdbc.dialect.H2Dialect;
import org.apache.ignite.cache.store.jdbc.model.Organization;
import org.apache.ignite.cache.store.jdbc.model.OrganizationKey;
import org.apache.ignite.cache.store.jdbc.model.Person;
@@ -41,16 +37,11 @@ import org.apache.ignite.cache.store.jdbc.model.PersonComplexKey;
import org.apache.ignite.cache.store.jdbc.model.PersonKey;
import org.apache.ignite.internal.processors.cache.CacheEntryImpl;
import org.apache.ignite.internal.util.typedef.CI2;
-import org.apache.ignite.internal.util.typedef.X;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.lang.IgniteBiInClosure;
import org.apache.ignite.testframework.GridTestUtils;
import org.apache.ignite.testframework.junits.cache.GridAbstractCacheStoreSelfTest;
import org.h2.jdbcx.JdbcConnectionPool;
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
-import org.springframework.context.support.GenericApplicationContext;
-import org.springframework.core.io.UrlResource;
/**
* Class for {@code PojoCacheStore} tests.
@@ -59,9 +50,6 @@ public class CacheJdbcPojoStoreTest extends GridAbstractCacheStoreSelfTest<Cache
/** DB connection URL. */
private static final String DFLT_CONN_URL = "jdbc:h2:mem:autoCacheStore;DB_CLOSE_DELAY=-1";
- /** Default config with mapping. */
- private static final String DFLT_MAPPING_CONFIG = "modules/core/src/test/config/store/jdbc/ignite-type-metadata.xml";
-
/** Organization count. */
protected static final int ORGANIZATION_CNT = 1000;
@@ -77,71 +65,86 @@ public class CacheJdbcPojoStoreTest extends GridAbstractCacheStoreSelfTest<Cache
/** {@inheritDoc} */
@Override protected CacheJdbcPojoStore<Object, Object> store() {
- CacheJdbcPojoStore<Object, Object> store = new CacheJdbcPojoStore<>();
-
-// PGPoolingDataSource ds = new PGPoolingDataSource();
-// ds.setUser("postgres");
-// ds.setPassword("postgres");
-// ds.setServerName("ip");
-// ds.setDatabaseName("postgres");
-// store.setDataSource(ds);
-
-// MysqlDataSource ds = new MysqlDataSource();
-// ds.setURL("jdbc:mysql://ip:port/dbname");
-// ds.setUser("mysql");
-// ds.setPassword("mysql");
-
+ CacheJdbcPojoStoreFactory<Object, Object> storeFactory = new CacheJdbcPojoStoreFactory<>();
+
+ JdbcType[] storeTypes = new JdbcType[6];
+
+ storeTypes[0] = new JdbcType();
+ storeTypes[0].setDatabaseSchema("PUBLIC");
+ storeTypes[0].setDatabaseTable("ORGANIZATION");
+ storeTypes[0].setKeyType("org.apache.ignite.cache.store.jdbc.model.OrganizationKey");
+ storeTypes[0].setKeyFields(new JdbcTypeField(Types.INTEGER, "ID", Integer.class, "id"));
+
+ storeTypes[0].setValueType("org.apache.ignite.cache.store.jdbc.model.Organization");
+ storeTypes[0].setValueFields(
+ new JdbcTypeField(Types.INTEGER, "ID", Integer.class, "id"),
+ new JdbcTypeField(Types.VARCHAR, "NAME", String.class, "name"),
+ new JdbcTypeField(Types.VARCHAR, "CITY", String.class, "city"));
+
+ storeTypes[1] = new JdbcType();
+ storeTypes[1].setDatabaseSchema("PUBLIC");
+ storeTypes[1].setDatabaseTable("PERSON");
+ storeTypes[1].setKeyType("org.apache.ignite.cache.store.jdbc.model.PersonKey");
+ storeTypes[1].setKeyFields(new JdbcTypeField(Types.INTEGER, "ID", Integer.class, "id"));
+
+ storeTypes[1].setValueType("org.apache.ignite.cache.store.jdbc.model.Person");
+ storeTypes[1].setValueFields(
+ new JdbcTypeField(Types.INTEGER, "ID", Integer.class, "id"),
+ new JdbcTypeField(Types.INTEGER, "ORG_ID", Integer.class, "orgId"),
+ new JdbcTypeField(Types.VARCHAR, "NAME", String.class, "name"));
+
+ storeTypes[2] = new JdbcType();
+ storeTypes[2].setDatabaseSchema("PUBLIC");
+ storeTypes[2].setDatabaseTable("PERSON_COMPLEX");
+ storeTypes[2].setKeyType("org.apache.ignite.cache.store.jdbc.model.PersonComplexKey");
+ storeTypes[2].setKeyFields(
+ new JdbcTypeField(Types.INTEGER, "ID", int.class, "id"),
+ new JdbcTypeField(Types.INTEGER, "ORG_ID", int.class, "orgId"),
+ new JdbcTypeField(Types.INTEGER, "CITY_ID", int.class, "cityId"));
+
+ storeTypes[2].setValueType("org.apache.ignite.cache.store.jdbc.model.Person");
+ storeTypes[2].setValueFields(
+ new JdbcTypeField(Types.INTEGER, "ID", Integer.class, "id"),
+ new JdbcTypeField(Types.INTEGER, "ORG_ID", Integer.class, "orgId"),
+ new JdbcTypeField(Types.VARCHAR, "NAME", String.class, "name"),
+ new JdbcTypeField(Types.INTEGER, "SALARY", Integer.class, "salary"));
+
+ storeTypes[3] = new JdbcType();
+ storeTypes[3].setDatabaseSchema("PUBLIC");
+ storeTypes[3].setDatabaseTable("TIMESTAMP_ENTRIES");
+ storeTypes[3].setKeyType("java.sql.Timestamp");
+ storeTypes[3].setKeyFields(new JdbcTypeField(Types.TIMESTAMP, "KEY", Timestamp.class, null));
+
+ storeTypes[3].setValueType("java.lang.Integer");
+ storeTypes[3].setValueFields(new JdbcTypeField(Types.INTEGER, "VAL", Integer.class, null));
+
+ storeTypes[4] = new JdbcType();
+ storeTypes[4].setDatabaseSchema("PUBLIC");
+ storeTypes[4].setDatabaseTable("STRING_ENTRIES");
+ storeTypes[4].setKeyType("java.lang.String");
+ storeTypes[4].setKeyFields(new JdbcTypeField(Types.VARCHAR, "KEY", String.class, null));
+
+ storeTypes[4].setValueType("java.lang.String");
+ storeTypes[4].setValueFields(new JdbcTypeField(Types.VARCHAR, "VAL", Integer.class, null));
+
+ storeTypes[5] = new JdbcType();
+ storeTypes[5].setDatabaseSchema("PUBLIC");
+ storeTypes[5].setDatabaseTable("UUID_ENTRIES");
+ storeTypes[5].setKeyType("java.util.UUID");
+ storeTypes[5].setKeyFields(new JdbcTypeField(Types.BINARY, "KEY", UUID.class, null));
+
+ storeTypes[5].setValueType("java.util.UUID");
+ storeTypes[5].setValueFields(new JdbcTypeField(Types.BINARY, "VAL", UUID.class, null));
+
+ storeFactory.setTypes(storeTypes);
+
+ storeFactory.setDialect(new H2Dialect());
+
+ CacheJdbcPojoStore<Object, Object> store = storeFactory.create();
+
+ // H2 DataSource
store.setDataSource(JdbcConnectionPool.create(DFLT_CONN_URL, "sa", ""));
- URL cfgUrl;
-
- try {
- cfgUrl = new URL(DFLT_MAPPING_CONFIG);
- }
- catch (MalformedURLException ignore) {
- cfgUrl = U.resolveIgniteUrl(DFLT_MAPPING_CONFIG);
- }
-
- if (cfgUrl == null)
- throw new IgniteException("Failed to resolve metadata path: " + DFLT_MAPPING_CONFIG);
-
- try {
- GenericApplicationContext springCtx = new GenericApplicationContext();
-
- new XmlBeanDefinitionReader(springCtx).loadBeanDefinitions(new UrlResource(cfgUrl));
-
- springCtx.refresh();
-
- Collection<CacheTypeMetadata> typeMeta = springCtx.getBeansOfType(CacheTypeMetadata.class).values();
-
- Map<Integer, Map<Object, CacheAbstractJdbcStore.EntryMapping>> cacheMappings = new HashMap<>();
-
- JdbcDialect dialect = store.resolveDialect();
-
- GridTestUtils.setFieldValue(store, CacheAbstractJdbcStore.class, "dialect", dialect);
-
- Map<Object, CacheAbstractJdbcStore.EntryMapping> entryMappings = U.newHashMap(typeMeta.size());
-
- for (CacheTypeMetadata type : typeMeta)
- entryMappings.put(store.keyTypeId(type.getKeyType()),
- new CacheAbstractJdbcStore.EntryMapping(null, dialect, type));
-
- store.prepareBuilders(null, typeMeta);
-
- cacheMappings.put(null, entryMappings);
-
- GridTestUtils.setFieldValue(store, CacheAbstractJdbcStore.class, "cacheMappings", cacheMappings);
- }
- catch (BeansException e) {
- if (X.hasCause(e, ClassNotFoundException.class))
- throw new IgniteException("Failed to instantiate Spring XML application context " +
- "(make sure all classes used in Spring configuration are present at CLASSPATH) " +
- "[springUrl=" + cfgUrl + ']', e);
- else
- throw new IgniteException("Failed to instantiate Spring XML application context [springUrl=" +
- cfgUrl + ", err=" + e.getMessage() + ']', e);
- }
-
return store;
}
@@ -224,7 +227,6 @@ public class CacheJdbcPojoStoreTest extends GridAbstractCacheStoreSelfTest<Cache
super.beforeTest();
}
-
/**
* @throws Exception If failed.
*/
@@ -274,7 +276,7 @@ public class CacheJdbcPojoStoreTest extends GridAbstractCacheStoreSelfTest<Cache
if (i > 0)
prnComplexStmt.setInt(5, 1000 + i * 500);
else // Add person with null salary
- prnComplexStmt.setNull(5, java.sql.Types.INTEGER);
+ prnComplexStmt.setNull(5, Types.INTEGER);
prnComplexStmt.addBatch();
}
@@ -302,9 +304,9 @@ public class CacheJdbcPojoStoreTest extends GridAbstractCacheStoreSelfTest<Cache
Person val = (Person)v;
- assert key.getId() == val.getId();
- assert key.getOrgId() == val.getOrgId();
- assertEquals("name" + key.getId(), val.getName());
+ assertTrue("Key ID should be the same as value ID", key.getId() == val.getId());
+ assertTrue("Key orgID should be the same as value orgID", key.getOrgId() == val.getOrgId());
+ assertEquals("name" + key.getId(), val.getName());
prnComplexKeys.add((PersonComplexKey)k);
}
@@ -351,25 +353,23 @@ public class CacheJdbcPojoStoreTest extends GridAbstractCacheStoreSelfTest<Cache
* @throws Exception If failed.
*/
public void testWriteRetry() throws Exception {
+ CacheJdbcPojoStore<Object, Object> store = store();
+
// Special dialect that will skip updates, to test write retry.
- BasicJdbcDialect dialect = new BasicJdbcDialect() {
+ store.setDialect(new H2Dialect() {
/** {@inheritDoc} */
- @Override public String updateQuery(String tblName, Collection<String> keyCols, Iterable<String> valCols) {
- return super.updateQuery(tblName, keyCols, valCols) + " AND 1 = 0";
+ @Override public boolean hasMerge() {
+ return false;
}
- };
-
- store.setDialect(dialect);
-
- Map<String, Map<Object, CacheAbstractJdbcStore.EntryMapping>> cacheMappings =
- GridTestUtils.getFieldValue(store, CacheAbstractJdbcStore.class, "cacheMappings");
-
- CacheAbstractJdbcStore.EntryMapping em = cacheMappings.get(null).get(OrganizationKey.class);
- CacheTypeMetadata typeMeta = GridTestUtils.getFieldValue(em, CacheAbstractJdbcStore.EntryMapping.class, "typeMeta");
+ /** {@inheritDoc} */
+ @Override public String updateQuery(String tblName, Collection<String> keyCols,
+ Iterable<String> valCols) {
+ return super.updateQuery(tblName, keyCols, valCols) + " AND 1 = 0";
+ }
+ });
- cacheMappings.get(null).put(OrganizationKey.class,
- new CacheAbstractJdbcStore.EntryMapping(null, dialect, typeMeta));
+ inject(store);
Connection conn = store.openConnection(false);
@@ -392,6 +392,8 @@ public class CacheJdbcPojoStoreTest extends GridAbstractCacheStoreSelfTest<Cache
try {
store.write(new CacheEntryImpl<>(k1, v1));
+
+ fail("CacheWriterException wasn't thrown.");
}
catch (CacheWriterException e) {
if (!e.getMessage().startsWith("Failed insert entry in database, violate a unique index or primary key") ||
@@ -418,4 +420,4 @@ public class CacheJdbcPojoStoreTest extends GridAbstractCacheStoreSelfTest<Cache
assertNull(store.load(k));
}
-}
\ No newline at end of file
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcStoreAbstractMultithreadedSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcStoreAbstractMultithreadedSelfTest.java b/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcStoreAbstractMultithreadedSelfTest.java
index 757cedd..4c4bd58 100644
--- a/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcStoreAbstractMultithreadedSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcStoreAbstractMultithreadedSelfTest.java
@@ -308,4 +308,4 @@ public abstract class CacheJdbcStoreAbstractMultithreadedSelfTest<T extends Cach
}
}, 8, "tx");
}
-}
\ No newline at end of file
+}