HBASE-JAVA-API

Hbse-Java Api 基础知识
初始化
Configuration conf = HBaseConfiguration.create();
conf.set("hbase.zookeeper.quorum", "master:2181,node1:2181,node2:2181");
conn = ConnectionFactory.createConnection(conf);
admin = conn.getAdmin();

这段代码初始化了一个连接到Apache HBase数据库的过程。以下是每行代码的作用:

  1. Configuration conf = HBaseConfiguration.create();:创建了一个新的HBase配置对象。

  2. conf.set("hbase.zookeeper.quorum", "master:2181,node1:2181,node2:2181");:设置了HBase用于协调的ZooKeeper群集服务器。在这种情况下,群集服务器是"master:2181,node1:2181,node2:2181"。群集服务器字符串的格式为主机名:端口号,可以使用逗号将多个服务器分隔开。

  3. conn = ConnectionFactory.createConnection(conf);:使用步骤1中创建的配置对象创建了一个到HBase数据库的新连接。

  4. admin = conn.getAdmin();:获取了HBase的Admin接口的实例,该接口用于对HBase数据库执行管理操作,例如创建表、添加列族等。

    为什么要创建配置对象

    在使用Apache HBase数据库时,我们需要配置一些参数,例如ZooKeeper的连接信息、HBase的数据存储路径、缓存大小等等。为了方便地管理这些参数,HBase提供了一个Configuration类,用于存储和管理这些参数。

    在代码中创建一个Configuration对象可以帮助我们将HBase的配置参数集中在一起,并将它们作为参数传递给其他HBase API方法,以便在连接到HBase数据库时使用这些参数。这样可以提高代码的可读性和维护性,使得修改配置变得更加方便和容易。

TableName.valueOf

TableName.valueOf()是HBase API中的一个静态方法,它将表名表示为一个字节数组(byte array)或字符串(String)转换为TableName对象。在HBase中,表名是唯一的标识符,用于指定要执行操作的表。

使用TableName.valueOf()方法可以将表名从字符串或字节数组转换为一个TableName对象,以便在API方法中使用表名参数时进行类型检查,防止出现拼写错误或其他错误。

例如,以下代码将字符串"mytable"转换为TableName对象:

TableName tableName = TableName.valueOf("mytable");

我们可以使用这个TableName对象来执行操作,例如在表中插入数据、获取数据等。

HTableDescriptor

HTableDescriptor是HBase API中的一个类,它用于描述HBase表的结构信息,例如表名、列族(column family)、表的最大版本数、是否开启WAL(Write-Ahead Logging)等。

HTableDescriptor对象可以通过HBaseAdmin对象的createTable方法来创建表,也可以通过HBaseAdmin对象的getTableDescriptor方法来获取已经存在的表的结构信息。

例如,以下代码创建了一个名为"mytable"的表,并定义了一个名为"cf1"的列族:

HBaseAdmin admin = new HBaseAdmin(conf);
HTableDescriptor tableDescriptor = new HTableDescriptor(TableName.valueOf("mytable"));
HColumnDescriptor columnDescriptor = new HColumnDescriptor("cf1");
tableDescriptor.addFamily(columnDescriptor);
admin.createTable(tableDescriptor);

在上述代码中,我们首先创建了一个HBaseAdmin对象,然后创建了一个HTableDescriptor对象,将其设置为表名为"mytable",然后创建了一个名为"cf1"的列族,并将其添加到表描述符中。最后,我们使用createTable方法创建表。

问题一:为什么列族不要做字节转化

虽然HBase中的数据是以字节数组的形式存储的,但是在HBase API中,通常使用字符串类型来表示列族名称,因为这样更方便进行编程和使用。

另外,HBase API中的一些方法接受的参数类型是字符串类型,而不是字节数组类型。例如,HColumnDescriptor类的构造函数和HTableDescriptor类的addFamily方法都需要传递列族名称作为字符串类型。

因此,我们通常建议在HBase API中使用字符串类型来表示列族名称,而不是字节数组类型。这样可以更方便地进行编程和使用,并且可以避免由于字节数组转换而引起的类型错误和数据截断问题。

问题二:为什么表名就要做字节转化

虽然表名可以使用字符串类型来表示,但是在HBase中,表名通常使用字节数组类型表示,因为HBase中的数据是以字节数组的形式存储的。此外,使用字节数组类型可以更方便地进行编程和使用,因为HBase API中的一些方法接受的参数类型是字节数组类型,例如HTableDescriptor类的构造函数和HBaseAdmin类的tableExists方法。

因此,在HBase API中,我们通常建议使用字节数组类型来表示表名,而不是字符串类型。这样可以更方便地进行编程和使用,并且可以避免由于类型错误和数据截断问题引起的错误。当需要将表名转换为字符串类型时,可以使用Bytes.toString方法将字节数组转换为字符串,例如:

byte[] tableNameBytes = Bytes.toBytes("mytable");
String tableNameString = Bytes.toString(tableNameBytes);

HTableDescriptor还可以用于修改表的结构信息,例如添加或删除列族、修改表的最大版本数等。

获取当前HBase集群中的所有表和列族名称
	HTableDescriptor[] hTableDescriptors = admin.listTables();
        for (HTableDescriptor descriptor : hTableDescriptors) {
            System.out.println(descriptor.getNameAsString());
            HColumnDescriptor[] families = descriptor.getColumnFamilies();
            for (HColumnDescriptor cf : families) {
                System.out.println(cf.getNameAsString());
            }
            System.out.println("####################");
        }

这段代码使用HBase的Java API获取当前HBase集群中的所有表名和列族名,并在控制台输出。

具体解释如下:

  1. HTableDescriptor[] hTableDescriptors = admin.listTables();:通过HBase的Admin对象admin,调用listTables()方法获取当前HBase集群中所有表的HTableDescriptor对象数组,并将数组赋值给hTableDescriptors变量。

  2. for (HTableDescriptor descriptor : hTableDescriptors):遍历hTableDescriptors数组,每次循环取出一个HTableDescriptor对象,并将其赋值给descriptor变量。

  3. System.out.println(descriptor.getNameAsString());:输出当前表的名称,使用getNameAsString()方法获取表名并在控制台打印输出。

  4. HColumnDescriptor[] families = descriptor.getColumnFamilies();:通过descriptor对象的getColumnFamilies()方法获取表中的所有列族,并将数组赋值给families变量。

  5. for (HColumnDescriptor cf : families):遍历families数组,每次循环取出一个HColumnDescriptor对象,并将其赋值给cf变量。

  6. System.out.println(cf.getNameAsString());:输出当前列族的名称,使用getNameAsString()方法获取列族名并在控制台打印输出。

  7. System.out.println("####################");:输出分隔符,用于区分不同表的输出结果。

综上,这段代码用于获取当前HBase集群中的所有表和列族名称,并通过控制台输出。这对于进行HBase开发和调试非常有帮助。

修改HBase表结构
		TableName new_t1_table_name = TableName.valueOf("new_t1");
        // 要想对表结构进行修改,得先获得原有的结构
        HTableDescriptor tableDescriptor = admin.getTableDescriptor(new_t1_table_name);
        HColumnDescriptor[] columnFamilies = tableDescriptor.getColumnFamilies();
        for (HColumnDescriptor cf : columnFamilies) {
            if ("cf1".equals(cf.getNameAsString())) {
                cf.setVersions(2, 8);
            }
        }
        admin.modifyTable(new_t1_table_name, tableDescriptor);

这段代码使用HBase的Java API修改表结构,将表t1cf1列族的版本数设置为2到8之间,并将修改后的表结构更新到HBase集群中。

具体解释如下:

  1. TableName new_t1_table_name = TableName.valueOf("new_t1");:定义一个新表名new_t1_table_name,使用TableName.valueOf()方法将表名字符串转换为TableName对象。

  2. HTableDescriptor tableDescriptor = admin.getTableDescriptor(new_t1_table_name);:通过admin对象的getTableDescriptor()方法获取表new_t1HTableDescriptor对象,并将其赋值给tableDescriptor变量。

  3. HColumnDescriptor[] columnFamilies = tableDescriptor.getColumnFamilies();:通过tableDescriptor对象的getColumnFamilies()方法获取表中的所有列族,并将数组赋值给columnFamilies变量。

  4. for (HColumnDescriptor cf : columnFamilies):遍历columnFamilies数组,每次循环取出一个HColumnDescriptor对象,并将其赋值给cf变量。

  5. if ("cf1".equals(cf.getNameAsString())) { cf.setVersions(2, 8); }:判断当前列族cf是否为cf1,如果是,则调用setVersions()方法将该列族的版本数设置为2到8之间。

  6. admin.modifyTable(new_t1_table_name, tableDescriptor);:通过admin对象的modifyTable()方法,将修改后的表结构更新到HBase集群中。

综上,这段代码用于修改HBase表结构,将表t1cf1列族的版本数设置为2到8之间,并将修改后的表结构更新到HBase集群中。

Put方法(插入)
TableName new_t1_table_name = TableName.valueOf("new_t1");
        Table new_t1 = conn.getTable(new_t1_table_name);
        // 向new_t1表的rowkey为rk1这一行数据的cf1列簇下插入一列数据,列名为id,值为001
        Put put = new Put("rk1".getBytes());
        put.addColumn("cf1".getBytes(), "id".getBytes(), "001".getBytes());
        put.addColumn("cf1".getBytes(), "name".getBytes(), "zhangsan".getBytes());
        new_t1.put(put);

这段代码使用HBase的Java API向表new_t1中插入一行数据,行键为rk1,列族为cf1,列名为idname,值分别为001zhangsan

具体解释如下:

  1. TableName new_t1_table_name = TableName.valueOf("new_t1");:定义一个新表名new_t1_table_name,使用TableName.valueOf()方法将表名字符串转换为TableName对象。

  2. Table new_t1 = conn.getTable(new_t1_table_name);:通过conn对象的getTable()方法获取表new_t1Table对象,并将其赋值给new_t1变量。

  3. Put put = new Put("rk1".getBytes());:创建一个Put对象put,将行键设置为rk1

  4. put.addColumn("cf1".getBytes(), "id".getBytes(), "001".getBytes());:向put对象中添加一个cf1:id的列,值为001

  5. put.addColumn("cf1".getBytes(), "name".getBytes(), "zhangsan".getBytes());:向put对象中添加一个cf1:name的列,值为zhangsan

  6. new_t1.put(put);:通过new_t1对象的put()方法将put对象中的数据插入到表new_t1中。

综上,这段代码用于向HBase表中插入一行数据,行键为rk1,列族为cf1,列名为idname,值分别为001zhangsan

问题一:上面的put的作用是什么

put对象用于将数据插入到HBase表中,其中包含一行数据的相关信息,包括行键、列族、列名和列值等。在这段代码中,通过put对象将一行数据插入到表new_t1中,行键为rk1,列族为cf1,列名分别为id和name,值分别为001和zhangsan。

在HBase中,每一行数据的唯一标识是行键,而每一行数据可以包含多个列族,每个列族又可以包含多个列。在插入数据时,需要指定行键和至少一个列族和对应的列名和值,才能将数据成功插入到表中。put对象的作用就是封装这些数据,并通过Table对象的`put()`方法将其插入到表中。

问题二:那put对象里到底存的是什么

`Put`对象存储了一行数据的信息,包括行键、列族、列名和列值等。在HBase中,每个数据单元可以通过行键、列族和列名来唯一确定。因此,`Put`对象中存储的数据包括:

1. 行键(rowkey):用于唯一标识一行数据,必须是字节数组类型。
2. 列族(column family):用于组织列的集合,通常具有相同的访问控制权限和生命周期。必须是字节数组类型。
3. 列名(column qualifier):用于唯一标识一个列,必须是字节数组类型。
4. 值(value):对应的列的值,必须是字节数组类型。

`Put`对象中可以包含多个列,每个列都需要指定列族、列名和对应的值,才能插入到HBase表中。在插入数据时,可以通过多次调用`put.addColumn()`方法向`Put`对象中添加多个列。

问题三:put(put)这段代码详解

put(put)方法是Table类中的一个方法,用于向HBase表中插入一行数据。它的参数是一个Put对象,表示要插入的数据。
示例代码如下:
// 创建一个Put对象
Put put = new Put(Bytes.toBytes("rowkey"));
// 向Put对象中添加列
put.addColumn(Bytes.toBytes("cf"), Bytes.toBytes("col1"), Bytes.toBytes("value1"));
put.addColumn(Bytes.toBytes("cf"), Bytes.toBytes("col2"), Bytes.toBytes("value2"));
// 将Put对象插入到表中
table.put(put);
在上述代码中,我们首先创建一个新的Put对象,并使用addColumn()方法向其添加两个列。接着,使用table.put(put)方法将Put对象插入到表中。

需要注意的是,put(put)方法可以用于一次性插入多行数据,只需要将多个Put对象依次传入即可。这样可以提高数据插入的效率。
conn.getTable

conn.getTable()是HBase客户端API中的一个方法,用于获取一个Table对象,以便对HBase表中的数据进行操作。

具体来说,conn是一个Connection对象,表示与HBase集群的连接。使用conn.getTable()方法可以获取一个指定名称的表的Table对象。例如,以下代码获取了名为my_table的HBase表的Table对象:

Connection conn = ConnectionFactory.createConnection(conf);
TableName tableName = TableName.valueOf("my_table");
Table table = conn.getTable(tableName);

在上述代码中,conf是一个Configuration对象,表示HBase集群的配置信息。Connection对象通过ConnectionFactory.createConnection(conf)方法创建,用于与HBase集群建立连接。TableName.valueOf("my_table")方法创建一个TableName对象,表示要操作的HBase表的名称。最后,通过conn.getTable(tableName)方法获取一个名为my_table的HBase表的Table对象。

获取到Table对象后,就可以使用该对象操作HBase表中的数据,例如插入数据、修改数据、删除数据、查询数据等。

Get方法

Get方法是HBase Java客户端API提供的一个类,用于从HBase表中获取指定行键(row key)的数据。通过Get方法可以获取一行数据中所有的列族、列限定符和值,也可以根据需要只获取指定的列族、列限定符和值。

以下是一个示例的Get方法的实现代码:

Get get = new Get(Bytes.toBytes(rowKey));
get.addFamily(Bytes.toBytes(family));
get.addColumn(Bytes.toBytes(family), Bytes.toBytes(qualifier));

Result result = table.get(get);

在示例代码中,首先创建一个Get对象,并使用Bytes.toBytes(rowKey)方法将行键转换为字节数组,并将其传入Get对象的构造函数中。

然后,使用get.addFamily(Bytes.toBytes(family))方法设置要获取的列族,使用get.addColumn(Bytes.toBytes(family), Bytes.toBytes(qualifier))方法设置要获取的列族和列限定符。

最后,使用table.get(get)方法从HBase表中获取数据,并将返回的Result对象保存在result变量中。

需要注意的是,在使用Get方法时,应该根据具体的业务需求设置需要获取的列族和列限定符,以避免获取过多的数据导致性能下降。同时,还需要考虑异常处理、连接池维护等问题。

listCells()方法

在Apache HBase中,listCells()是HBase API中的一个方法,用于检索与给定行键相关联的所有单元格。该方法返回一个Result对象,其中包含行键、列族、列修饰符、时间戳和单元格值等单元格的详细信息。

以下是使用Java HBase API中的listCells()方法的示例代码:

// 创建HBase表连接
Configuration config = HBaseConfiguration.create();
Connection connection = ConnectionFactory.createConnection(config);

// 获取表对象
TableName tableName = TableName.valueOf("my_table");
Table table = connection.getTable(tableName);

// 创建Get对象,并设置要检索的行键
Get get = new Get(Bytes.toBytes("my_row_key"));

// 检索与行键相关联的所有单元格
Result result = table.get(get);

// 获取结果中的单元格列表
List<Cell> cells = result.listCells();

// 遍历单元格列表并打印单元格信息
for (Cell cell : cells) {
    byte[] family = CellUtil.cloneFamily(cell);
    byte[] qualifier = CellUtil.cloneQualifier(cell);
    byte[] value = CellUtil.cloneValue(cell);
    System.out.println("Column Family: " + Bytes.toString(family) 
        + " Column Qualifier: " + Bytes.toString(qualifier)
        + " Value: " + Bytes.toString(value));
}

// 关闭连接和表对象
table.close();
connection.close();

这段代码首先创建一个HBase表连接,然后获取表对象。然后,创建一个Get对象,并设置要检索的行键。接下来,使用table.get(get)方法检索与行键相关联的单元格,并使用result.listCells()方法获取单元格列表。最后,遍历单元格列表并获取每个单元格的列族、列修饰符和值等信息。

如果您使用上一条回复中提供的示例代码并将其运行在正确配置的HBase集群中,您可能会看到类似以下的输出:

Column Family: my_cf Column Qualifier: my_col Value: my_value

这个输出说明在表my_table中,行键为my_row_key的行中,列族为my_cf,列修饰符为my_col的单元格的值为my_value。如果该行中有多个单元格,listCells()方法将返回所有单元格,您可以遍历单元格列表并获取每个单元格的详细信息。

获取HBase表中某一行数据的过程中,对数据进行解析和提取的过程
     // 获取putOneData方法中写入的数据
        TableName new_t1_table_name = TableName.valueOf("new_t1");
        Table new_t1 = conn.getTable(new_t1_table_name);

        Get get = new Get("rk1".getBytes());
        // 通过rowkey可以获取某一条数据,该条数据中会包含n个cell单元格
        Result res = new_t1.get(get);

        // 获取每一条数据结构都固定的数据
        byte[] id = res.getValue("cf1".getBytes(), "id".getBytes());
        byte[] name = res.getValue("cf1".getBytes(), "name".getBytes());

        // 需要使用HBase提供的Bytes工具 将二进制数组转换成Java中的类型
        System.out.println(Bytes.toString(id));
        System.out.println(Bytes.toString(name));

        // 每一条数据结构不统一时,那如果还是按照上述方法获取数据,会导致有很多空值的出现
        List<Cell> cells = res.listCells();
        for (Cell cell : cells) {
            // 提取当前行数据每一个cell单元格
            String rk = Bytes.toString(CellUtil.cloneRow(cell));
            String cf = Bytes.toString(CellUtil.cloneFamily(cell));
            String qualifier = Bytes.toString(CellUtil.cloneQualifier(cell));
            String value = Bytes.toString(CellUtil.cloneValue(cell));
            System.out.println(rk + "," + cf + ":" + qualifier + " " + value);
        }

上述代码是一个Java程序,它通过HBase客户端API从HBase表中获取一行数据,并输出该行数据中的所有列。

具体的步骤如下:

  1. 创建一个new_t1表的Table对象,用于操作HBase表中的数据。这里使用conn.getTable()方法获取Table对象,参数是一个TableName对象,表示要操作的表名。
TableName new_t1_table_name = TableName.valueOf("new_t1");
Table new_t1 = conn.getTable(new_t1_table_name);
  1. 创建一个Get对象,表示要获取的数据的行键。这里使用new Get("rk1".getBytes())方法创建一个Get对象,参数是一个字节数组,表示行键。
Get get = new Get("rk1".getBytes());
  1. 使用Table.get()方法获取一行数据,返回一个Result对象。该对象中包含了该行数据的所有信息,包括列族、列名和列值等。
Result res = new_t1.get(get);
  1. Result对象中获取指定列的值。这里通过getValue()方法获取idname列的值,并使用Bytes.toString()方法将二进制数组转换为字符串类型。
byte[] id = res.getValue("cf1".getBytes(), "id".getBytes());
byte[] name = res.getValue("cf1".getBytes(), "name".getBytes());
System.out.println(Bytes.toString(id));
System.out.println(Bytes.toString(name));
  1. 获取该行数据中的所有列。这里使用listCells()方法获取所有的cell单元格,并使用CellUtil类提供的方法获取每个单元格的行键、列族、列名和列值。最后将这些信息输出到控制台。
List<Cell> cells = res.listCells();
for (Cell cell : cells) {
    String rk = Bytes.toString(CellUtil.cloneRow(cell));
    String cf = Bytes.toString(CellUtil.cloneFamily(cell));
    String qualifier = Bytes.toString(CellUtil.cloneQualifier(cell));
    String value = Bytes.toString(CellUtil.cloneValue(cell));
    System.out.println(rk + "," + cf + ":" + qualifier + " " + value);
}

需要注意的是,如果某一行数据中包含的列的数量不固定,可以使用上述方式获取该行数据中的所有列。如果列的数量固定,则可以直接使用getValue()方法获取指定列的值。

这段代码是在获取HBase表中某一行数据的过程中,对数据进行解析和提取的过程。具体来说,代码中假设已经使用putOneData方法将数据插入到名为new_t1的HBase表中,并且这些数据的行键为rk1。现在需要从表中读取该行数据,并对数据进行解析和提取。

首先,使用conn.getTable()方法获取名为new_t1的表的Table对象,然后使用Get对象设置行键为rk1,并调用new_t1.get(get)方法从表中获取该行数据的Result对象。

接下来,代码中调用res.getValue()方法从Result对象中提取通过列族cf1和列限定符id和name定义的两个列的值,并使用Bytes.toString()方法将获取的字节数组转换为字符串类型,并输出到控制台上。

然后,代码中使用res.listCells()方法获取该行数据中的所有Cell对象,并使用CellUtil提供的方法从Cell对象中提取行键、列族、列限定符和值,并输出到控制台上。

需要注意的是,如果一行数据中包含的列的数量和定义不一致,那么使用res.getValue()方法可能会导致空值的出现,因此在读取数据时需要使用res.listCells()方法获取所有的Cell对象,并逐个进行解析和提取
示例

读取students.txt数据 写入到HBase的stu表中,以每条数据的id作为rowkey stu表包含info列簇,info列簇分别包含了:id、name、age、gender、clazz五列

@Test
    // 读取students.txt数据 写入到HBase的stu表中,以每条数据的id作为rowkey
    // stu表包含info列簇,info列簇分别包含了:id、name、age、gender、clazz五列
    public void putStu() throws IOException {
        TableName stu_table_name = TableName.valueOf("stu");
        // 创建stu表
        if (!admin.tableExists(stu_table_name)) {
            HTableDescriptor hTableDescriptor = new HTableDescriptor(stu_table_name);
            HColumnDescriptor info = new HColumnDescriptor("info");
            hTableDescriptor.addFamily(info);
            admin.createTable(hTableDescriptor);
        }

        Table stu = conn.getTable(stu_table_name);

        // 读取文件,获取每一条数据
        BufferedReader br = new BufferedReader(new FileReader("./data/students.txt"));
        String line;
        while ((line = br.readLine()) != null) {
            String[] splits = line.split(",");
            String id = splits[0];
            String name = splits[1];
            String age = splits[2];
            String gender = splits[3];
            String clazz = splits[4];

            Put put = new Put(id.getBytes());
            put.addColumn("info".getBytes(), "id".getBytes(), id.getBytes());
            put.addColumn("info".getBytes(), "name".getBytes(), name.getBytes());
            put.addColumn("info".getBytes(), "age".getBytes(), age.getBytes());
            put.addColumn("info".getBytes(), "gender".getBytes(), gender.getBytes());
            put.addColumn("info".getBytes(), "clazz".getBytes(), clazz.getBytes());
            stu.put(put);
        }

    }

这段Java代码旨在将一个文本文件中的数据写入到HBase表中。下面是逐行解释:

TableName stu_table_name = TableName.valueOf("stu");
// 创建stu表
if (!admin.tableExists(stu_table_name)) {
    HTableDescriptor hTableDescriptor = new HTableDescriptor(stu_table_name);
    HColumnDescriptor info = new HColumnDescriptor("info");
    hTableDescriptor.addFamily(info);
    admin.createTable(hTableDescriptor);
}

这里创建一个stu表的TableName对象,并检查是否已经存在该表。如果表不存在,代码将创建一个HTableDescriptor对象,并设置列族为info,然后将列族添加到表描述符中。最后,使用admin.createTable(hTableDescriptor)方法创建表。

Table stu = conn.getTable(stu_table_name);

这里使用conn.getTable(stu_table_name)方法获取HBase连接中的stu表对象。

BufferedReader br = new BufferedReader(new FileReader("./data/students.txt"));
String line;
while ((line = br.readLine()) != null) {
    String[] splits = line.split(",");
    String id = splits[0];
    String name = splits[1];
    String age = splits[2];
    String gender = splits[3];
    String clazz = splits[4];

这里使用BufferedReader类和FileReader类从文件系统中读取名为students.txt的文本文件,并使用String.split()方法将每一行的数据分割成一个包含五个元素的字符串数组。然后,分别将五个元素赋值给idnameagegenderclazz变量。

Put put = new Put(id.getBytes());
put.addColumn("info".getBytes(), "id".getBytes(), id.getBytes());
put.addColumn("info".getBytes(), "name".getBytes(), name.getBytes());
put.addColumn("info".getBytes(), "age".getBytes(), age.getBytes());
put.addColumn("info".getBytes(), "gender".getBytes(), gender.getBytes());
put.addColumn("info".getBytes(), "clazz".getBytes(), clazz.getBytes());
stu.put(put);

这里创建一个Put对象,并使用id作为行键。然后,使用addColumn()方法向Put对象添加五个列,分别为idnameagegenderclazz。最后,使用stu.put(put)方法将数据写入到stu表中。

br.close();
stu.close();

这里使用br.close()方法关闭文件读取器,使用stu.close()方法关闭stu表对象。这些代码行确保在写入完所有条目后,释放文件和表资源。

Delet方法
  @Test
    public void delete() throws IOException {
        TableName t1_table_name = TableName.valueOf("t1");
        Table t1 = conn.getTable(t1_table_name);

        Delete delete = new Delete("rk1".getBytes());

        t1.delete(delete);

    }

这段代码是一个 Java 语言的方法,它的作用是从 HBase 数据库中表名为 “t1” 的表中删除一行,该行的行键为 “rk1”。

具体来说,代码首先创建一个 TableName 对象,用于指定要操作的表名。然后,它使用 conn 对象获取该表的 Table 对象,以便能够执行操作。接下来,它创建一个 Delete 对象,该对象表示要删除的行,其中 rk1 是该行的行键。最后,它调用 t1.delete(delete) 方法来执行删除操作。

需要注意的是,这段代码中的 conn 对象需要在代码其他地方进行初始化,以便能够连接到 HBase 数据库。此外,代码还需要处理可能出现的异常,例如 IOException

Scan方法

Scan 是 HBase Java API 中的一个类,用于在 HBase 表中执行扫描操作。它的主要作用是根据指定的条件扫描表中的行,并返回符合要求的行数据。下面是 Scan 函数的具体用法和示例代码:

  1. 设置扫描器的起始和结束行键:
Scan scan = new Scan();
scan.withStartRow(Bytes.toBytes("row1"));
scan.withStopRow(Bytes.toBytes("row5"));

上述代码中,创建了一个 Scan 对象,并使用 scan.withStartRow() 方法和 scan.withStopRow() 方法设置了扫描器的起始行键和结束行键。这样设置后,扫描器只会扫描行键在 row1row5 之间的数据。

  1. 设置扫描器的列族和列:
Scan scan = new Scan();
scan.addColumn(Bytes.toBytes("info"), Bytes.toBytes("name"));
scan.addColumn(Bytes.toBytes("info"), Bytes.toBytes("age"));

上述代码中,创建了一个 Scan 对象,并使用 scan.addColumn() 方法设置了扫描器要返回的列族和列。这样设置后,扫描器只会返回 info:nameinfo:age 两列的数据。

  1. 设置扫描器的过滤器:
Filter filter = new SingleColumnValueFilter(Bytes.toBytes("info"), Bytes.toBytes("age"), CompareOperator.LESS, Bytes.toBytes("25"));
Scan scan = new Scan();
scan.setFilter(filter);

上述代码中,创建了一个 SingleColumnValueFilter 过滤器,该过滤器会筛选出 info:age 列值小于 25 的行。然后,使用 scan.setFilter() 方法将该过滤器设置到扫描器中。这样设置后,扫描器只会返回符合过滤器条件的行数据。

  1. 设置扫描器的缓存和批量:
Scan scan = new Scan();
scan.setCaching(100);
scan.setBatch(10);

上述代码中,创建了一个 Scan 对象,并使用 scan.setCaching() 方法设置了扫描器的缓存大小为 100,使用 scan.setBatch() 方法设置了每次从服务器读取的行数为 10。这样设置后,扫描器将会一次性读取 100 行数据到客户端缓存中,然后每次返回 10 行数据给客户端。

下面是一个完整的示例代码,演示如何使用 Scan 扫描 HBase 表中的数据:

Configuration config = HBaseConfiguration.create();
config.set("hbase.zookeeper.quorum", "localhost");
config.set("hbase.zookeeper.property.clientPort", "2181");
Connection conn = ConnectionFactory.createConnection(config);

TableName tableName = TableName.valueOf("mytable");
Table table = conn.getTable(tableName);

Scan scan = new Scan();
scan.withStartRow(Bytes.toBytes("row1"));
scan.withStopRow(Bytes.toBytes("row5"));

ResultScanner scanner = table.getScanner(scan);
for (Result result : scanner) {
   byte[] row = result.getRow();
   byte[] name = result.getValue(Bytes.toBytes("info"), Bytes.toBytes("name"));
   byte[] age = result.getValue(Bytes.toBytes("info"), Bytes.toBytes("age"));
   System.out.println("rowkey: " + Bytes.toString(row) + ", name: " + Bytes.toString(name) + ", age: " + Bytes.toString(age));
}

table.close();
conn.close();

上述代码中,首先创建了一个 HBase 连接对象 conn,并获取了名为 mytable 的表的 Table 对象。然后,创建了一个 Scan 对象,并使用 scan.withStartRow() 方法和 scan.withStopRow() 方法设置了扫描器的起始行键和结束行键。接着,使用 table.getScanner() 方法获取一个 ResultScanner 对象,并使用 for 循环遍历 ResultScanner 中的每一行数据。最后,输出每一行数据的行键、姓名和年龄。执行该程序后,会输出符合条件的行数据的详细信息。

示例输出结果:

rowkey: row1, name: Tom, age: 20
rowkey: row2, name: Jack, age: 22
rowkey: row3, name: Lily, age: 24
rowkey: row4, name: Lucy, age: 26

上述代码中,默认情况下输出的行数据按照行键的字典序排列。如果需要按照其他列的值排序,可以使用 scan.setReversed() 方法设置扫描的顺序。如果需要分页获取扫描的结果,可以使用 setStartRow()setStopRow() 方法设置起始和结束位置,然后多次执行扫描操作获取不同页的数据。

示例
@Test
    public void scan() throws IOException {
        TableName stu_table_name = TableName.valueOf("stu");
        Table stu = conn.getTable(stu_table_name);
        // 返回rowkey范围在1500100888~1500100900的前10条数据
        Scan scan = new Scan();
        scan.setLimit(10);
        scan.withStartRow("1500100888".getBytes());
        scan.withStopRow("1500100900".getBytes());


        ResultScanner resultScanner = stu.getScanner(scan);
        for (Result rs : resultScanner) {
            String id = Bytes.toString(rs.getValue("info".getBytes(), "id".getBytes()));
            String name = Bytes.toString(rs.getValue("info".getBytes(), "name".getBytes()));
            String age = Bytes.toString(rs.getValue("info".getBytes(), "age".getBytes()));
            String gender = Bytes.toString(rs.getValue("info".getBytes(), "gender".getBytes()));
            String clazz = Bytes.toString(rs.getValue("info".getBytes(), "clazz".getBytes()));

            System.out.println(id + "," + name + "," + age + "," + gender + "," + clazz);
        }

    }

这段代码是一个 Java 语言的方法,它的作用是从 HBase 数据库中的名为 “stu” 的表中扫描并返回行键在 “1500100888” 和 “1500100900” 之间的前 10 行数据。

下面是代码的逐行解释:

  1. @Test:这是 JUnit 框架中的一个注解,表示这是一个测试方法。

  2. public void scan() throws IOException:这是一个公共方法,返回类型为 void,并抛出可能会出现的 IOException 异常。

  3. TableName stu_table_name = TableName.valueOf("stu");:创建一个 TableName 对象,指定要操作的表名为 “stu”。

  4. Table stu = conn.getTable(stu_table_name);:从 HBase 连接对象 conn 中获取名为 “stu” 的表的 Table 对象,以便能够执行操作。

  5. Scan scan = new Scan();:创建一个 Scan 对象,用于表示要执行的扫描操作。

  6. scan.setLimit(10);:设置扫描结果集的最大行数为 10。

  7. scan.withStartRow("1500100888".getBytes());:设置扫描的起始行键为 “1500100888”。

  8. scan.withStopRow("1500100900".getBytes());:设置扫描的结束行键为 “1500100900”。

  9. ResultScanner resultScanner = stu.getScanner(scan);:获取 stu 表中满足条件的结果集,返回一个 ResultScanner 对象。

  10. for (Result rs : resultScanner):使用 for 循环遍历 ResultScanner 中的每一行数据。

  11. String id = Bytes.toString(rs.getValue("info".getBytes(), "id".getBytes()));:从当前行数据中获取列族为 “info”,列名为 “id” 的单元格的值,并将其转换成字符串类型。

  12. String name = Bytes.toString(rs.getValue("info".getBytes(), "name".getBytes()));:从当前行数据中获取列族为 “info”,列名为 “name” 的单元格的值,并将其转换成字符串类型。

  13. String age = Bytes.toString(rs.getValue("info".getBytes(), "age".getBytes()));:从当前行数据中获取列族为 “info”,列名为 “age” 的单元格的值,并将其转换成字符串类型。

  14. String gender = Bytes.toString(rs.getValue("info".getBytes(), "gender".getBytes()));:从当前行数据中获取列族为 “info”,列名为 “gender” 的单元格的值,并将其转换成字符串类型。

  15. String clazz = Bytes.toString(rs.getValue("info".getBytes(), "clazz".getBytes()));:从当前行数据中获取列族为 “info”,列名为 “clazz” 的单元格的值,并将其转换成字符串类型。

  16. System.out.println(id + "," + name + "," + age + "," + gender + "," + clazz);:将获取到的行数据输出到控制台,以逗号为分隔符。

电信实例
 @Test
    // 读取DIANXIN.csv数据 写入到HBase的dianxin表中,以每条数据的mdn作为rowkey
    // dianxin表包含一个列簇info,info包含两列数据:lg经度、lat维度
    // 以起始时间(第三列)作为时间戳
    // 能够基于给定的mdn获取用户最新的3条位置记录
    public void putDianXin() throws IOException {
        // 创建dianxin表
        TableName dianxin_t_name = TableName.valueOf("dianxin");
        if (!admin.tableExists(dianxin_t_name)) {
            HTableDescriptor hTableDescriptor = new HTableDescriptor(dianxin_t_name);
            HColumnDescriptor info = new HColumnDescriptor("info");
            info.setMaxVersions(5);
            hTableDescriptor.addFamily(info);
            admin.createTable(hTableDescriptor);
        }

        Table dianxin = conn.getTable(dianxin_t_name);

        // 读取DIANXIN.csv数据文件
        BufferedReader br = new BufferedReader(new FileReader("./data/DIANXIN.csv"));
        String line;

        ArrayList<Put> puts = new ArrayList<>();
        int batchSize = 1000;

        while ((line = br.readLine()) != null) {
            String[] splits = line.split(",");
            String mdn = splits[0];
            String start_time = splits[2];
            String lg = splits[4];
            String lat = splits[5];
            Put put = new Put(mdn.getBytes());

            put.addColumn("info".getBytes(), "lg".getBytes(), Long.parseLong(start_time), lg.getBytes());
            put.addColumn("info".getBytes(), "lat".getBytes(), Long.parseLong(start_time), lat.getBytes());

            puts.add(put);
            if (puts.size() == batchSize) {
                dianxin.put(puts);
                puts.clear();
            }
        }

        if (puts.size() > 0) {
            dianxin.put(puts);
        }

    }

上述代码实现了将 DIANXIN.csv 文件中的数据写入到 HBase 表中,并且能够基于给定的 MDN 获取用户最新的 3 条位置记录。下面是逐行对代码进行解释:

TableName dianxin_t_name = TableName.valueOf("dianxin");
Table dianxin = conn.getTable(dianxin_t_name);

这段代码定义了 HBase 表的名称,并且使用 conn.getTable() 方法获取了对应的 Table 对象,用于进行数据写入操作。

BufferedReader br = new BufferedReader(new FileReader("./data/DIANXIN.csv"));
String line;

这段代码使用 BufferedReader 读取 DIANXIN.csv 文件中的数据。

ArrayList<Put> puts = new ArrayList<>();
int batchSize = 1000;

这段代码定义了一个 ArrayList 对象 puts 用于存放要写入 HBase 表的数据,定义了批量写入的批次大小 batchSize

while ((line = br.readLine()) != null) {
String[] splits = line.split(",");
String mdn = splits[0];
String start_time = splits[2];
String lg = splits[4];
String lat = splits[5];
Put put = new Put(mdn.getBytes());

put.addColumn("info".getBytes(), "lg".getBytes(), Long.parseLong(start_time), lg.getBytes());
put.addColumn("info".getBytes(), "lat".getBytes(), Long.parseLong(start_time), lat.getBytes());

puts.add(put);
if (puts.size() == batchSize) {
  dianxin.put(puts);
  puts.clear();
}
}

if (puts.size() > 0) {
dianxin.put(puts);
}

这段代码使用循环遍历读取 DIANXIN.csv 文件中的每一行数据,对于每一行数据,将其切分成若干个字段,并且将其中的 MDN、起始时间、经度和纬度信息提取出来,创建一个 Put 对象,并且将经度和纬度信息分别添加到 Put 对象中的 info:lginfo:lat 列族中。然后将 Put 对象添加到 puts 列表中,并且当 puts 列表的大小达到了 batchSize 批次大小时,使用 table.put() 方法将 puts 列表中的数据写入到 HBase 表中,并且清空 puts 列表,继续进行下一次数据写入操作。最后,如果 puts 列表中还有未写入的数据,则将其写入到 HBase 表中。

需要注意的是,上述代码中将起始时间作为经纬度数据的时间戳,并且将其添加到 Put 对象中的经度和纬度列中。这样可以实现基于 MDN 获取用户最新的 3 条位置记录,因为 HBase 支持多版本数据存储,可以根据时间戳获取指定版本的数据。同时,上述代码中使用了批量写入的方式,可以提高数据写入的效率和性能。

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: HBase-Java API 是一种用于管理 HBase 表的编程接口。使用 HBase-Java API,开发人员可以编写 Java 代码来创建、删除、修改和查询 HBase 表。HBase-Java API 提供了一系列类和方法,可以让开发人员轻松地与 HBase 表进行交互。例如,可以使用 HBaseAdmin 类来管理 HBase 表,使用 HTable 类来访问 HBase 表中的数据,使用 Put 类来插入数据,使用 Get 类来获取数据,等等。总之,HBase-Java APIHBase 的重要组成部分,它为开发人员提供了强大的工具来管理和操作 HBase 表。 ### 回答2: HBase是一个分布式的列式存储数据库,在很多大数据应用中得到广泛的使用。它采用Hadoop作为其底层基础框架,同时提供了Java API供开发人员使用。HBaseJava API为开发人员提供了一个管理表的接口,使得开发人员可以对HBase数据库中的表进行创建、读取、修改和删除等基本操作。 首先,我们需要用Java API创建一个HBase数据库中的表。使用HBaseJava API创建表的流程如下: 1. 首先需要获取HBase Configuration对象,并设置HBase连接参数以连接HBase数据库。 2. 接下来,需要获取HBase Admin对象,以便在操作HBase数据库表之前检查表是否存在,如果表不存在,需要创建该表。 3. 通过HBaseJava API创建表时,需要指定表的表名、列族的名称以及版本数等属性。 4. 创建表时需要考虑表的region的分配问题,可以对表的region进行手动或自动分片,以此来控制HBase的负载均衡。 创建了HBase数据库中的表之后,我们可以使用Java API对表进行读写操作。在进行读写操作时,需要使用HBaseJava API提供的Get的方法来获取表中的数据、Scan方法来扫描整个表、以及Put方法来向表中插入数据。此外,在进行表操作时还需要设置一些常见的数据操作参数,例如版本数、时间戳等。 在使用HBaseJava API时,还需要注意一些性能优化的问题,例如何时启用缓存、何时触发分区策略以及如何优化HBase表的大小等。这些优化措施能够在HBase的性能以及数据读写时的延迟方面提供很好的支持和帮助。 总的来说,HBaseJava API提供的表管理接口为开发人员提供了非常方便和快捷的方式来操作HBase数据库中的表。通过使用这些API,开发人员可以创建、读取、修改和删除表的数据,并且能够充分应用HBase的分布式特性来优化数据管理和性能提升。 ### 回答3: HBase是一个开源、分布式、非关系型数据库,它可以存储和处理大规模结构化、半结构化和非结构化数据。HBase Java APIHBase的官方API,它提供了对HBase表的管理和操作功能,让开发人员可以通过Java代码轻松地连接到HBase数据库。 在使用HBase Java API管理表时,首先需要创建一个HBaseConfiguration对象,它包含了连接HBase数据库所需的配置信息,如Zookeeper地址、HBase根目录等。然后,可以使用HBaseAdmin类创建、删除、修改表,以及列族等操作。例如,创建一个表可以通过以下代码实现: ``` HBaseAdmin admin = new HBaseAdmin(HBaseConfiguration.create()); HTableDescriptor tableDescriptor = new HTableDescriptor("table_name"); HColumnDescriptor columnDescriptor = new HColumnDescriptor("column_family"); tableDescriptor.addFamily(columnDescriptor); admin.createTable(tableDescriptor); ``` 创建表时,需要先通过HTableDescriptor类定义表名称,然后通过HColumnDescriptor类定义列族名称。可以通过addFamily()方法将列族添加到表描述中,最后通过HBaseAdmin的createTable()方法创建表。 除了创建表之外,HBase Java API还提供了许多其他的操作,如获取表信息、获取所有表的列表、删除表等。同时,HBase Java API还提供了对数据的CRUD操作,包括put、get、scan、delete等方法,让开发人员可以方便地进行数据操作。 总之,HBase Java API是一个非常强大的工具,它可以使开发人员轻松地管理HBase数据库,并实现数据的高效存储和处理。但是,在使用HBase Java API时,需要了解HBase的基本知识和API的用法,才能更好地发挥其功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

混分吴老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值