Use the HBase Java API to connect to an ApsaraDB for HBase Performance-enhanced Edition instance and run DDL and DML operations against it.
How it works
The HBase Java client uses three core objects. Understanding their roles and threading behavior prevents the most common connection errors:
| Object | Weight | Thread-safe | Responsibility |
|---|---|---|---|
Connection | Heavyweight | Yes — share across all threads | Manages the connection to the cluster. Create once per application; close on shutdown. |
Admin | Lightweight | — | DDL operations: create, disable, truncate, and delete tables. Create as needed and close when done. |
Table | Lightweight | No — each thread needs its own instance | DML operations: put, get, delete, and scan. Create per thread and close when done. |
Because Connection is expensive to create, you share one instance. Because Table is not thread-safe, you never share instances across threads — get a new one from the connection for each thread.
Prerequisites
Before you begin, ensure that you have:
The ApsaraDB for HBase SDK for Java installed. For more information, see Download ApsaraDB for HBase SDK for Java
For internal network connections: an Elastic Compute Service (ECS) instance deployed in the same virtual private cloud (VPC) as the HBase instance, with the ECS instance IP address added to the HBase instance whitelist. See Create an ECS instance and Configure a whitelist
For Internet connections: the IP address whitelist configured for the instance. See Configure a whitelist
Connect to your instance
Step 1: Get the client connection configuration
Log on to the ApsaraDB for HBase console.
On the Clusters page, find the instance and click its ID.

In the left-side navigation pane of the instance details page, click Database Connection.
Click Generate Configuration Items. In the Client Connection Configuration dialog box, click the Java Configuration tab and copy the Java code.

Step 2: Initialize the client
Paste the copied Java configuration code into your project to create a Configuration object:
// Create a Configuration object.
Configuration conf = HBaseConfiguration.create();
// Set the endpoint. Use the public endpoint for Internet connections,
// or the VPC-facing endpoint for internal network connections.
// Find both endpoints on the Database Connection page in the console.
conf.set("hbase.zookeeper.quorum", "ld-xxxx-proxy-hbaseue.hbaseue.xxx.rds.aliyuncs.com:30020");
// Set the username and password. The defaults are both "root".
conf.set("hbase.client.username", "root");
conf.set("hbase.client.password", "root");
// Required only if you use the alihbase-connector dependency.
// Not needed if you use the alihbase-client dependency.
//conf.set("hbase.client.connection.impl", AliHBaseUEClusterConnection.class.getName());Step 3: Create a connection
Create a single Connection for the entire lifecycle of your application. It is thread-safe and can be shared across all threads.
// Connection is a heavyweight object — create it once and reuse it.
// Close it after all operations are complete to prevent connection leaks.
Connection connection = ConnectionFactory.createConnection(conf);Tip: Wrap the connection in a try-finally block to make sure it is always closed, even if an exception occurs.Run DDL and DML operations
DDL operations
Use Admin for table management. Admin is lightweight — create it as needed and close it when done.
try (Admin admin = connection.getAdmin()) {
// Create a table with one column family.
// In production, pre-split the table based on your data distribution.
HTableDescriptor htd = new HTableDescriptor(TableName.valueOf("tablename"));
htd.addFamily(new HColumnDescriptor(Bytes.toBytes("family")));
admin.createTable(htd);
// Disable a table.
admin.disableTable(TableName.valueOf("tablename"));
// Truncate a table (preserves the table structure).
admin.truncateTable(TableName.valueOf("tablename"), true);
// Delete a table.
admin.deleteTable(TableName.valueOf("tablename"));
}DML operations
Use Table for data operations. Table is not thread-safe — each thread must get its own instance from the connection.
// Table is lightweight and not thread-safe. Get a new instance per thread;
// never share a Table instance across threads.
try (Table table = connection.getTable(TableName.valueOf("tablename"))) {
// Insert a row.
Put put = new Put(Bytes.toBytes("row"));
put.addColumn(Bytes.toBytes("family"), Bytes.toBytes("qualifier"), Bytes.toBytes("value"));
table.put(put);
// Read a single row.
Get get = new Get(Bytes.toBytes("row"));
Result res = table.get(get);
// Delete a row.
Delete delete = new Delete(Bytes.toBytes("row"));
table.delete(delete);
// Scan a range of rows — cursor-like access over a key range.
Scan scan = new Scan(Bytes.toBytes("startRow"), Bytes.toBytes("endRow"));
ResultScanner scanner = table.getScanner(scan);
for (Result result : scanner) {
// Process each result.
}
scanner.close();
}Complete example
The following self-contained class combines all steps above. Copy it into your project, replace the endpoint with your actual value, and run it to verify connectivity.
import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Admin;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.apache.hadoop.hbase.client.Delete;
import org.apache.hadoop.hbase.client.Get;
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.util.Bytes;
public class HBaseQuickStart {
public static void main(String[] args) throws IOException {
// --- Configuration ---
Configuration conf = HBaseConfiguration.create();
// Replace with your actual endpoint from the Database Connection page.
conf.set("hbase.zookeeper.quorum", "ld-xxxx-proxy-hbaseue.hbaseue.xxx.rds.aliyuncs.com:30020");
conf.set("hbase.client.username", "root");
conf.set("hbase.client.password", "root");
// Uncomment if using the alihbase-connector dependency:
//conf.set("hbase.client.connection.impl", AliHBaseUEClusterConnection.class.getName());
// --- Connection ---
// Connection is heavyweight — create once and share across all threads.
// Close it in finally to prevent connection leaks.
Connection connection = ConnectionFactory.createConnection(conf);
try {
// --- DDL: create a table ---
// Admin is lightweight; create it as needed and close when done.
try (Admin admin = connection.getAdmin()) {
HTableDescriptor htd = new HTableDescriptor(TableName.valueOf("tablename"));
htd.addFamily(new HColumnDescriptor(Bytes.toBytes("family")));
// In production, pre-split the table based on your data distribution.
admin.createTable(htd);
}
// --- DML: write and read data ---
// Table is lightweight and not thread-safe.
// Each thread must get its own Table instance from the connection.
try (Table table = connection.getTable(TableName.valueOf("tablename"))) {
// Insert a row.
Put put = new Put(Bytes.toBytes("row"));
put.addColumn(Bytes.toBytes("family"), Bytes.toBytes("qualifier"), Bytes.toBytes("value"));
table.put(put);
// Read a single row.
Get get = new Get(Bytes.toBytes("row"));
Result res = table.get(get);
// Scan a range of rows — cursor-like access over a key range.
Scan scan = new Scan(Bytes.toBytes("startRow"), Bytes.toBytes("endRow"));
ResultScanner scanner = table.getScanner(scan);
for (Result result : scanner) {
// Process each result.
}
scanner.close();
// Delete a row.
Delete delete = new Delete(Bytes.toBytes("row"));
table.delete(delete);
}
// --- DDL: clean up ---
try (Admin admin = connection.getAdmin()) {
admin.disableTable(TableName.valueOf("tablename"));
admin.deleteTable(TableName.valueOf("tablename"));
}
} finally {
connection.close();
}
}
}