瀏覽代碼

Merge pull request #1979 from flyingglass/3.0

添加Phoenix整合
miemieYaho 5 年之前
父節點
當前提交
4b1dee27a4

+ 6 - 0
mybatis-plus-annotation/src/main/java/com/baomidou/mybatisplus/annotation/DbType.java

@@ -88,6 +88,12 @@ public enum DbType {
      * Kingbase
      */
     KINGBASE_ES("kingbasees", "人大金仓数据库", "com.baomidou.mybatisplus.extension.plugins.pagination.dialects.KingbaseDialect"),
+
+    /**
+     * Phoenix
+     */
+    PHOENIX("phoenix", "Phoenix HBase数据库", "com.baomidou.mybatisplus.extension.plugins.pagination.dialects.PhoenixDialect"),
+
     /**
      * UNKONWN DB
      */

+ 1 - 0
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/enums/SqlMethod.java

@@ -26,6 +26,7 @@ public enum SqlMethod {
      * 插入
      */
     INSERT_ONE("insert", "插入一条数据(选择字段插入)", "<script>\nINSERT INTO %s %s VALUES %s\n</script>"),
+    UPSERT_ONE("upsert", "Phoenix插入一条数据(选择字段插入)", "<script>\nUPSERT INTO %s %s VALUES %s\n</script>"),
 
     /**
      * 删除

+ 67 - 0
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/injector/methods/Upsert.java

@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2011-2020, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed 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
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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 com.baomidou.mybatisplus.extension.injector.methods;
+
+import com.baomidou.mybatisplus.core.enums.SqlMethod;
+import com.baomidou.mybatisplus.core.injector.AbstractMethod;
+import com.baomidou.mybatisplus.core.metadata.TableInfo;
+import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
+import org.apache.ibatis.executor.keygen.KeyGenerator;
+import org.apache.ibatis.executor.keygen.NoKeyGenerator;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.mapping.SqlSource;
+
+/**
+ * 插入一条数据(选择字段插入)
+ *
+ * @author fly
+ * @since 2018-04-06
+ */
+@SuppressWarnings("all")
+public class Upsert extends AbstractMethod {
+
+    @Override
+    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
+        KeyGenerator keyGenerator = new NoKeyGenerator();
+        SqlMethod sqlMethod = SqlMethod.INSERT_ONE;
+        String columnScript = SqlScriptUtils.convertTrim(tableInfo.getAllInsertSqlColumnMaybeIf(),
+            LEFT_BRACKET, RIGHT_BRACKET, null, COMMA);
+        String valuesScript = SqlScriptUtils.convertTrim(tableInfo.getAllInsertSqlPropertyMaybeIf(null),
+            LEFT_BRACKET, RIGHT_BRACKET, null, COMMA);
+        String keyProperty = null;
+        String keyColumn = null;
+        // 表包含主键处理逻辑,如果不包含主键当普通字段处理
+        if (StringUtils.isNotBlank(tableInfo.getKeyProperty())) {
+            // 自增主键会造成HBase单Region数据挤压,直接移除
+            if (null != tableInfo.getKeySequence()) {
+                keyGenerator = TableInfoHelper.genKeyGenerator(getMethod(sqlMethod), tableInfo, builderAssistant);
+                keyProperty = tableInfo.getKeyProperty();
+                keyColumn = tableInfo.getKeyColumn();
+            }
+        }
+        String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), columnScript, valuesScript);
+        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
+        return this.addInsertMappedStatement(mapperClass, modelClass, getMethod(sqlMethod), sqlSource, keyGenerator, keyProperty, keyColumn);
+    }
+
+    @Override
+    public String getMethod(SqlMethod sqlMethod) {
+        // 自定义 mapper 方法名
+        return "upsert";
+    }
+}

+ 15 - 0
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/PhoenixDialect.java

@@ -0,0 +1,15 @@
+package com.baomidou.mybatisplus.extension.plugins.pagination.dialects;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.DialectModel;
+
+/**
+ * @author: fly
+ * Created date: 2019/12/20 11:39
+ */
+public class PhoenixDialect implements IDialect {
+    @Override
+    public DialectModel buildPaginationSql(String originalSql, long offset, long limit) {
+        String sql = originalSql + " limit " + FIRST_MARK + " offset " + SECOND_MARK;
+        return new DialectModel(sql, limit, offset).setConsumerChain();
+    }
+}

+ 2 - 0
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/toolkit/JdbcUtils.java

@@ -65,6 +65,8 @@ public class JdbcUtils {
             return DbType.XU_GU;
         } else if (jdbcUrl.contains(":kingbase:") || jdbcUrl.contains(":kingbase8:")) {
             return DbType.KINGBASE_ES;
+        } else if (jdbcUrl.contains(":phoenix:")) {
+            return DbType.PHOENIX;
         } else {
             logger.warn("The jdbcUrl is " + jdbcUrl + ", Mybatis Plus Cannot Read Database type or The Database's Not Supported!");
             return DbType.OTHER;

+ 8 - 1
mybatis-plus/build.gradle

@@ -19,5 +19,12 @@ dependencies {
     testCompile "${lib.'spring-context-support'}"
     testCompile "${lib.'spring-jdbc'}"
     testCompile 'javax.annotation:javax.annotation-api:1.3.2'
-
+    testCompile ('com.github.flyingglass:phoenix-core-shaded:1.0.0-SNAPSHOT')
+        {
+            exclude group: 'org.apache.phoenix', module: 'phoenix-core'
+        }
+    testCompile ('com.github.flyingglass:hbase-client-shaded:1.0.0-SNAPSHOT')
+        {
+            exclude group: 'org.apache.hbase', module: 'hbase-client'
+        }
 }

+ 18 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/phoenix/PhoenixBaseMapper.java

@@ -0,0 +1,18 @@
+package com.baomidou.mybatisplus.test.phoenix;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * @author: fly
+ * Created date: 2019/12/21 16:35
+ */
+public interface PhoenixBaseMapper<T> extends BaseMapper<T> {
+
+    int upsert(T entity);
+
+    @Override
+    default int insert(T entity) {
+        return upsert(entity);
+    }
+
+}

+ 50 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/phoenix/PhoenixTest.java

@@ -0,0 +1,50 @@
+package com.baomidou.mybatisplus.test.phoenix;
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.test.phoenix.entity.PhoenixTestInfo;
+import com.baomidou.mybatisplus.test.phoenix.mapper.PhoenixTestInfoMapper;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+/**
+ * @author: fly
+ * Created date: 2019/12/21 16:35
+ */
+@DirtiesContext
+@TestMethodOrder(MethodOrderer.Alphanumeric.class)
+@ExtendWith(SpringExtension.class)
+@ContextConfiguration(locations = {"classpath:phoenix/spring-test-phoenix.xml"})
+public class PhoenixTest {
+
+    @Resource(name = "phoenixTestInfoMapper")
+    PhoenixTestInfoMapper mapper;
+
+    @Test
+    void a00_upsertForeach() {
+
+        for (int i = 0; i < 10; i++) {
+            PhoenixTestInfo testInfo = new PhoenixTestInfo()
+                .setId(i)
+                .setName("upsert");
+            mapper.upsert(testInfo);
+        }
+    }
+
+    @Test
+    void a01_select() {
+        int size = 10;
+
+        List<PhoenixTestInfo> l = mapper.selectList(Wrappers.emptyWrapper());
+        assert (l.size() == size);
+    }
+
+
+}

+ 73 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/phoenix/config/DBConfig.java

@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2011-2020, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed 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
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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 com.baomidou.mybatisplus.test.phoenix.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+import org.springframework.jdbc.datasource.DataSourceTransactionManager;
+import org.springframework.jdbc.datasource.SimpleDriverDataSource;
+import org.springframework.jdbc.datasource.init.DataSourceInitializer;
+import org.springframework.jdbc.datasource.init.DatabasePopulator;
+import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+import javax.sql.DataSource;
+import java.io.IOException;
+import java.util.Properties;
+
+/**
+ * @author miemie
+ * @since 2018/6/7
+ */
+@Configuration
+@EnableTransactionManagement
+public class DBConfig {
+
+    @Bean("dataSource")
+    public DataSource dataSource() {
+        SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
+        dataSource.setDriverClass(org.apache.phoenix.jdbc.PhoenixDriver);
+        dataSource.setUrl("jdbc:phoenix:dnode28,dnode29,dnode30:2181");
+        Properties properties = new Properties();
+        properties.setProperty("schema", "TEST");
+        dataSource.setConnectionProperties(properties);
+        return dataSource;
+    }
+
+    @Bean
+    public DataSourceTransactionManager transactionManager(DataSource ds) {
+        return new DataSourceTransactionManager(ds);
+    }
+
+    @Bean
+    public DataSourceInitializer dataSourceInitializer(DataSource dataSource) throws IOException {
+        final DataSourceInitializer initializer = new DataSourceInitializer();
+        initializer.setDataSource(dataSource);
+        initializer.setDatabasePopulator(databasePopulator());
+        initializer.setEnabled(true);
+        return initializer;
+    }
+
+    private DatabasePopulator databasePopulator() throws IOException {
+        ResourceDatabasePopulator resourceDatabasePopulator = new ResourceDatabasePopulator();
+        resourceDatabasePopulator.setContinueOnError(false);
+        resourceDatabasePopulator.addScripts(
+            new PathMatchingResourcePatternResolver().getResources("classpath:/phoenix/*.sql")
+        );
+        return resourceDatabasePopulator;
+    }
+}

+ 87 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/phoenix/config/MybatisPlusConfig.java

@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2011-2020, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed 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
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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 com.baomidou.mybatisplus.test.phoenix.config;
+
+import com.baomidou.mybatisplus.core.MybatisConfiguration;
+import com.baomidou.mybatisplus.core.config.GlobalConfig;
+import com.baomidou.mybatisplus.core.injector.AbstractMethod;
+import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
+import com.baomidou.mybatisplus.extension.MybatisMapWrapperFactory;
+import com.baomidou.mybatisplus.extension.injector.methods.Upsert;
+import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
+import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.apache.ibatis.type.JdbcType;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+
+import javax.sql.DataSource;
+import java.util.List;
+
+/**
+ * Mybatis Plus Config
+ *
+ * @author Caratacus
+ * @since 2017/4/1
+ */
+@Configuration
+@MapperScan("com.baomidou.mybatisplus.test.phoenix.mapper")
+public class MybatisPlusConfig {
+
+    @Bean("mybatisSqlSession")
+    public SqlSessionFactory sqlSessionFactory(DataSource dataSource, GlobalConfig globalConfig) throws Exception {
+        MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
+        /* 数据源 */
+        sqlSessionFactory.setDataSource(dataSource);
+        /* xml扫描 */
+        sqlSessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
+            .getResources("classpath:/mapper/*.xml"));
+        /* 扫描 typeHandler */
+        MybatisConfiguration configuration = new MybatisConfiguration();
+        configuration.setJdbcTypeForNull(JdbcType.NULL);
+        /* 驼峰转下划线 */
+        configuration.setMapUnderscoreToCamelCase(true);
+        /* 乐观锁插件 */
+        configuration.addInterceptor(new OptimisticLockerInterceptor());
+        /* map 下划线转驼峰 */
+        configuration.setObjectWrapperFactory(new MybatisMapWrapperFactory());
+        sqlSessionFactory.setConfiguration(configuration);
+        sqlSessionFactory.setGlobalConfig(globalConfig);
+        return sqlSessionFactory.getObject();
+    }
+
+    @Bean
+    public GlobalConfig globalConfig() {
+        GlobalConfig conf = new GlobalConfig();
+        conf.setDbConfig(new GlobalConfig.DbConfig()
+            .setColumnFormat("`%s`"));
+        DefaultSqlInjector phoenixSqlInjector = new DefaultSqlInjector() {
+            /**
+             * 注入自定义全局方法
+             */
+            @Override
+            public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
+                List<AbstractMethod> methodList = super.getMethodList(mapperClass);
+                methodList.add(new Upsert());
+                return methodList;
+            }
+        };
+        conf.setSqlInjector(phoenixSqlInjector);
+        return conf;
+    }
+}

+ 29 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/phoenix/entity/PhoenixTestInfo.java

@@ -0,0 +1,29 @@
+package com.baomidou.mybatisplus.test.phoenix.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+/**
+ * @author fly
+ * @date 2019/5/22 17:52
+ * description: phoenix hbase TEST_INFO table
+ */
+@Data
+@Accessors(chain = true)
+@TableName("test_info")
+public class PhoenixTestInfo {
+
+    /**
+     * Phoenix主键Mybatis不支持自增,需要插入传入或者设置key generator
+     */
+    private Integer id;
+
+    private String name;
+    private String phone;
+    private String position;
+    private String department;
+    private String company;
+    private String fileName;
+    private String posDepCom;
+}

+ 21 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/phoenix/mapper/PhoenixTestInfoMapper.java

@@ -0,0 +1,21 @@
+package com.baomidou.mybatisplus.test.phoenix.mapper;
+
+import com.baomidou.mybatisplus.test.phoenix.PhoenixBaseMapper;
+import com.baomidou.mybatisplus.test.phoenix.entity.PhoenixTestInfo;
+import org.apache.ibatis.annotations.Insert;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * @author fly
+ * @date 2019/5/22 17:55
+ * description:
+ */
+public interface PhoenixTestInfoMapper extends PhoenixBaseMapper<PhoenixTestInfo> {
+
+        @Insert(
+                "UPSERT INTO TEST_INFO " +
+                "(ID, NAME) " +
+                "VALUES(#{t.id},#{t.name})"
+        )
+        void addTestInfo(@Param("t") PhoenixTestInfo t);
+}

+ 9 - 0
mybatis-plus/src/test/resources/hbase-site.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--Autogenerated by Cloudera Manager-->
+<configuration>
+  <property>
+    <name>phoenix.schema.isNamespaceMappingEnabled</name>
+    <value>true</value>
+  </property>
+</configuration>

+ 9 - 0
mybatis-plus/src/test/resources/phoenix/spring-test-phoenix.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns="http://www.springframework.org/schema/beans"
+       xmlns:context="http://www.springframework.org/schema/context"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
+
+    <context:component-scan base-package="com.baomidou.mybatisplus.test.phoenix.config"/>
+</beans>

+ 17 - 0
mybatis-plus/src/test/resources/phoenix/test_info.ddl.sql

@@ -0,0 +1,17 @@
+DROP SCHEMA TEST;
+CREATE SCHEMA TEST;
+USE TEST;
+
+DROP TABLE IF EXISTS TEST_INFO;
+CREATE TABLE TEST_INFO (
+  id INTEGER NOT NULL PRIMARY KEY,
+  name VARCHAR,
+  phone VARCHAR,
+  position VARCHAR,
+  department VARCHAR,
+  company VARCHAR,
+  file_name VARCHAR,
+  pos_dep_com VARCHAR,
+  gmt_updated DATE,
+  gmt_create DATE
+);