Return-Path: X-Original-To: apmail-ignite-commits-archive@minotaur.apache.org Delivered-To: apmail-ignite-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 2EC2A1889D for ; Wed, 1 Jul 2015 19:54:11 +0000 (UTC) Received: (qmail 11476 invoked by uid 500); 1 Jul 2015 19:54:11 -0000 Delivered-To: apmail-ignite-commits-archive@ignite.apache.org Received: (qmail 11446 invoked by uid 500); 1 Jul 2015 19:54:11 -0000 Mailing-List: contact commits-help@ignite.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@ignite.incubator.apache.org Delivered-To: mailing list commits@ignite.incubator.apache.org Received: (qmail 11437 invoked by uid 99); 1 Jul 2015 19:54:11 -0000 Received: from Unknown (HELO spamd1-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 01 Jul 2015 19:54:11 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd1-us-west.apache.org (ASF Mail Server at spamd1-us-west.apache.org) with ESMTP id 9BEF9D17E0 for ; Wed, 1 Jul 2015 19:54:10 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd1-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: 1.23 X-Spam-Level: * X-Spam-Status: No, score=1.23 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, KAM_LAZY_DOMAIN_SECURITY=1, RP_MATCHES_RCVD=-0.571, URIBL_BLOCKED=0.001] autolearn=disabled Received: from mx1-us-east.apache.org ([10.40.0.8]) by localhost (spamd1-us-west.apache.org [10.40.0.7]) (amavisd-new, port 10024) with ESMTP id XvNkiDKMqUq9 for ; Wed, 1 Jul 2015 19:54:00 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx1-us-east.apache.org (ASF Mail Server at mx1-us-east.apache.org) with SMTP id 5975F4545A for ; Wed, 1 Jul 2015 19:53:59 +0000 (UTC) Received: (qmail 2458 invoked by uid 99); 1 Jul 2015 19:52:43 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 01 Jul 2015 19:52:43 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 85C2DE03CF; Wed, 1 Jul 2015 19:52:43 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: sergi@apache.org To: commits@ignite.incubator.apache.org Date: Wed, 01 Jul 2015 19:52:43 -0000 Message-Id: X-Mailer: ASF-Git Admin Mailer Subject: [1/4] incubator-ignite git commit: ignite-959-x - wip Repository: incubator-ignite Updated Branches: refs/heads/ignite-959-x [created] 7df4f8cb0 ignite-959-x - wip Project: http://git-wip-us.apache.org/repos/asf/incubator-ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ignite/commit/781f0d5f Tree: http://git-wip-us.apache.org/repos/asf/incubator-ignite/tree/781f0d5f Diff: http://git-wip-us.apache.org/repos/asf/incubator-ignite/diff/781f0d5f Branch: refs/heads/ignite-959-x Commit: 781f0d5ff32ea034d67260469a595cdb64048655 Parents: 285d790 Author: S.Vladykin Authored: Thu Jun 25 12:46:25 2015 +0300 Committer: S.Vladykin Committed: Thu Jun 25 12:46:25 2015 +0300 ---------------------------------------------------------------------- .../configuration/CacheConfiguration.java | 602 ++++++++++++++++++- .../processors/query/GridQueryProcessor.java | 44 ++ .../processors/query/h2/IgniteH2Indexing.java | 2 - 3 files changed, 632 insertions(+), 16 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/781f0d5f/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java b/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java index 7af4974..50ba040 100644 --- a/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java +++ b/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java @@ -25,6 +25,9 @@ import org.apache.ignite.cache.eviction.*; import org.apache.ignite.cache.query.annotations.*; import org.apache.ignite.cache.store.*; import org.apache.ignite.cluster.*; +import org.apache.ignite.internal.processors.query.*; +import org.apache.ignite.internal.util.tostring.*; +import org.apache.ignite.internal.util.typedef.*; import org.apache.ignite.internal.util.typedef.internal.*; import org.apache.ignite.lang.*; import org.apache.ignite.plugin.*; @@ -33,8 +36,11 @@ import org.jetbrains.annotations.*; import javax.cache.*; import javax.cache.configuration.*; import javax.cache.expiry.*; +import java.lang.reflect.*; import java.util.*; +import static org.apache.ignite.internal.processors.query.GridQueryIndexType.*; + /** * This class defines grid cache configuration. This configuration is passed to * grid via {@link IgniteConfiguration#getCacheConfiguration()} method. It defines all configuration @@ -298,7 +304,7 @@ public class CacheConfiguration extends MutableConfiguration { private boolean sqlEscapeAll; /** */ - private Class[] indexedTypes; + private transient Class[] indexedTypes; /** */ private int sqlOnheapRowCacheSize = DFLT_SQL_ONHEAP_ROW_CACHE_SIZE; @@ -1506,7 +1512,12 @@ public class CacheConfiguration extends MutableConfiguration { * @return {@code this} for chaining. */ public CacheConfiguration setTypeMetadata(Collection typeMeta) { - this.typeMeta = typeMeta; + if (this.typeMeta == null) + this.typeMeta = new ArrayList<>(typeMeta); + else if (indexedTypes != null) + this.typeMeta.addAll(typeMeta); + else + throw new CacheException("Type metadata can be set only once."); return this; } @@ -1661,21 +1672,31 @@ public class CacheConfiguration extends MutableConfiguration { * @return {@code this} for chaining. */ public CacheConfiguration setIndexedTypes(Class... indexedTypes) { - A.ensure(indexedTypes == null || (indexedTypes.length & 1) == 0, + int len = indexedTypes.length; + + A.ensure(len > 0, "Array of indexed types can not be empty."); + A.ensure((len & 1) == 0, "Number of indexed types is expected to be even. Refer to method javadoc for details."); - if (indexedTypes != null) { - int len = indexedTypes.length; + if (this.indexedTypes != null) + throw new CacheException("Indexed types can be set only once."); + + Class[] newIndexedTypes = new Class[len]; - Class[] newIndexedTypes = new Class[len]; + for (int i = 0; i < len; i++) + newIndexedTypes[i] = U.box(indexedTypes[i]); - for (int i = 0; i < len; i++) - newIndexedTypes[i] = U.box(indexedTypes[i]); + if (typeMeta == null) + typeMeta = new ArrayList<>(); - this.indexedTypes = newIndexedTypes; + for (int i = 0; i < len; i += 2) { + Class keyCls = newIndexedTypes[i]; + Class valCls = newIndexedTypes[i + 1]; + + TypeDescriptor desc = processKeyAndValueClasses(keyCls, valCls); + + typeMeta.add(convert(desc)); } - else - this.indexedTypes = null; return this; } @@ -1773,6 +1794,165 @@ public class CacheConfiguration extends MutableConfiguration { return this; } + /** + * @param desc Type descriptor. + * @return Type metadata. + */ + private CacheTypeMetadata convert(TypeDescriptor desc) { + CacheTypeMetadata meta = new CacheTypeMetadata(); + + // TODO + + return meta; + } + + /** + * @param keyCls Key class. + * @param valCls Value class. + * @return Type descriptor. + */ + private static TypeDescriptor processKeyAndValueClasses( + Class keyCls, + Class valCls + ) { + TypeDescriptor d = new TypeDescriptor(); + + d.keyClass(keyCls); + d.valueClass(valCls); + + processAnnotationsInClass(true, d.keyCls, d, null); + + String valTypeName = GridQueryProcessor.typeName(valCls); + + d.name(valTypeName); + + processAnnotationsInClass(false, d.valCls, d, null); + + return d; + } + + /** + * Process annotations for class. + * + * @param key If given class relates to key. + * @param cls Class. + * @param type Type descriptor. + * @param parent Parent in case of embeddable. + */ + private static void processAnnotationsInClass(boolean key, Class cls, TypeDescriptor type, + @Nullable ClassProperty parent) { + if (U.isJdk(cls) || GridQueryProcessor.isGeometryClass(cls)) { + if (parent == null && !key && GridQueryProcessor.isSqlType(cls) ) { // We have to index primitive _val. + String idxName = "_val_idx"; + + type.addIndex(idxName, GridQueryProcessor.isGeometryClass(cls) ? GEO_SPATIAL : SORTED); + + type.addFieldToIndex(idxName, "_VAL", 0, false); + } + + return; + } + + if (parent != null && parent.knowsClass(cls)) + throw new CacheException("Recursive reference found in type: " + cls.getName()); + + if (parent == null) { // Check class annotation at top level only. + QueryTextField txtAnnCls = cls.getAnnotation(QueryTextField.class); + + if (txtAnnCls != null) + type.valueTextIndex(true); + + QueryGroupIndex grpIdx = cls.getAnnotation(QueryGroupIndex.class); + + if (grpIdx != null) + type.addIndex(grpIdx.name(), SORTED); + + QueryGroupIndex.List grpIdxList = cls.getAnnotation(QueryGroupIndex.List.class); + + if (grpIdxList != null && !F.isEmpty(grpIdxList.value())) { + for (QueryGroupIndex idx : grpIdxList.value()) + type.addIndex(idx.name(), SORTED); + } + } + + for (Class c = cls; c != null && !c.equals(Object.class); c = c.getSuperclass()) { + for (Field field : c.getDeclaredFields()) { + QuerySqlField sqlAnn = field.getAnnotation(QuerySqlField.class); + QueryTextField txtAnn = field.getAnnotation(QueryTextField.class); + + if (sqlAnn != null || txtAnn != null) { + ClassProperty prop = new ClassProperty(field, key); + + prop.parent(parent); + + processAnnotation(key, sqlAnn, txtAnn, field.getType(), prop, type); + + type.addProperty(prop, true); + } + } + + for (Method mtd : c.getDeclaredMethods()) { + QuerySqlField sqlAnn = mtd.getAnnotation(QuerySqlField.class); + QueryTextField txtAnn = mtd.getAnnotation(QueryTextField.class); + + if (sqlAnn != null || txtAnn != null) { + if (mtd.getParameterTypes().length != 0) + throw new CacheException("Getter with QuerySqlField " + + "annotation cannot have parameters: " + mtd); + + ClassProperty prop = new ClassProperty(mtd, key); + + prop.parent(parent); + + processAnnotation(key, sqlAnn, txtAnn, mtd.getReturnType(), prop, type); + + type.addProperty(prop, true); + } + } + } + } + + /** + * Processes annotation at field or method. + * + * @param key If given class relates to key. + * @param sqlAnn SQL annotation, can be {@code null}. + * @param txtAnn H2 text annotation, can be {@code null}. + * @param cls Class of field or return type for method. + * @param prop Current property. + * @param desc Class description. + */ + private static void processAnnotation(boolean key, QuerySqlField sqlAnn, QueryTextField txtAnn, + Class cls, ClassProperty prop, TypeDescriptor desc) { + if (sqlAnn != null) { + processAnnotationsInClass(key, cls, desc, prop); + + if (!sqlAnn.name().isEmpty()) + prop.name(sqlAnn.name()); + + if (sqlAnn.index()) { + String idxName = prop.name() + "_idx"; + + desc.addIndex(idxName, GridQueryProcessor.isGeometryClass(prop.type()) ? GEO_SPATIAL : SORTED); + + desc.addFieldToIndex(idxName, prop.name(), 0, sqlAnn.descending()); + } + + if (!F.isEmpty(sqlAnn.groups())) { + for (String group : sqlAnn.groups()) + desc.addFieldToIndex(group, prop.name(), 0, false); + } + + if (!F.isEmpty(sqlAnn.orderedGroups())) { + for (QuerySqlField.Group idx : sqlAnn.orderedGroups()) + desc.addFieldToIndex(idx.name(), prop.name(), idx.order(), idx.descending()); + } + } + + if (txtAnn != null) + desc.addFieldToTextIndex(prop.name()); + } + /** {@inheritDoc} */ @Override public String toString() { return S.toString(CacheConfiguration.class, this); @@ -1792,10 +1972,404 @@ public class CacheConfiguration extends MutableConfiguration { /** {@inheritDoc} */ @Override public boolean equals(Object obj) { - if (obj == null) - return false; + return obj != null && obj.getClass().equals(this.getClass()); + } + } + + /** + * Descriptor of type. + */ + private static class TypeDescriptor implements GridQueryTypeDescriptor { + /** */ + private String name; + + /** Value field names and types with preserved order. */ + @GridToStringInclude + private final Map> fields = new LinkedHashMap<>(); + + /** */ + @GridToStringExclude + private final Map props = new HashMap<>(); + + /** */ + @GridToStringInclude + private final Map indexes = new HashMap<>(); + + /** */ + private IndexDescriptor fullTextIdx; + + /** */ + private Class keyCls; + + /** */ + private Class valCls; + + /** */ + private boolean valTextIdx; + + /** SPI can decide not to register this type. */ + private boolean registered; + + /** + * @return {@code True} if type registration in SPI was finished and type was not rejected. + */ + boolean registered() { + return registered; + } + + /** + * @param registered Sets registered flag. + */ + void registered(boolean registered) { + this.registered = registered; + } + + /** {@inheritDoc} */ + @Override public String name() { + return name; + } + + /** + * Sets type name. + * + * @param name Name. + */ + void name(String name) { + this.name = name; + } + + /** {@inheritDoc} */ + @Override public Map> fields() { + return fields; + } + + /** {@inheritDoc} */ + @SuppressWarnings("unchecked") + @Override public T value(String field, Object key, Object val) throws IgniteCheckedException { + assert field != null; + + Property prop = props.get(field); + + if (prop == null) + throw new IgniteCheckedException("Failed to find field '" + field + "' in type '" + name + "'."); + + return (T)prop.value(key, val); + } + + /** {@inheritDoc} */ + @Override public Map indexes() { + return Collections.unmodifiableMap(indexes); + } + + /** + * Adds index. + * + * @param idxName Index name. + * @param type Index type. + * @return Index descriptor. + */ + public IndexDescriptor addIndex(String idxName, GridQueryIndexType type) { + IndexDescriptor idx = new IndexDescriptor(type); + + if (indexes.put(idxName, idx) != null) + throw new CacheException("Index with name '" + idxName + "' already exists."); + + return idx; + } - return obj.getClass().equals(this.getClass()); + /** + * Adds field to index. + * + * @param idxName Index name. + * @param field Field name. + * @param orderNum Fields order number in index. + * @param descending Sorting order. + */ + public void addFieldToIndex(String idxName, String field, int orderNum, + boolean descending) { + IndexDescriptor desc = indexes.get(idxName); + + if (desc == null) + desc = addIndex(idxName, SORTED); + + desc.addField(field, orderNum, descending); + } + + /** + * Adds field to text index. + * + * @param field Field name. + */ + public void addFieldToTextIndex(String field) { + if (fullTextIdx == null) { + fullTextIdx = new IndexDescriptor(FULLTEXT); + + indexes.put(null, fullTextIdx); + } + + fullTextIdx.addField(field, 0, false); + } + + /** {@inheritDoc} */ + @Override public Class valueClass() { + return valCls; + } + + /** + * Sets value class. + * + * @param valCls Value class. + */ + void valueClass(Class valCls) { + this.valCls = valCls; + } + + /** {@inheritDoc} */ + @Override public Class keyClass() { + return keyCls; + } + + /** + * Set key class. + * + * @param keyCls Key class. + */ + void keyClass(Class keyCls) { + this.keyCls = keyCls; + } + + /** + * Adds property to the type descriptor. + * + * @param prop Property. + * @param failOnDuplicate Fail on duplicate flag. + */ + public void addProperty(Property prop, boolean failOnDuplicate) { + String name = prop.name(); + + if (props.put(name, prop) != null && failOnDuplicate) + throw new CacheException("Property with name '" + name + "' already exists."); + + fields.put(name, prop.type()); + } + + /** {@inheritDoc} */ + @Override public boolean valueTextIndex() { + return valTextIdx; + } + + /** + * Sets if this value should be text indexed. + * + * @param valTextIdx Flag value. + */ + public void valueTextIndex(boolean valTextIdx) { + this.valTextIdx = valTextIdx; + } + + /** {@inheritDoc} */ + @Override public String toString() { + return S.toString(TypeDescriptor.class, this); + } + } + + /** + * Index descriptor. + */ + private static class IndexDescriptor implements GridQueryIndexDescriptor { + /** Fields sorted by order number. */ + private final Collection> fields = new TreeSet<>( + new Comparator>() { + @Override public int compare(T2 o1, T2 o2) { + if (o1.get2().equals(o2.get2())) // Order is equal, compare field names to avoid replace in Set. + return o1.get1().compareTo(o2.get1()); + + return o1.get2() < o2.get2() ? -1 : 1; + } + }); + + /** Fields which should be indexed in descending order. */ + private Collection descendings; + + /** */ + private final GridQueryIndexType type; + + /** + * @param type Type. + */ + private IndexDescriptor(GridQueryIndexType type) { + assert type != null; + + this.type = type; + } + + /** {@inheritDoc} */ + @Override public Collection fields() { + Collection res = new ArrayList<>(fields.size()); + + for (T2 t : fields) + res.add(t.get1()); + + return res; + } + + /** {@inheritDoc} */ + @Override public boolean descending(String field) { + return descendings != null && descendings.contains(field); + } + + /** + * Adds field to this index. + * + * @param field Field name. + * @param orderNum Field order number in this index. + * @param descending Sort order. + */ + public void addField(String field, int orderNum, boolean descending) { + fields.add(new T2<>(field, orderNum)); + + if (descending) { + if (descendings == null) + descendings = new HashSet<>(); + + descendings.add(field); + } + } + + /** {@inheritDoc} */ + @Override public GridQueryIndexType type() { + return type; + } + + /** {@inheritDoc} */ + @Override public String toString() { + return S.toString(IndexDescriptor.class, this); + } + } + + /** + * + */ + private abstract static class Property { + /** + * Gets this property value from the given object. + * + * @param key Key. + * @param val Value. + * @return Property value. + * @throws IgniteCheckedException If failed. + */ + public abstract Object value(Object key, Object val) throws IgniteCheckedException; + + /** + * @return Property name. + */ + public abstract String name(); + + /** + * @return Class member type. + */ + public abstract Class type(); + } + + /** + * Description of type property. + */ + private static class ClassProperty extends Property { + /** */ + private final Member member; + + /** */ + private ClassProperty parent; + + /** */ + private String name; + + /** */ + private boolean field; + + /** */ + private boolean key; + + /** + * Constructor. + * + * @param member Element. + */ + ClassProperty(Member member, boolean key) { + this.member = member; + this.key = key; + + name = member instanceof Method && member.getName().startsWith("get") && member.getName().length() > 3 ? + member.getName().substring(3) : member.getName(); + + ((AccessibleObject) member).setAccessible(true); + + field = member instanceof Field; + } + + /** {@inheritDoc} */ + @Override public Object value(Object key, Object val) throws IgniteCheckedException { + Object x = this.key ? key : val; + + if (parent != null) + x = parent.value(key, val); + + if (x == null) + return null; + + try { + if (field) { + Field field = (Field)member; + + return field.get(x); + } + else { + Method mtd = (Method)member; + + return mtd.invoke(x); + } + } + catch (Exception e) { + throw new IgniteCheckedException(e); + } + } + + /** + * @param name Property name. + */ + public void name(String name) { + this.name = name; + } + + /** {@inheritDoc} */ + @Override public String name() { + return name; + } + + /** {@inheritDoc} */ + @Override public Class type() { + return member instanceof Field ? ((Field)member).getType() : ((Method)member).getReturnType(); + } + + /** + * @param parent Parent property if this is embeddable element. + */ + public void parent(ClassProperty parent) { + this.parent = parent; + } + + /** {@inheritDoc} */ + @Override public String toString() { + return S.toString(ClassProperty.class, this); + } + + /** + * @param cls Class. + * @return {@code true} If this property or some parent relates to member of the given class. + */ + public boolean knowsClass(Class cls) { + return member.getDeclaringClass() == cls || (parent != null && parent.knowsClass(cls)); } } } http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/781f0d5f/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 e080c6d..f6cff33 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 @@ -41,6 +41,8 @@ import org.jsr166.*; import javax.cache.*; import java.lang.reflect.*; +import java.math.*; +import java.sql.*; import java.util.*; import java.util.concurrent.*; @@ -52,6 +54,28 @@ import static org.apache.ignite.internal.processors.query.GridQueryIndexType.*; * Indexing processor. */ public class GridQueryProcessor extends GridProcessorAdapter { + /** */ + private static final Class GEOMETRY_CLASS = U.classForName("com.vividsolutions.jts.geom.Geometry", null); + + /** */ + private static Set> SQL_TYPES = new HashSet<>(F.>asList( + Integer.class, + Boolean.class, + Byte.class, + Short.class, + Long.class, + BigDecimal.class, + Double.class, + Float.class, + Time.class, + Timestamp.class, + java.util.Date.class, + java.sql.Date.class, + String.class, + UUID.class, + byte[].class + )); + /** For tests. */ public static Class idxCls; @@ -801,6 +825,26 @@ public class GridQueryProcessor extends GridProcessorAdapter { } /** + * Checks if the given class can be mapped to a simple SQL type. + * + * @param cls Class. + * @return {@code true} If can. + */ + public static boolean isSqlType(Class cls) { + return SQL_TYPES.contains(cls); + } + + /** + * Checks if the given class is GEOMETRY. + * + * @param cls Class. + * @return {@code true} If this is geometry. + */ + public static boolean isGeometryClass(Class cls) { + return GEOMETRY_CLASS != null && GEOMETRY_CLASS.isAssignableFrom(cls); + } + + /** * Gets type name by class. * * @param cls Class. http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/781f0d5f/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java index 06c0961..359341a 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java @@ -1584,8 +1584,6 @@ public class IgniteH2Indexing implements GridQueryIndexing { map.put(Timestamp.class, TIMESTAMP); map.put(java.util.Date.class, TIMESTAMP); map.put(java.sql.Date.class, DATE); - map.put(char.class, CHAR); - map.put(Character.class, CHAR); map.put(String.class, VARCHAR); map.put(UUID.class, UUID); map.put(byte[].class, BINARY);