最近在做Hbase项目,考虑到整体Hbase操作采用API的方式比较繁琐,简单封装了一下,项目使用SpringCould构建,涉及zookeeper,和spring security构建的比较复杂,所以就甩点干货.
annotation涉及两个:
FamilyColumn,用来定义列族名称,默认列族为"f"
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FamilyColumn {
String value() default "f";
}
Qualifier用来定义JavaBean的索引字段
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Qualifier {
}
工具类驼峰转下划线,主要用来将javabean对象的驼峰映射为下划线,如:SysUser会自动映射为sys_user方式,用来统一映射hbase表
CamelUnderlineConvert
public class CamelUnderlineConvert {
public static final char UNDERLINE = '_';
/**
* 驼峰格式字符串转换为下划线格式字符串
*
* @param param
* @return
*/
public static String camelToUnderline(String param) {
if (param == null || "".equals(param.trim())) {
return "";
}
int len = param.length();
StringBuilder sb = new StringBuilder(len);
for (int i = 0; i < len; i++) {
char c = param.charAt(i);
if (i !=0 && Character.isUpperCase(c)) {
sb.append(UNDERLINE);
sb.append(Character.toLowerCase(c));
} else {
sb.append(Character.toLowerCase(c));
}
}
return sb.toString();
}
/**
* 下划线格式字符串转换为驼峰格式字符串
*
* @param param
* @return
*/
public static String underlineToCamel(String param) {
if (param == null || "".equals(param.trim())) {
return "";
}
int len = param.length();
StringBuilder sb = new StringBuilder(len);
for (int i = 0; i < len; i++) {
char c = param.charAt(i);
if (c == UNDERLINE) {
if (++i < len) {
sb.append(Character.toUpperCase(param.charAt(i)));
}
} else {
sb.append(c);
}
}
return sb.toString();
}
}
BixiAnnotationUtils,主要是用来解析annotation
import java.lang.reflect.Field;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import com.tk.bixi.annotation.Qualifier;
public class BixiAnnotationUtils extends AnnotationUtils{
@Nullable
public static String findQualifierAnnotation(Class<?> clazz) {
Assert.notNull(clazz, "Class must not be null");
Field [] fields = clazz.getDeclaredFields();
for (Field field : fields) {
Qualifier qualifier = field.getAnnotation(Qualifier.class);
if(qualifier!=null) {
return CamelUnderlineConvert.camelToUnderline(field.getName());
}
}
return null;
}
}
新增查询封装
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.ResultScanner;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.client.Table;
import org.apache.hadoop.hbase.filter.FilterList;
import org.apache.hadoop.hbase.filter.PageFilter;
import org.apache.hadoop.hbase.util.Bytes;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import com.tk.bixi.annotation.FamilyColumn;
import com.tk.bixi.utils.BixiAnnotationUtils;
import com.tk.bixi.utils.CamelUnderlineConvert;
@Service
@RefreshScope
public class HBaseService<T> {
/**
* 获取hbase连接
*/
@Autowired
org.apache.hadoop.hbase.client.Connection hbaseConnection;
/**
* 名字空间定义
*/
@Value("${hbase.namespace}")
private String nameSpace;
/**
* 分页大小
*/
@Value("${hbase.pagesize}")
private Integer pageSize;
/**
* 查询pojo,比尴尬的是因为用了倒序,结果起始数据不包含在结果集中
* @param startRowkey 开始行号
* @param stopRowkey 结束行号
* @param className pojo类
* @param filterList 自定义过滤
* @return
* @throws InstantiationException
* @throws IllegalAccessException
* @throws InvocationTargetException
* @throws IOException
*/
public List<T> getRowKey(String startRowkey, String stopRowkey, Class<T> className,FilterList filterList) throws InstantiationException, IllegalAccessException, InvocationTargetException, IOException {
if(null!=filterList&&filterList.size()>0) {
filterList.addFilter(new PageFilter(pageSize));
}else {
filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL);
filterList.addFilter(new PageFilter(pageSize));
}
Scan scan = new Scan();
scan.setFilter(filterList);
scan.setReversed(true);
scan.withStartRow(Bytes.toBytes(stopRowkey));
scan.withStopRow(Bytes.toBytes(startRowkey));
Table table = hbaseConnection.getTable(TableName.valueOf(nameSpace+":"+CamelUnderlineConvert.camelToUnderline(className.getSimpleName())));
ResultScanner scanners = table.getScanner(scan);
List<T> listResult = new ArrayList<>();
for (Result result : scanners) {
T obj = className.newInstance();
String rowkey = BixiAnnotationUtils.findQualifierAnnotation(obj.getClass());
org.apache.commons.beanutils.BeanUtils.setProperty(obj, rowkey,new String( result.getRow()));
Cell[] cells = result.rawCells();
for (Cell c : cells) {
String rowName = new String(CellUtil.cloneQualifier(c));
String value = new String(CellUtil.cloneValue(c));
org.apache.commons.beanutils.BeanUtils.setProperty(obj, rowName, value);
}
listResult.add(obj);
}
return listResult;
}
/**
*
* @param record 插入指hbase数据
* @throws IllegalAccessException
* @throws InvocationTargetException
* @throws NoSuchMethodException
* @throws IOException
*/
public void add(T record)
throws IllegalAccessException, InvocationTargetException, NoSuchMethodException, IOException {
String tableNameStr = CamelUnderlineConvert.camelToUnderline(record.getClass().getSimpleName());
TableName tableName = TableName.valueOf(nameSpace+":"+tableNameStr);
FamilyColumn FamilyColumn = BixiAnnotationUtils.findAnnotation(record.getClass(), FamilyColumn.class);
String columnFamily = "f";
if (FamilyColumn != null) {
columnFamily = FamilyColumn.value();
}
Field[] fields = record.getClass().getDeclaredFields();
String rowName = BixiAnnotationUtils.findQualifierAnnotation(record.getClass());
Put put = new Put(Bytes.toBytes(BeanUtils.getSimpleProperty(record, rowName)));
Table table = hbaseConnection.getTable(tableName);
for (Field field : fields) {
String columnName = CamelUnderlineConvert.camelToUnderline(field.getName());
if(rowName.equals(columnName)) continue;
put.addColumn(Bytes.toBytes(columnFamily),Bytes.toBytes(columnName),Bytes.toBytes(BeanUtils.getSimpleProperty(record, field.getName())));
}
table.put(put);
}
}
写一个pojo类测试
import com.tk.bixi.annotation.FamilyColumn;
import com.tk.bixi.annotation.Qualifier;
@FamilyColumn
public class Person {
@Qualifier
private String rowkey;
private String name;
public String getName() {
return name;
}
public String getRowkey() {
return rowkey;
}
public void setRowkey(String rowkey) {
this.rowkey = rowkey;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
private Integer age;
}
写一个Controller测试一下
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.tk.bixi.service.HBaseService;
import com.tk.bixi.service.Person;
import com.tk.bixi.utils.Msg;
import com.tk.bixi.utils.ResultUtil;
@RestController
public class TestController {
@Autowired
private HBaseService<Person> hbaseTemplate;
public static Integer rowKey = 10;
@RequestMapping("/person/add/{name}/{age}")
public Msg add(@PathVariable("name") String name,@PathVariable("age") Integer age) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException, IOException {
Person person = new Person();
rowKey++;
person.setRowkey("rowkey"+rowKey);
person.setName(name);
person.setAge(age);
hbaseTemplate.add(person);
return ResultUtil.success();
}
@RequestMapping("/person/{rowkey}/{endrowkey}")
public Msg add(@PathVariable("rowkey") String rowkey,@PathVariable("endrowkey") String endrowkey) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException, IOException, InstantiationException {
List<Person> persons = hbaseTemplate.getRowKey(rowkey, endrowkey, Person.class,null);
System.out.println("persons:"+persons.size());
return ResultUtil.success(persons);
}
}
hbase shell查看
根据rowkey查询