You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by am...@apache.org on 2019/06/05 11:08:10 UTC

[ignite] 07/31: GG-18896 Web Console: Added support for configuration of "Hive storage" and "Hive data source". Fixes #54.

This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch gg-19225
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit f79a2d6cc4aaa6f99e751a9ee84a35f355418cf4
Author: Vasiliy Sisko <vs...@gridgain.com>
AuthorDate: Thu May 30 16:25:22 2019 +0700

    GG-18896 Web Console: Added support for configuration of "Hive storage" and "Hive data source". Fixes #54.
    
    (cherry picked from commit 465689cdc323b2af3cc29d1311808990d15b2c97)
---
 modules/web-console/backend/app/schemas.js         |  26 ++++-
 .../components/modal-import-models/component.js    |  29 +++--
 .../components/cache-edit-form/controller.ts       |   4 +
 .../components/cache-edit-form/templates/store.pug | 130 ++++++++++++++++++++-
 .../generator/generator/ConfigurationGenerator.js  | 108 ++++++++++-------
 .../generator/generator/JavaTransformer.service.js |   6 +-
 .../generator/generator/Readme.service.js          |   4 +-
 .../generator/generator/defaults/Cache.service.js  |   7 ++
 .../frontend/app/configuration/mixins.pug          |   4 +-
 .../frontend/app/configuration/services/Caches.ts  |   7 ++
 .../web-console/frontend/app/data/dialects.json    |   3 +-
 .../frontend/app/data/pom-dependencies.json        |   5 +
 .../frontend/app/services/LegacyUtils.service.js   |   3 +-
 13 files changed, 272 insertions(+), 64 deletions(-)

diff --git a/modules/web-console/backend/app/schemas.js b/modules/web-console/backend/app/schemas.js
index 0191f4f..6cacf78 100644
--- a/modules/web-console/backend/app/schemas.js
+++ b/modules/web-console/backend/app/schemas.js
@@ -243,13 +243,29 @@ module.exports.factory = function() {
         cacheStoreFactory: {
             kind: {
                 type: String,
-                enum: ['CacheJdbcPojoStoreFactory', 'CacheJdbcBlobStoreFactory', 'CacheHibernateBlobStoreFactory']
+                enum: ['HiveCacheJdbcPojoStoreFactory', 'CacheJdbcPojoStoreFactory', 'CacheJdbcBlobStoreFactory', 'CacheHibernateBlobStoreFactory']
+            },
+            HiveCacheJdbcPojoStoreFactory: {
+                dataSourceBean: String,
+                dialect: {
+                    type: String,
+                    enum: ['Generic', 'Oracle', 'DB2', 'SQLServer', 'MySQL', 'PostgreSQL', 'H2', 'Hive']
+                },
+                implementationVersion: String,
+                batchSize: Number,
+                maximumPoolSize: Number,
+                maximumWriteAttempts: Number,
+                parallelLoadCacheMinimumThreshold: Number,
+                hasher: String,
+                transformer: String,
+                sqlEscapeAll: Boolean,
+                streamerEnabled: {type: Boolean, default: true}
             },
             CacheJdbcPojoStoreFactory: {
                 dataSourceBean: String,
                 dialect: {
                     type: String,
-                    enum: ['Generic', 'Oracle', 'DB2', 'SQLServer', 'MySQL', 'PostgreSQL', 'H2']
+                    enum: ['Generic', 'Oracle', 'DB2', 'SQLServer', 'MySQL', 'PostgreSQL', 'H2', 'Hive']
                 },
                 implementationVersion: String,
                 batchSize: Number,
@@ -267,7 +283,7 @@ module.exports.factory = function() {
                 dataSourceBean: String,
                 dialect: {
                     type: String,
-                    enum: ['Generic', 'Oracle', 'DB2', 'SQLServer', 'MySQL', 'PostgreSQL', 'H2']
+                    enum: ['Generic', 'Oracle', 'DB2', 'SQLServer', 'MySQL', 'PostgreSQL', 'H2', 'Hive']
                 },
                 initSchema: Boolean,
                 createTableQuery: String,
@@ -589,7 +605,7 @@ module.exports.factory = function() {
                 dataSourceBean: String,
                 dialect: {
                     type: String,
-                    enum: ['Generic', 'Oracle', 'DB2', 'SQLServer', 'MySQL', 'PostgreSQL', 'H2']
+                    enum: ['Generic', 'Oracle', 'DB2', 'SQLServer', 'MySQL', 'PostgreSQL', 'H2', 'Hive']
                 }
             },
             SharedFs: {
@@ -951,7 +967,7 @@ module.exports.factory = function() {
                 dataSourceBean: String,
                 dialect: {
                     type: String,
-                    enum: ['Generic', 'Oracle', 'DB2', 'SQLServer', 'MySQL', 'PostgreSQL', 'H2']
+                    enum: ['Generic', 'Oracle', 'DB2', 'SQLServer', 'MySQL', 'PostgreSQL', 'H2', 'Hive']
                 },
                 user: String,
                 checkpointTableName: String,
diff --git a/modules/web-console/frontend/app/configuration/components/modal-import-models/component.js b/modules/web-console/frontend/app/configuration/components/modal-import-models/component.js
index 722c6b7..ee00805 100644
--- a/modules/web-console/frontend/app/configuration/components/modal-import-models/component.js
+++ b/modules/web-console/frontend/app/configuration/components/modal-import-models/component.js
@@ -93,7 +93,7 @@ export class ModalImportModels {
     /** @type {ng.ICompiledExpression} */
     onHide;
 
-    static $inject = ['$uiRouter', 'ConfigSelectors', 'ConfigEffects', 'ConfigureState', 'IgniteConfirm', 'IgniteConfirmBatch', 'IgniteFocus', 'SqlTypes', 'JavaTypes', 'IgniteMessages', '$scope', '$rootScope', 'AgentManager', 'IgniteActivitiesData', 'IgniteLoading', 'IgniteFormUtils', 'IgniteLegacyUtils'];
+    static $inject = ['$uiRouter', 'ConfigSelectors', 'ConfigEffects', 'ConfigureState', 'IgniteConfirm', 'IgniteConfirmBatch', 'IgniteFocus', 'SqlTypes', 'JavaTypes', 'IgniteMessages', '$scope', '$rootScope', 'AgentManager', 'IgniteActivitiesData', 'IgniteLoading', 'IgniteFormUtils', 'IgniteLegacyUtils', 'IgniteVersion'];
 
     /**
      * @param {UIRouter} $uiRouter
@@ -108,7 +108,7 @@ export class ModalImportModels {
      * @param {AgentManager} agentMgr
      * @param {ActivitiesData} ActivitiesData
      */
-    constructor($uiRouter, ConfigSelectors, ConfigEffects, ConfigureState, Confirm, ConfirmBatch, Focus, SqlTypes, JavaTypes, Messages, $scope, $root, agentMgr, ActivitiesData, Loading, FormUtils, LegacyUtils) {
+    constructor($uiRouter, ConfigSelectors, ConfigEffects, ConfigureState, Confirm, ConfirmBatch, Focus, SqlTypes, JavaTypes, Messages, $scope, $root, agentMgr, ActivitiesData, Loading, FormUtils, LegacyUtils, IgniteVersion) {
         this.$uiRouter = $uiRouter;
         this.ConfirmBatch = ConfirmBatch;
         this.ConfigSelectors = ConfigSelectors;
@@ -120,7 +120,7 @@ export class ModalImportModels {
         this.JavaTypes = JavaTypes;
         this.SqlTypes = SqlTypes;
         this.ActivitiesData = ActivitiesData;
-        Object.assign(this, {Confirm, Focus, Messages, Loading, FormUtils, LegacyUtils});
+        Object.assign(this, {Confirm, Focus, Messages, Loading, FormUtils, LegacyUtils, IgniteVersion});
     }
 
     loadData() {
@@ -389,6 +389,12 @@ export class ModalImportModels {
                 jdbcDriverClass: 'org.h2.Driver',
                 jdbcUrl: 'jdbc:h2:tcp://[host]/[database]',
                 user: 'sa'
+            },
+            {
+                db: 'Hive',
+                jdbcDriverClass: 'org.apache.hive.jdbc.HiveDriver',
+                jdbcUrl: 'jdbc:hive2://[host]:[port]/[database]',
+                user: 'hiveuser'
             }
         ];
 
@@ -820,13 +826,18 @@ export class ModalImportModels {
 
                         const catalog = $scope.importDomain.catalog;
 
+                        const dsFactoryBean = {
+                            dataSourceBean: 'ds' + dialect + '_' + catalog,
+                            dialect,
+                            implementationVersion: $scope.selectedPreset.jdbcDriverImplementationVersion
+                        };
+
                         newCache.cacheStoreFactory = {
-                            kind: 'CacheJdbcPojoStoreFactory',
-                            CacheJdbcPojoStoreFactory: {
-                                dataSourceBean: 'ds' + dialect + '_' + catalog,
-                                dialect,
-                                implementationVersion: $scope.selectedPreset.jdbcDriverImplementationVersion
-                            },
+                            kind: dialect === 'Hive' && this.IgniteVersion.currentSbj.getValue().hiveVersion
+                                ? 'HiveCacheJdbcPojoStoreFactory'
+                                : 'CacheJdbcPojoStoreFactory',
+                            HiveCacheJdbcPojoStoreFactory: dsFactoryBean,
+                            CacheJdbcPojoStoreFactory: dsFactoryBean,
                             CacheJdbcBlobStoreFactory: { connectVia: 'DataSource' }
                         };
                     }
diff --git a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/controller.ts b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/controller.ts
index 7101d95..b9cdd70 100644
--- a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/controller.ts
+++ b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/controller.ts
@@ -56,6 +56,10 @@ export default class CacheEditFormController {
 
             if (this.available(['1.0.0', '2.0.0']))
                 this.$scope.affinityFunction.splice(1, 0, {value: 'Fair', label: 'Fair'});
+
+            if (!this.IgniteVersion.currentSbj.getValue().hiveVersion
+                && _.get(this.clonedCache, 'cacheStoreFactory.kind') === 'HiveCacheJdbcPojoStoreFactory')
+                this.clonedCache.cacheStoreFactory.kind = null;
         };
 
         rebuildDropdowns();
diff --git a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/store.pug b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/store.pug
index 5f1559b..c87ff61 100644
--- a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/store.pug
+++ b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/store.pug
@@ -29,7 +29,32 @@ panel-collapsible(ng-form=form on-open=`ui.loadPanel('${form}')`)
         .pca-form-column-6.pc-form-grid-row
             -var storeFactory = `${model}.cacheStoreFactory`;
             -var storeFactoryKind = `${storeFactory}.kind`;
-            .pc-form-grid-col-60
+            .pc-form-grid-col-60(ng-if='$ctrl.IgniteVersion.currentSbj.getValue().hiveVersion')
+                +form-field__dropdown({
+                    label: 'Store factory:',
+                    model: storeFactoryKind,
+                    name: '"cacheStoreFactory_2_7"',
+                    placeholder: '{{ ::$ctrl.Caches.cacheStoreFactory.kind.default }}',
+                    options: '::$ctrl.Caches.cacheStoreFactory.values_2_7',
+                    tip: `Factory for persistent storage for cache data
+                    <ul>
+                        <li>JDBC POJO store factory - Objects are stored in underlying database by using java beans mapping description via reflection backed by JDBC</li>
+                        <li>JDBC BLOB store factory - Objects are stored in underlying database in BLOB format backed by JDBC</li>
+                        <li>Hibernate BLOB store factory - Objects are stored in underlying database in BLOB format backed by Hibernate</li>
+                    </ul>`
+                })(
+                ui-validate=`{
+                        writeThroughOn: '$ctrl.Caches.cacheStoreFactory.storeDisabledValueOff(${model}, ${model}.writeThrough)',
+                        readThroughOn: '$ctrl.Caches.cacheStoreFactory.storeDisabledValueOff(${model}, ${model}.readThrough)',
+                        writeBehindOn: '$ctrl.Caches.cacheStoreFactory.storeDisabledValueOff(${model}, ${model}.writeBehindEnabled)'
+                    }`
+                ui-validate-watch-collection=`"[${model}.readThrough, ${model}.writeThrough, ${model}.writeBehindEnabled]"`
+                ng-model-options='{allowInvalid: true}'
+                )
+                    +form-field__error({ error: 'writeThroughOn', message: 'Write through is enabled but store is not set' })
+                    +form-field__error({ error: 'readThroughOn', message: 'Read through is enabled but store is not set' })
+                    +form-field__error({ error: 'writeBehindOn', message: 'Write-behind is enabled but store is not set' })
+            .pc-form-grid-col-60(ng-if='!$ctrl.IgniteVersion.currentSbj.getValue().hiveVersion')
                 +form-field__dropdown({
                     label: 'Store factory:',
                     model: storeFactoryKind,
@@ -55,6 +80,109 @@ panel-collapsible(ng-form=form on-open=`ui.loadPanel('${form}')`)
                     +form-field__error({ error: 'readThroughOn', message: 'Read through is enabled but store is not set' })
                     +form-field__error({ error: 'writeBehindOn', message: 'Write-behind is enabled but store is not set' })
             .pc-form-group(ng-if=storeFactoryKind)
+                .pc-form-grid-row(ng-if=`$ctrl.available("2.7.0") && ${storeFactoryKind} === 'HiveCacheJdbcPojoStoreFactory'`)
+                    -var pojoStoreFactory = `${storeFactory}.HiveCacheJdbcPojoStoreFactory`
+                    -var required = `${storeFactoryKind} === 'HiveCacheJdbcPojoStoreFactory'`
+
+                    .pc-form-grid-col-30
+                        +form-field__text({
+                            label: 'Data source bean name:',
+                            model: `${pojoStoreFactory}.dataSourceBean`,
+                            name: '"pojoDataSourceBean"',
+                            required: required,
+                            placeholder: 'Input bean name',
+                            tip: 'Name of the data source bean in Spring context'
+                        })(
+                            is-valid-java-identifier
+                            not-java-reserved-word
+                        )
+                            +form-field__error({ error: 'required', message: 'Data source bean name is required' })
+                            +form-field__error({ error: 'isValidJavaIdentifier', message: 'Data source bean name is not a valid Java identifier' })
+                            +form-field__error({ error: 'notJavaReservedWord', message: 'Data source bean name should not be a Java reserved word' })
+                    .pc-form-grid-col-30
+                        +form-field__dialect({
+                            label: 'Dialect:',
+                            model: `${pojoStoreFactory}.dialect`,
+                            name: '"pojoDialect"',
+                            required,
+                            tip: 'Dialect of SQL implemented by a particular RDBMS:',
+                            genericDialectName: 'Generic JDBC dialect',
+                            placeholder: 'Choose JDBC dialect',
+                            change:`$ctrl.clearImplementationVersion(${pojoStoreFactory})`
+                        })
+                    .pc-form-grid-col-60(ng-if=`$ctrl.Caches.requiresProprietaryDrivers(${pojoStoreFactory})`)
+                        a.link-success(ng-href=`{{ $ctrl.Caches.jdbcDriverURL(${pojoStoreFactory}) }}` target='_blank')
+                            | Download JDBC drivers?
+                    .pc-form-grid-col-30
+                        +form-field__number({
+                            label:'Batch size:',
+                            model: `${pojoStoreFactory}.batchSize`,
+                            name: '"pojoBatchSize"',
+                            placeholder: '512',
+                            min: '1',
+                            tip: 'Maximum batch size for writeAll and deleteAll operations'
+                        })
+                    .pc-form-grid-col-30
+                        +form-field__number({
+                            label: 'Thread count:',
+                            model: `${pojoStoreFactory}.maximumPoolSize`,
+                            name: '"pojoMaximumPoolSize"',
+                            placeholder: 'availableProcessors',
+                            min: '1',
+                            tip: 'Maximum workers thread count.<br/>\
+                                 These threads are responsible for load cache.'
+                        })
+                    .pc-form-grid-col-30
+                        +form-field__number({
+                            label: 'Maximum write attempts:',
+                            model: `${pojoStoreFactory}.maximumWriteAttempts`,
+                            name: '"pojoMaximumWriteAttempts"',
+                            placeholder: '2',
+                            min: '0',
+                            tip: 'Maximum write attempts in case of database error'
+                        })
+                    .pc-form-grid-col-30
+                        +form-field__number({
+                            label: 'Parallel load threshold:',
+                            model: `${pojoStoreFactory}.parallelLoadCacheMinimumThreshold`,
+                            name: '"pojoParallelLoadCacheMinimumThreshold"',
+                            placeholder: '512',
+                            min: '0',
+                            tip: 'Parallel load cache minimum threshold.<br/>\
+                                 If <b>0</b> then load sequentially.'
+                        })
+                    .pc-form-grid-col-60
+                        +form-field__java-class({
+                            label: 'Hasher:',
+                            model: `${pojoStoreFactory}.hasher`,
+                            name: '"pojoHasher"',
+                            tip: 'Hash calculator',
+                            validationActive: required
+                        })
+                    .pc-form-grid-col-60
+                        +form-field__java-class({
+                            label: 'Transformer:',
+                            model: `${pojoStoreFactory}.transformer`,
+                            name: '"pojoTransformer"',
+                            tip: 'Types transformer',
+                            validationActive: required
+                        })
+                    .pc-form-grid-col-60
+                        +form-field__checkbox({
+                            label: 'Escape table and filed names',
+                            model:`${pojoStoreFactory}.sqlEscapeAll`,
+                            name: '"sqlEscapeAll"',
+                            tip: 'If enabled than all schema, table and field names will be escaped with double quotes (for example: "tableName"."fieldName").<br/>\
+                                  This enforces case sensitivity for field names and also allows having special characters in table and field names.<br/>\
+                                  Escaped names will be used for CacheJdbcPojoStore internal SQL queries.'
+                        })
+                    .pc-form-grid-col-60
+                        +form-field__checkbox({
+                            label: 'Data streamer',
+                            model:`${pojoStoreFactory}.streamerEnabled`,
+                            name: '"streamerEnabled"',
+                            tip: 'Indicating whether job data streamer is used during load cache.'
+                        })
                 .pc-form-grid-row(ng-if=`${storeFactoryKind} === 'CacheJdbcPojoStoreFactory'`)
                     -var pojoStoreFactory = `${storeFactory}.CacheJdbcPojoStoreFactory`
                     -var required = `${storeFactoryKind} === 'CacheJdbcPojoStoreFactory'`
diff --git a/modules/web-console/frontend/app/configuration/generator/generator/ConfigurationGenerator.js b/modules/web-console/frontend/app/configuration/generator/generator/ConfigurationGenerator.js
index b4fb34f..25e5017 100644
--- a/modules/web-console/frontend/app/configuration/generator/generator/ConfigurationGenerator.js
+++ b/modules/web-console/frontend/app/configuration/generator/generator/ConfigurationGenerator.js
@@ -134,7 +134,7 @@ export default class IgniteConfigurationGenerator {
         this.clusterTransactions(cluster.transactionConfiguration, available, cfg);
         this.clusterUserAttributes(cluster, cfg);
 
-        this.clusterCaches(cluster, cluster.caches, cluster.igfss, available, client, cfg);
+        this.clusterCaches(cluster, cluster.caches, cluster.igfss, available, targetVer, client, cfg);
 
         if (!client)
             this.clusterIgfss(cluster.igfss, available, cfg);
@@ -151,15 +151,18 @@ export default class IgniteConfigurationGenerator {
 
         switch (dialect) {
             case 'Generic':
+            case 'Hive':
                 dsBean = new Bean('com.mchange.v2.c3p0.ComboPooledDataSource', id, {})
                     .property('jdbcUrl', `${id}.jdbc.url`, 'jdbc:your_database');
 
                 break;
+
             case 'Oracle':
                 dsBean = new Bean('oracle.jdbc.pool.OracleDataSource', id, {})
                     .property('URL', `${id}.jdbc.url`, 'jdbc:oracle:thin:@[host]:[port]:[database]');
 
                 break;
+
             case 'DB2':
                 dsBean = new Bean('com.ibm.db2.jcc.DB2DataSource', id, {})
                     .property('serverName', `${id}.jdbc.server_name`, 'YOUR_DATABASE_SERVER_NAME')
@@ -168,11 +171,13 @@ export default class IgniteConfigurationGenerator {
                     .propertyInt('driverType', `${id}.jdbc.driver_type`, 'YOUR_JDBC_DRIVER_TYPE');
 
                 break;
+
             case 'SQLServer':
                 dsBean = new Bean('com.microsoft.sqlserver.jdbc.SQLServerDataSource', id, {})
                     .property('URL', `${id}.jdbc.url`, 'jdbc:sqlserver://[host]:[port][;databaseName=database]');
 
                 break;
+
             case 'MySQL':
                 const dep = storeDeps
                     ? _.find(storeDeps, (d) => d.name === dialect)
@@ -184,11 +189,13 @@ export default class IgniteConfigurationGenerator {
                     .property('URL', `${id}.jdbc.url`, 'jdbc:mysql://[host]:[port]/[database]');
 
                 break;
+
             case 'PostgreSQL':
                 dsBean = new Bean('org.postgresql.ds.PGPoolingDataSource', id, {})
                     .property('url', `${id}.jdbc.url`, 'jdbc:postgresql://[host]:[port]/[database]');
 
                 break;
+
             case 'H2':
                 dsBean = new Bean('org.h2.jdbcx.JdbcDataSource', id, {})
                     .property('URL', `${id}.jdbc.url`, 'jdbc:h2:tcp://[host]/[database]');
@@ -448,7 +455,7 @@ export default class IgniteConfigurationGenerator {
         });
     }
 
-    static clusterCaches(cluster, caches, igfss, available, client, cfg = this.igniteConfigurationBean(cluster)) {
+    static clusterCaches(cluster, caches, igfss, available, targetVer, client, cfg = this.igniteConfigurationBean(cluster)) {
         const usedDataSourceVersions = [];
 
         if (cluster.discovery.kind === 'Jdbc')
@@ -466,7 +473,7 @@ export default class IgniteConfigurationGenerator {
 
         const useDeps = _.uniqWith(ArtifactVersionChecker.latestVersions(usedDataSourceVersions), _.isEqual);
 
-        const ccfgs = _.map(caches, (cache) => this.cacheConfiguration(cache, available, useDeps));
+        const ccfgs = _.map(caches, (cache) => this.cacheConfiguration(cache, available, targetVer, useDeps));
 
         if (!client) {
             _.forEach(igfss, (igfs) => {
@@ -2496,58 +2503,73 @@ export default class IgniteConfigurationGenerator {
         return ccfg;
     }
 
-    // Generate cache store group.
-    static cacheStore(cache, domains, available, deps, ccfg = this.cacheConfigurationBean(cache)) {
-        const kind = _.get(cache, 'cacheStoreFactory.kind');
+    static _baseJdbcPojoStoreFactory(storeFactory, bean, cacheName, domains, available, deps) {
+        const jdbcId = bean.valueOf('dataSourceBean');
 
-        if (kind && cache.cacheStoreFactory[kind]) {
-            let bean = null;
+        bean.dataSource(jdbcId, 'dataSourceBean', this.dataSourceBean(jdbcId, storeFactory.dialect, available, deps, storeFactory.implementationVersion))
+            .beanProperty('dialect', new EmptyBean(this.dialectClsName(storeFactory.dialect)));
 
-            const storeFactory = cache.cacheStoreFactory[kind];
+        bean.intProperty('batchSize')
+            .intProperty('maximumPoolSize')
+            .intProperty('maximumWriteAttempts')
+            .intProperty('parallelLoadCacheMinimumThreshold')
+            .emptyBeanProperty('hasher')
+            .emptyBeanProperty('transformer')
+            .boolProperty('sqlEscapeAll');
+
+        const setType = (typeBean, propName) => {
+            if (javaTypes.nonBuiltInClass(typeBean.valueOf(propName)))
+                typeBean.stringProperty(propName);
+            else
+                typeBean.classProperty(propName);
+        };
 
-            switch (kind) {
-                case 'CacheJdbcPojoStoreFactory':
-                    bean = new Bean('org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory', 'cacheStoreFactory',
-                        storeFactory, cacheDflts.cacheStoreFactory.CacheJdbcPojoStoreFactory);
+        const types = _.reduce(domains, (acc, domain) => {
+            if (isNil(domain.databaseTable))
+                return acc;
 
-                    const jdbcId = bean.valueOf('dataSourceBean');
+            const typeBean = this.domainJdbcTypeBean(_.merge({}, domain, {cacheName}))
+                .stringProperty('cacheName');
 
-                    bean.dataSource(jdbcId, 'dataSourceBean', this.dataSourceBean(jdbcId, storeFactory.dialect, available, deps, storeFactory.implementationVersion))
-                        .beanProperty('dialect', new EmptyBean(this.dialectClsName(storeFactory.dialect)));
+            setType(typeBean, 'keyType');
+            setType(typeBean, 'valueType');
 
-                    bean.intProperty('batchSize')
-                        .intProperty('maximumPoolSize')
-                        .intProperty('maximumWriteAttempts')
-                        .intProperty('parallelLoadCacheMinimumThreshold')
-                        .emptyBeanProperty('hasher')
-                        .emptyBeanProperty('transformer')
-                        .boolProperty('sqlEscapeAll');
+            this.domainStore(domain, typeBean);
 
-                    const setType = (typeBean, propName) => {
-                        if (javaTypes.nonBuiltInClass(typeBean.valueOf(propName)))
-                            typeBean.stringProperty(propName);
-                        else
-                            typeBean.classProperty(propName);
-                    };
+            acc.push(typeBean);
 
-                    const types = _.reduce(domains, (acc, domain) => {
-                        if (isNil(domain.databaseTable))
-                            return acc;
+            return acc;
+        }, []);
 
-                        const typeBean = this.domainJdbcTypeBean(_.merge({}, domain, {cacheName: cache.name}))
-                            .stringProperty('cacheName');
+        bean.varArgProperty('types', 'types', types, 'org.apache.ignite.cache.store.jdbc.JdbcType');
+    }
 
-                        setType(typeBean, 'keyType');
-                        setType(typeBean, 'valueType');
+    // Generate cache store group.
+    static cacheStore(cache, domains, available, targetVer, deps, ccfg = this.cacheConfigurationBean(cache)) {
+        const kind = _.get(cache, 'cacheStoreFactory.kind');
 
-                        this.domainStore(domain, typeBean);
+        if (kind && cache.cacheStoreFactory[kind]) {
+            let bean = null;
 
-                        acc.push(typeBean);
+            const storeFactory = cache.cacheStoreFactory[kind];
 
-                        return acc;
-                    }, []);
+            switch (kind) {
+                case 'HiveCacheJdbcPojoStoreFactory':
+                    if (targetVer.hiveVersion) {
+                        bean = new Bean('org.gridgain.cachestore.HiveCacheJdbcPojoStoreFactory', 'cacheStoreFactory',
+                            storeFactory, cacheDflts.cacheStoreFactory.HiveCacheJdbcPojoStoreFactory);
+
+                        this._baseJdbcPojoStoreFactory(storeFactory, bean, cache.name, domains, available, deps);
+
+                        bean.boolProperty('streamerEnabled');
+                    }
+
+                    break;
+                case 'CacheJdbcPojoStoreFactory':
+                    bean = new Bean('org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory', 'cacheStoreFactory',
+                        storeFactory, cacheDflts.cacheStoreFactory.CacheJdbcPojoStoreFactory);
 
-                    bean.varArgProperty('types', 'types', types, 'org.apache.ignite.cache.store.jdbc.JdbcType');
+                    this._baseJdbcPojoStoreFactory(storeFactory, bean, cache.name, domains, available, deps);
 
                     break;
                 case 'CacheJdbcBlobStoreFactory':
@@ -2768,12 +2790,12 @@ export default class IgniteConfigurationGenerator {
         ccfg.collectionProperty('qryEntities', 'queryEntities', qryEntities, 'org.apache.ignite.cache.QueryEntity');
     }
 
-    static cacheConfiguration(cache, available, deps = [], ccfg = this.cacheConfigurationBean(cache)) {
+    static cacheConfiguration(cache, available, targetVer, deps = [], ccfg = this.cacheConfigurationBean(cache)) {
         this.cacheGeneral(cache, available, ccfg);
         this.cacheAffinity(cache, available, ccfg);
         this.cacheMemory(cache, available, ccfg);
         this.cacheQuery(cache, cache.domains, available, ccfg);
-        this.cacheStore(cache, cache.domains, available, deps, ccfg);
+        this.cacheStore(cache, cache.domains, available, targetVer, deps, ccfg);
         this.cacheKeyConfiguration(cache.keyConfiguration, available, ccfg);
 
         const igfs = _.get(cache, 'nodeFilter.IGFS.instance');
diff --git a/modules/web-console/frontend/app/configuration/generator/generator/JavaTransformer.service.js b/modules/web-console/frontend/app/configuration/generator/generator/JavaTransformer.service.js
index 9ea0fe3..3b4f0d2 100644
--- a/modules/web-console/frontend/app/configuration/generator/generator/JavaTransformer.service.js
+++ b/modules/web-console/frontend/app/configuration/generator/generator/JavaTransformer.service.js
@@ -23,7 +23,11 @@ import StringBuilder from './StringBuilder';
 import VersionService from 'app/services/Version.service';
 
 const versionService = new VersionService();
-const STORE_FACTORY = ['org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory'];
+
+const STORE_FACTORY = [
+    'org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory',
+    'org.gridgain.cachestore.HiveCacheJdbcPojoStoreFactory'
+];
 
 // Descriptors for generation of demo data.
 const PREDEFINED_QUERIES = [
diff --git a/modules/web-console/frontend/app/configuration/generator/generator/Readme.service.js b/modules/web-console/frontend/app/configuration/generator/generator/Readme.service.js
index 6b631ee..66e8683 100644
--- a/modules/web-console/frontend/app/configuration/generator/generator/Readme.service.js
+++ b/modules/web-console/frontend/app/configuration/generator/generator/Readme.service.js
@@ -32,7 +32,7 @@ export default class IgniteReadmeGenerator {
      * @returns {string} Generated content.
      */
     generateJDBC(sb = new StringBuilder()) {
-        sb.append('Proprietary JDBC drivers for databases like Oracle, IBM DB2, Microsoft SQL Server are not available on Maven Central repository.');
+        sb.append('Proprietary JDBC drivers for databases like Oracle, IBM DB2 Server are not available on Maven Central repository.');
         sb.append('Drivers should be downloaded manually and copied to this folder.');
 
         return sb.asString();
@@ -69,7 +69,7 @@ export default class IgniteReadmeGenerator {
 
         sb.emptyLine();
 
-        sb.append('Note, in case of using proprietary JDBC drivers (Oracle, IBM DB2, Microsoft SQL Server)');
+        sb.append('Note, in case of using proprietary JDBC drivers (Oracle, IBM DB2)');
         sb.append('you should download them manually and copy into ./jdbc-drivers folder.');
 
         return sb.asString();
diff --git a/modules/web-console/frontend/app/configuration/generator/generator/defaults/Cache.service.js b/modules/web-console/frontend/app/configuration/generator/generator/defaults/Cache.service.js
index ab731d6..d44992c 100644
--- a/modules/web-console/frontend/app/configuration/generator/generator/defaults/Cache.service.js
+++ b/modules/web-console/frontend/app/configuration/generator/generator/defaults/Cache.service.js
@@ -40,6 +40,13 @@ const DFLT_CACHE = {
     storeKeepBinary: false,
     loadPreviousValue: false,
     cacheStoreFactory: {
+        HiveCacheJdbcPojoStoreFactory: {
+            batchSize: 512,
+            maximumWriteAttempts: 2,
+            parallelLoadCacheMinimumThreshold: 512,
+            sqlEscapeAll: false,
+            streamerEnabled: true
+        },
         CacheJdbcPojoStoreFactory: {
             batchSize: 512,
             maximumWriteAttempts: 2,
diff --git a/modules/web-console/frontend/app/configuration/mixins.pug b/modules/web-console/frontend/app/configuration/mixins.pug
index 9794662..b6e47b7 100644
--- a/modules/web-console/frontend/app/configuration/mixins.pug
+++ b/modules/web-console/frontend/app/configuration/mixins.pug
@@ -404,7 +404,8 @@ mixin form-field__dialect({ label, model, name, required, tip, genericDialectNam
                 {value: "SQLServer", label: "Microsoft SQL Server"},\
                 {value: "MySQL", label: "MySQL"},\
                 {value: "PostgreSQL", label: "PostgreSQL"},\
-                {value: "H2", label: "H2 database"}\
+                {value: "H2", label: "H2 database"},\
+                {value: "Hive", label: "Apache Hive"}\
         ]',
         tip: `${ tip }
             <ul>
@@ -415,5 +416,6 @@ mixin form-field__dialect({ label, model, name, required, tip, genericDialectNam
                 <li>MySQL</li>
                 <li>PostgreSQL</li>
                 <li>H2 database</li>
+                <li>Apache Hive</li>
             </ul>`
     })
diff --git a/modules/web-console/frontend/app/configuration/services/Caches.ts b/modules/web-console/frontend/app/configuration/services/Caches.ts
index 4649b1a..1279a2d 100644
--- a/modules/web-console/frontend/app/configuration/services/Caches.ts
+++ b/modules/web-console/frontend/app/configuration/services/Caches.ts
@@ -191,6 +191,13 @@ export default class Caches {
             {value: 'CacheHibernateBlobStoreFactory', label: 'Hibernate BLOB store factory'},
             {value: null, label: 'Not set'}
         ],
+        values_2_7: [
+            {value: 'HiveCacheJdbcPojoStoreFactory', label: 'GridGain Hive JDBC POJO store factory'},
+            {value: 'CacheJdbcPojoStoreFactory', label: 'JDBC POJO store factory'},
+            {value: 'CacheJdbcBlobStoreFactory', label: 'JDBC BLOB store factory'},
+            {value: 'CacheHibernateBlobStoreFactory', label: 'Hibernate BLOB store factory'},
+            {value: null, label: 'Not set'}
+        ],
         storeDisabledValueOff: (cache, value) => {
             return cache && cache.cacheStoreFactory.kind ? true : !value;
         },
diff --git a/modules/web-console/frontend/app/data/dialects.json b/modules/web-console/frontend/app/data/dialects.json
index 007fbc6..87dccfc 100644
--- a/modules/web-console/frontend/app/data/dialects.json
+++ b/modules/web-console/frontend/app/data/dialects.json
@@ -5,5 +5,6 @@
   "SQLServer": "org.apache.ignite.cache.store.jdbc.dialect.SQLServerDialect",
   "MySQL": "org.apache.ignite.cache.store.jdbc.dialect.MySQLDialect",
   "PostgreSQL": "org.apache.ignite.cache.store.jdbc.dialect.BasicJdbcDialect",
-  "H2": "org.apache.ignite.cache.store.jdbc.dialect.H2Dialect"
+  "H2": "org.apache.ignite.cache.store.jdbc.dialect.H2Dialect",
+  "Hive": "org.apache.ignite.cache.store.jdbc.dialect.BasicJdbcDialect"
 }
\ No newline at end of file
diff --git a/modules/web-console/frontend/app/data/pom-dependencies.json b/modules/web-console/frontend/app/data/pom-dependencies.json
index 428455f..e7bc106 100644
--- a/modules/web-console/frontend/app/data/pom-dependencies.json
+++ b/modules/web-console/frontend/app/data/pom-dependencies.json
@@ -15,6 +15,11 @@
         {"groupId": "com.mchange", "artifactId": "c3p0", "version": "0.9.5.2"},
         {"groupId": "com.mchange", "artifactId": "mchange-commons-java", "version": "0.2.11"}
     ],
+    "Hive": [
+        {"groupId": "org.apache.hive", "artifactId": "hive-jdbc", "version": "3.1.1"},
+        {"groupId": "com.mchange", "artifactId": "c3p0", "version": "0.9.5.2"},
+        {"groupId": "com.mchange", "artifactId": "mchange-commons-java", "version": "0.2.11"}
+    ],
     "MySQL": {"groupId": "mysql", "artifactId": "mysql-connector-java", "version": "8.0.15"},
     "PostgreSQL": {"groupId": "org.postgresql", "artifactId": "postgresql", "version": "42.2.5"},
     "H2": {"groupId": "com.h2database", "artifactId": "h2", "version": [
diff --git a/modules/web-console/frontend/app/services/LegacyUtils.service.js b/modules/web-console/frontend/app/services/LegacyUtils.service.js
index 27ed502..2ddbc63 100644
--- a/modules/web-console/frontend/app/services/LegacyUtils.service.js
+++ b/modules/web-console/frontend/app/services/LegacyUtils.service.js
@@ -242,7 +242,8 @@ export default function service(ErrorPopover) {
         {value: 'SQLServer', label: 'Microsoft SQL Server'},
         {value: 'MySQL', label: 'MySQL'},
         {value: 'PostgreSQL', label: 'PostgreSQL'},
-        {value: 'H2', label: 'H2 database'}
+        {value: 'H2', label: 'H2 database'},
+        {value: 'Hive', label: 'Apache Hive'}
     ];
 
     function domainForStoreConfigured(domain) {