1. 程式人生 > 實用技巧 >HBase~hbase-shaded-client解決包衝突問題

HBase~hbase-shaded-client解決包衝突問題

對於springboot操作hbase來說,我們可以選擇官方的依賴包hbase-client,但這個包的google類庫很多時候會和你的專案裡的google類庫衝突,最後就是你的程式缺少類而無法啟動,解決這個問題的方法很多,而最徹底的就是自己封裝一個shade包,或者使用人家封裝好的shade包,shade就是maven裡的一個重寫包的外掛,非常好用。

依賴包

之前的原始包

  <dependency>
    <groupId>org.apache.hbase</groupId>
    <artifactId>hbase-client</artifactId>
    <version>1.4.6</version>
  /dependency>

使用shade包

  <dependency>
    <groupId>org.apache.hbase</groupId>
    <artifactId>hbase-shaded-client</artifactId>
    <version>1.3.1</version>
  </dependency>

封裝一下hbase的操作類

@Component
public class HBaseTemplate implements HBaseOperations {

    private static final Logger logger = LoggerFactory.getLogger(HBaseTemplate.class);

    @Autowired
    private HBaseAdmin hBaseAdmin;

    @Autowired
    private Connection connection;

    /**
     * 判斷表名是否存在
     *
     * @param tableName 表名 String ,注意這裡區分大小寫
     * @return
     */
    @Override
    public boolean tableExists(String tableName) {
        Table table = null;
        boolean tableExistsFlag = false;
        try {
            table = connection.getTable(TableName.valueOf(tableName));
            tableExistsFlag = hBaseAdmin.tableExists(table.getName());
        } catch (IOException e) {
            logger.error("IOException : {}", e.getMessage());
            e.printStackTrace();
        } finally {
            closeTable(table);
        }
        return tableExistsFlag;
    }

    /**
     * 通過表名和rowKey獲取資料,獲取一條資料
     *
     * @param tableName 表名
     * @param rowKeyVar rowKey 泛型 可支援多種型別{String,Long,Double}
     * @return Result 型別
     */
    @Override
    public <T> Result queryByTableNameAndRowKey(String tableName, T rowKeyVar) {

        Assert.notNullBatch(tableName, rowKeyVar);
        Assert.hasLength(tableName);

        boolean tableExists = tableExists(tableName);
        if (!tableExists) {
            logger.info("{}" + ExceptionMessage.TABLE_NOT_EXISTS_MSG, tableName);
            return null;
        }

        byte[] rowKey = checkType(rowKeyVar);
        Result result = null;
        Table table = null;
        try {
            table = connection.getTable(TableName.valueOf(tableName));
            Get get = new Get(rowKey);
            result = table.get(get);
        } catch (IOException e) {
            logger.error("IOException : {}", e.getMessage());
            e.printStackTrace();
        } finally {
            closeTable(table);
        }
        return result;
    }

    /**
     * 自定義查詢
     *
     * @param tableName 表名
     * @param getList   請求體
     * @return Result型別
     */
    @Override
    public Result[] query(String tableName, List<Get> getList) {

        Assert.notNullBatch(tableName, getList);
        Assert.hasLength(tableName);

        boolean tableExists = tableExists(tableName);
        if (!tableExists) {
            logger.info("{}" + ExceptionMessage.TABLE_NOT_EXISTS_MSG, tableName);
            return null;
        }

        Table table = null;
        Result[] result = null;
        try {
            table = connection.getTable(TableName.valueOf(tableName));
            result = table.get(getList);
        } catch (IOException e) {
            logger.error("query error , message:{}", e.getMessage());
            e.printStackTrace();
        } finally {
            closeTable(table);
        }
        return result;
    }


    /**
     * 傳入一個泛型V 判斷基本型別,返回對應的byte陣列
     *
     * @param rowKeyVar 泛型rowKey
     * @param <V>       泛型
     * @return 返回格式化後的位元組陣列
     */
    private <V> byte[] checkType(V rowKeyVar) {
        byte[] rowKey = new byte[0];
        //判斷T的型別
        String rowKeyType = rowKeyVar.getClass().getTypeName();
        logger.info("rowKey Type is : {}", rowKeyType);
        if (String.class.getName().equals(rowKeyType)) {
            rowKey = Bytes.toBytes((String) rowKeyVar);
        }
        if (Long.class.getName().equals(rowKeyType)) {
            rowKey = Bytes.toBytes((Long) rowKeyVar);
        }
        if (Double.class.getName().equals(rowKeyType)) {
            rowKey = Bytes.toBytes((Double) rowKeyVar);
        }
        if (Integer.class.getName().equals(rowKeyType)) {
            rowKey = Bytes.toBytes((Integer) rowKeyVar);
        }

        return rowKey;
    }

    /**
     * 關閉連線
     *
     * @param table 表名
     */
    private void closeTable(Table table) {
        if (table != null) {
            try {
                table.close();
            } catch (IOException e) {
                logger.error("close table {} error {}", table.getName(), e.getMessage());
                e.printStackTrace();
            }
        } else {
            logger.info("table is null");
        }
    }

    /**
     * 建立一張表
     *
     * @param tableName  表名
     * @param familyName 列族名
     */
    @Override
    public void createTable(String tableName, String... familyName) {

        Assert.notNullBatch(tableName, familyName);
        Assert.hasLength(tableName);

        TableName tableNameVar = TableName.valueOf(tableName);
        if (!tableExists(tableName)) {
            HTableDescriptor hTableDescriptor = new HTableDescriptor(tableNameVar);
            for (int i = 0; i < familyName.length; i++) {
                HColumnDescriptor hColumnDescriptor = new HColumnDescriptor(familyName[i]);
                hTableDescriptor.addFamily(hColumnDescriptor);
            }
            try {
                hBaseAdmin.createTable(hTableDescriptor);
            } catch (IOException e) {
                logger.error("create failed , Exception: {}", e.getMessage());
                e.printStackTrace();
            }
        } else {
            throw new IllegalArgumentException(ExceptionMessage.TABLE_ALREADY_EXISTS_MSG);
        }
    }

    /**
     * 新增一條資料
     *
     * @param tableName  目標資料表
     * @param rowName    rowKey
     * @param familyName 列族名
     * @param qualifier  列名
     * @param data       位元組陣列型別的資料
     */
    @Override
    public void put(String tableName, String rowName, String familyName, String qualifier, byte[] data) {

        Assert.notNullBatch(tableName, rowName, familyName, qualifier);
        Assert.hasLengthBatch(tableName, rowName, familyName, qualifier);

        Table table = null;
        if (tableExists(tableName)) {
            try {
                table = connection.getTable(TableName.valueOf(tableName));
                Put put = new Put(Bytes.toBytes(rowName));
                put.addColumn(Bytes.toBytes(familyName), Bytes.toBytes(qualifier), data);
                table.put(put);
            } catch (IOException e) {
                logger.error("data put error,message: {}", e.getMessage());
                e.printStackTrace();
            } finally {
                closeTable(table);
            }
        } else {
            throw new IllegalArgumentException(ExceptionMessage.TABLE_NOT_EXISTS_MSG);
        }
    }

    /**
     * 批量插入資料
     *
     * @param tableName 表名
     * @param putList   put集合
     */
    @Override
    public void putBatch(String tableName, List<Put> putList) {

        Assert.notNull(putList);
        Assert.hasLength(tableName);

        Table table = null;
        if (tableExists(tableName)) {
            try {
                table = connection.getTable(TableName.valueOf(tableName));
                table.put(putList);
            } catch (IOException e) {
                logger.error("data put error, message:{}", e.getMessage());
                e.printStackTrace();
            } finally {
                closeTable(table);
            }
        } else {
            throw new IllegalArgumentException(ExceptionMessage.TABLE_NOT_EXISTS_MSG);
        }
    }

    /**
     * 刪除一個列族下的資料
     *
     * @param tableName  目標資料表
     * @param rowName    rowKey
     * @param familyName 列族名
     */
    @Override
    public void delete(String tableName, String rowName, String familyName) {
        delete(tableName, rowName, familyName, null);
    }

    /**
     * 刪除某個列下的資料
     *
     * @param tableName  目標資料表
     * @param rowName    rowKey
     * @param familyName 列族名
     * @param qualifier  列名
     */
    @Override
    public void delete(String tableName, String rowName, String familyName, String qualifier) {

        Assert.notNullBatch(tableName, rowName, familyName);
        Assert.hasLengthBatch(tableName, rowName, familyName);

        Table table = null;
        try {
            table = connection.getTable(TableName.valueOf(tableName));
            Delete delete = new Delete(rowName.getBytes());
            if (qualifier != null) {
                delete.addColumn(familyName.getBytes(), qualifier.getBytes());
            }
            table.delete(delete);
        } catch (IOException e) {
            logger.error("data delete error, message:{}", e.getMessage());
            e.printStackTrace();
        } finally {
            closeTable(table);
        }
    }

    /**
     * 批量刪除資料
     *
     * @param tableName  表名
     * @param deleteList 需要刪除的資料
     */
    @Override
    public void deleteBatch(String tableName, List<Delete> deleteList) {

        Assert.notNull(tableName);
        Assert.hasLength(tableName);

        Table table = null;
        try {
            table = connection.getTable(TableName.valueOf(tableName));
            table.delete(deleteList);
        } catch (IOException e) {
            logger.error("data delete error, message:{}", e.getMessage());
            e.printStackTrace();
        } finally {
            closeTable(table);
        }
    }

    /**
     * 通過scan查詢資料
     *
     * @param tableName 表名
     * @param scan      scan
     * @return 返回 ResultScanner
     */
    @Override
    public ResultScanner queryByScan(String tableName, Scan scan) {

        Assert.notNullBatch(tableName, scan);
        Assert.hasLength(tableName);

        ResultScanner resultScanner = null;
        Table table = null;
        try {
            table = connection.getTable(TableName.valueOf(tableName));
            resultScanner = table.getScanner(scan);
        } catch (IOException e) {
            logger.error("query error, message:", e.getMessage());
            e.printStackTrace();
        } finally {
            closeTable(table);
        }
        return resultScanner;
    }

    /**
     * 刪除表
     *
     * @param tableName 表名稱
     */
    @Override
    public void dropTable(String tableName) {
        boolean tableExists = tableExists(tableName);
        if (tableExists) {
            try {
                hBaseAdmin.disableTable(tableName);
                hBaseAdmin.deleteTable(tableName);
                logger.info("table {} delete successfully", tableName);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            logger.info("table {} is not exists", tableName);
        }
    }
}

測試put操作

不使用shade包,在put操作時會有錯誤,在scan類裡的newLimit位置會出現錯誤

    /**
     * 插入一條記錄
     */
    @Test
    public void putTest() {
        String rowKey = UUID.randomUUID().toString();
        hBaseDao.put(TABLE_NAME, rowKey, COLUMN_FAMILY, "name", Bytes.toBytes("testData"));
    }

操作後截圖