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数据库的过程。以下是每行代码的作用:
-
Configuration conf = HBaseConfiguration.create();
:创建了一个新的HBase配置对象。 -
conf.set("hbase.zookeeper.quorum", "master:2181,node1:2181,node2:2181");
:设置了HBase用于协调的ZooKeeper群集服务器。在这种情况下,群集服务器是"master:2181,node1:2181,node2:2181"。群集服务器字符串的格式为主机名:端口号,可以使用逗号将多个服务器分隔开。 -
conn = ConnectionFactory.createConnection(conf);
:使用步骤1中创建的配置对象创建了一个到HBase数据库的新连接。 -
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集群中的所有表名和列族名,并在控制台输出。
具体解释如下:
HTableDescriptor[] hTableDescriptors = admin.listTables();
:通过HBase的Admin
对象admin
,调用listTables()
方法获取当前HBase集群中所有表的HTableDescriptor
对象数组,并将数组赋值给hTableDescriptors
变量。
for (HTableDescriptor descriptor : hTableDescriptors)
:遍历hTableDescriptors
数组,每次循环取出一个HTableDescriptor
对象,并将其赋值给descriptor
变量。
System.out.println(descriptor.getNameAsString());
:输出当前表的名称,使用getNameAsString()
方法获取表名并在控制台打印输出。
HColumnDescriptor[] families = descriptor.getColumnFamilies();
:通过descriptor
对象的getColumnFamilies()
方法获取表中的所有列族,并将数组赋值给families
变量。
for (HColumnDescriptor cf : families)
:遍历families
数组,每次循环取出一个HColumnDescriptor
对象,并将其赋值给cf
变量。
System.out.println(cf.getNameAsString());
:输出当前列族的名称,使用getNameAsString()
方法获取列族名并在控制台打印输出。
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修改表结构,将表
t1
中cf1
列族的版本数设置为2到8之间,并将修改后的表结构更新到HBase集群中。具体解释如下:
TableName new_t1_table_name = TableName.valueOf("new_t1");
:定义一个新表名new_t1_table_name
,使用TableName.valueOf()
方法将表名字符串转换为TableName
对象。
HTableDescriptor tableDescriptor = admin.getTableDescriptor(new_t1_table_name);
:通过admin
对象的getTableDescriptor()
方法获取表new_t1
的HTableDescriptor
对象,并将其赋值给tableDescriptor
变量。
HColumnDescriptor[] columnFamilies = tableDescriptor.getColumnFamilies();
:通过tableDescriptor
对象的getColumnFamilies()
方法获取表中的所有列族,并将数组赋值给columnFamilies
变量。
for (HColumnDescriptor cf : columnFamilies)
:遍历columnFamilies
数组,每次循环取出一个HColumnDescriptor
对象,并将其赋值给cf
变量。
if ("cf1".equals(cf.getNameAsString())) { cf.setVersions(2, 8); }
:判断当前列族cf
是否为cf1
,如果是,则调用setVersions()
方法将该列族的版本数设置为2到8之间。
admin.modifyTable(new_t1_table_name, tableDescriptor);
:通过admin
对象的modifyTable()
方法,将修改后的表结构更新到HBase集群中。综上,这段代码用于修改HBase表结构,将表
t1
中cf1
列族的版本数设置为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
,列名为id
和name
,值分别为001
和zhangsan
。具体解释如下:
TableName new_t1_table_name = TableName.valueOf("new_t1");
:定义一个新表名new_t1_table_name
,使用TableName.valueOf()
方法将表名字符串转换为TableName
对象。
Table new_t1 = conn.getTable(new_t1_table_name);
:通过conn
对象的getTable()
方法获取表new_t1
的Table
对象,并将其赋值给new_t1
变量。
Put put = new Put("rk1".getBytes());
:创建一个Put
对象put
,将行键设置为rk1
。
put.addColumn("cf1".getBytes(), "id".getBytes(), "001".getBytes());
:向put
对象中添加一个cf1:id
的列,值为001
。
put.addColumn("cf1".getBytes(), "name".getBytes(), "zhangsan".getBytes());
:向put
对象中添加一个cf1:name
的列,值为zhangsan
。
new_t1.put(put);
:通过new_t1
对象的put()
方法将put
对象中的数据插入到表new_t1
中。综上,这段代码用于向HBase表中插入一行数据,行键为
rk1
,列族为cf1
,列名为id
和name
,值分别为001
和zhangsan
。
问题一:上面的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表中获取一行数据,并输出该行数据中的所有列。
具体的步骤如下:
- 创建一个
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);
- 创建一个
Get
对象,表示要获取的数据的行键。这里使用new Get("rk1".getBytes())
方法创建一个Get
对象,参数是一个字节数组,表示行键。
Get get = new Get("rk1".getBytes());
- 使用
Table.get()
方法获取一行数据,返回一个Result
对象。该对象中包含了该行数据的所有信息,包括列族、列名和列值等。
Result res = new_t1.get(get);
- 从
Result
对象中获取指定列的值。这里通过getValue()
方法获取id
和name
列的值,并使用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));
- 获取该行数据中的所有列。这里使用
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()
方法将每一行的数据分割成一个包含五个元素的字符串数组。然后,分别将五个元素赋值给id
、name
、age
、gender
和clazz
变量。
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
对象添加五个列,分别为id
、name
、age
、gender
和clazz
。最后,使用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
函数的具体用法和示例代码:
- 设置扫描器的起始和结束行键:
Scan scan = new Scan();
scan.withStartRow(Bytes.toBytes("row1"));
scan.withStopRow(Bytes.toBytes("row5"));
上述代码中,创建了一个 Scan
对象,并使用 scan.withStartRow()
方法和 scan.withStopRow()
方法设置了扫描器的起始行键和结束行键。这样设置后,扫描器只会扫描行键在 row1
和 row5
之间的数据。
- 设置扫描器的列族和列:
Scan scan = new Scan();
scan.addColumn(Bytes.toBytes("info"), Bytes.toBytes("name"));
scan.addColumn(Bytes.toBytes("info"), Bytes.toBytes("age"));
上述代码中,创建了一个 Scan
对象,并使用 scan.addColumn()
方法设置了扫描器要返回的列族和列。这样设置后,扫描器只会返回 info:name
和 info:age
两列的数据。
- 设置扫描器的过滤器:
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()
方法将该过滤器设置到扫描器中。这样设置后,扫描器只会返回符合过滤器条件的行数据。
- 设置扫描器的缓存和批量:
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 行数据。
下面是代码的逐行解释:
@Test
:这是 JUnit 框架中的一个注解,表示这是一个测试方法。
public void scan() throws IOException
:这是一个公共方法,返回类型为 void,并抛出可能会出现的 IOException 异常。
TableName stu_table_name = TableName.valueOf("stu");
:创建一个 TableName 对象,指定要操作的表名为 “stu”。
Table stu = conn.getTable(stu_table_name);
:从 HBase 连接对象conn
中获取名为 “stu” 的表的Table
对象,以便能够执行操作。
Scan scan = new Scan();
:创建一个Scan
对象,用于表示要执行的扫描操作。
scan.setLimit(10);
:设置扫描结果集的最大行数为 10。
scan.withStartRow("1500100888".getBytes());
:设置扫描的起始行键为 “1500100888”。
scan.withStopRow("1500100900".getBytes());
:设置扫描的结束行键为 “1500100900”。
ResultScanner resultScanner = stu.getScanner(scan);
:获取stu
表中满足条件的结果集,返回一个ResultScanner
对象。
for (Result rs : resultScanner)
:使用 for 循环遍历ResultScanner
中的每一行数据。
String id = Bytes.toString(rs.getValue("info".getBytes(), "id".getBytes()));
:从当前行数据中获取列族为 “info”,列名为 “id” 的单元格的值,并将其转换成字符串类型。
String name = Bytes.toString(rs.getValue("info".getBytes(), "name".getBytes()));
:从当前行数据中获取列族为 “info”,列名为 “name” 的单元格的值,并将其转换成字符串类型。
String age = Bytes.toString(rs.getValue("info".getBytes(), "age".getBytes()));
:从当前行数据中获取列族为 “info”,列名为 “age” 的单元格的值,并将其转换成字符串类型。
String gender = Bytes.toString(rs.getValue("info".getBytes(), "gender".getBytes()));
:从当前行数据中获取列族为 “info”,列名为 “gender” 的单元格的值,并将其转换成字符串类型。
String clazz = Bytes.toString(rs.getValue("info".getBytes(), "clazz".getBytes()));
:从当前行数据中获取列族为 “info”,列名为 “clazz” 的单元格的值,并将其转换成字符串类型。
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:lg
和info:lat
列族中。然后将Put
对象添加到puts
列表中,并且当puts
列表的大小达到了batchSize
批次大小时,使用table.put()
方法将puts
列表中的数据写入到 HBase 表中,并且清空puts
列表,继续进行下一次数据写入操作。最后,如果puts
列表中还有未写入的数据,则将其写入到 HBase 表中。文章来源:https://www.toymoban.com/news/detail-797175.html需要注意的是,上述代码中将起始时间作为经纬度数据的时间戳,并且将其添加到
Put
对象中的经度和纬度列中。这样可以实现基于 MDN 获取用户最新的 3 条位置记录,因为 HBase 支持多版本数据存储,可以根据时间戳获取指定版本的数据。同时,上述代码中使用了批量写入的方式,可以提高数据写入的效率和性能。文章来源地址https://www.toymoban.com/news/detail-797175.html
到了这里,关于HBASE-JAVA-API的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!