Use Alibaba Druid as a JDBC connection pool to manage connections to LindormTSDB efficiently. A connection pool pre-creates a set of connections and reuses them across database operations — instead of opening and closing a connection for every write or query. Calling connection.close() returns the connection to the pool rather than terminating it.
This approach is especially useful for IoT and time series workloads, where applications write sensor readings at high frequency with short-lived operations. Reusing connections significantly reduces latency and resource consumption.
Prerequisites
Before you begin, make sure you have:
Java Development Kit (JDK) 1.8 or later installed
Your client IP address added to the whitelist of your Lindorm instance. See Configure a whitelist
Add Maven dependencies
Add both the Druid connection pool and the Lindorm JDBC driver to your pom.xml:
<!-- Alibaba Druid connection pool -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.6</version>
</dependency>
<!-- Lindorm JDBC driver -->
<dependency>
<groupId>com.aliyun.lindorm</groupId>
<artifactId>lindorm-all-client</artifactId>
<version>2.2.1.3</version>
</dependency>To install the JDBC driver manually instead, download the lindorm-all-client JAR package and add it to your project classpath. For example, to use version 2.1.5, download lindorm-all-client-2.1.5.jar.Configure Druid
In src/main/resources of your Maven project, create a file named druid.properties.
Required parameters
These parameters connect Druid to your LindormTSDB instance. Replace the placeholder values with your actual connection details from the Lindorm console.
# Driver class — keep this value unchanged
driverClassName=com.aliyun.lindorm.table.client.Driver
# JDBC URL — get this from the Lindorm console
url=jdbc:lindorm:tsdb:url=http://ld-bp12pt80qr38p****-proxy-tsdb-pub.lindorm.rds.aliyuncs.com:8242
username=root
password=root
# Database to connect to
connectionProperties=database=defaultFor details on the JDBC URL format and parameters, see URL of the JDBC driver. The default username and password are both root.Pool size and timeout
# Initialize the pool on startup
init=true
# Number of connections to create at startup
initialSize=10
# Minimum number of idle connections to maintain
minIdle=10
# Maximum number of active connections
maxActive=20
# Maximum time to wait for a connection, in milliseconds
maxWait=30000Adjust initialSize, minIdle, and maxActive based on your workload. Keep maxWait at 30000 ms.
Keep-alive settings
These settings prevent idle connections from being silently dropped by the server. Keep all values unchanged to avoid ConnectionDisconnectedException.
druid.keepAlive=true
druid.keepAliveBetweenTimeMillis=30000
minEvictableIdleTimeMillis=600000
maxEvictableIdleTimeMillis=900000
timeBetweenEvictionRunsMillis=5000Connection validation
validationQuery=SELECT 1
testWhileIdle=true
testOnBorrow=false
testOnReturn=falseStatement cache
Disable the prepared statement cache. Enabling it causes NoSuchStatement exceptions with LindormTSDB.
poolPreparedStatements=false
maxOpenPreparedStatements=-1
druid.maxPoolPreparedStatementPerConnectionSize=-1Connect and run queries
Initialize the connection pool
Load druid.properties and create the DataSource:
// Load Druid configuration
Properties properties = new Properties();
InputStream inputStream = tsdb.class.getClassLoader().getResourceAsStream("druid.properties");
properties.load(inputStream);
// Initialize the connection pool
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);Create a table
try (Connection connection = dataSource.getConnection()) {
try (Statement statement = connection.createStatement()) {
String sql = "CREATE TABLE sensor ("
+ "device_id VARCHAR TAG,"
+ "region VARCHAR TAG,"
+ "time TIMESTAMP,"
+ "temperature DOUBLE,"
+ "humidity DOUBLE,"
+ "PRIMARY KEY(device_id))";
int ret = statement.executeUpdate(sql);
System.out.println(ret);
}
} // connection.close() returns the connection to the poolInsert data
Use addBatch to send multiple rows in a single round trip:
try (Connection connection = dataSource.getConnection()) {
try (Statement stmt = connection.createStatement()) {
stmt.addBatch("INSERT INTO sensor(device_id, region, time, temperature, humidity) values('F07A1260','north-cn','2021-04-22 15:33:00',12.1,45)");
stmt.addBatch("INSERT INTO sensor(device_id, region, time, temperature, humidity) values('F07A1260','north-cn','2021-04-22 15:33:10',13.2,47)");
stmt.addBatch("INSERT INTO sensor(device_id, region, time, temperature, humidity) values('F07A1260','north-cn','2021-04-22 15:33:20',10.6,46)");
stmt.addBatch("INSERT INTO sensor(device_id, region, time, temperature, humidity) values('F07A1261','south-cn','2021-04-22 15:33:00',18.1,44)");
stmt.addBatch("INSERT INTO sensor(device_id, region, time, temperature, humidity) values('F07A1261','south-cn','2021-04-22 15:33:10',19.7,44)");
stmt.executeBatch();
}
} // connection.close() returns the connection to the poolQuery data
Always specify a time range to limit the amount of data scanned:
try (Connection connection = dataSource.getConnection()) {
try (PreparedStatement pstmt = connection.prepareStatement(
"SELECT device_id, region, time, temperature, humidity FROM sensor WHERE time >= ? AND time <= ?")) {
Timestamp startTime = Timestamp.valueOf("2021-04-22 15:33:00");
Timestamp endTime = Timestamp.valueOf("2021-04-22 15:33:20");
pstmt.setTimestamp(1, startTime);
pstmt.setTimestamp(2, endTime);
try (ResultSet rs = pstmt.executeQuery()) {
while (rs.next()) {
String device_id = rs.getString("device_id");
String region = rs.getString("region");
Timestamp time = rs.getTimestamp("time");
Double temperature = rs.getDouble("temperature");
Double humidity = rs.getDouble("humidity");
System.out.printf("%s %s %s %f %f\n", device_id, region, time, temperature, humidity);
}
}
}
} // connection.close() returns the connection to the pool