Druid is a Java Database Connectivity (JDBC) connection pool. This topic shows how to connect to LindormTable using Druid and run basic CRUD operations.
Prerequisites
Before you begin, ensure that you have:
Java Development Kit (JDK) 1.8 or later installed
A whitelist configured for your Lindorm instance. See Configure whitelists
LindormTable 2.3.1 or later. To upgrade, see Upgrade the minor engine version of a Lindorm instance
Usage notes
Connection lifecycle
Lindorm frontend nodes use Server Load Balancer (SLB) for load balancing. To distribute requests evenly across frontend nodes, avoid holding connections open for extended periods. Set the phyMaxUseCount and phyTimeoutMillis parameters to control connection lifetime.
After each query, call conn.close() to return the connection to the pool. If a connection is not returned and becomes invalid, Druid cannot detect that state.
Resilience
In complex network environments, connection interruptions can occur due to gateway bottlenecks, network jitter, high retransmission rates, or packet loss. Configure the connection pool appropriately and implement retry logic in your application code.
When the server is upgraded or restarted, connections may be temporarily interrupted. Even with a connection pool, your application may encounter exceptions—catch those exceptions and implement retries.
Observability
Monitor your connection pool using DruidDataSource#getStatData() and DruidDataSource#dump(). Call these methods periodically to verify that your configurations are taking effect—including confirming that phyMaxUseCount and phyTimeoutMillis are recycling connections and resolving any load imbalance.
Add dependencies
Add the following to your Maven project's pom.xml. Download the sample code to run a working example locally.
Standard Maven setup
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.11</version>
</dependency>
<dependency>
<groupId>com.aliyun.lindorm</groupId>
<artifactId>lindorm-all-client</artifactId>
<version>2.2.1.3</version>
</dependency>Spring Boot Starter setup
When using druid-spring-boot-starter, exclude the bundled druid component and add the explicit version separately. This prevents version conflicts between the starter's built-in Druid and the Lindorm JDBC Driver.
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.11</version>
<exclusions>
<exclusion>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.11</version>
</dependency>
<dependency>
<groupId>com.aliyun.lindorm</groupId>
<artifactId>lindorm-all-client</artifactId>
<version>2.2.1.3</version>
</dependency>Connect to LindormTable
Step 1: Configure the connection pool
In src/main/resources, create druid.properties with the following content. Parameters are grouped into three categories:
Replace with your values — required before the application can connect
Tune for your workload — adjust based on your concurrency and hardware
Keep as-is — defaults are optimized for LindormTable; changing them may cause errors
# ── Replace with your values ─────────────────────────────────────────────────
# Driver class name — do not change this value.
driverClassName=com.aliyun.lindorm.table.client.Driver
# Endpoint for LindormTable. Get the value from the Lindorm console.
# See: https://www.alibabacloud.com/help/en/lindorm/user-guide/connect-to-an-apsaradb-for-lindorm-instance#section-xi3-1q0-gv0
url=jdbc:lindorm:table:url=http://ld-bp17j28j2y7pm****.lindorm.rds.aliyuncs.com:30060
# Username and password for LindormTable.
# View or reset credentials in the LindormTable cluster management system.
# See: https://www.alibabacloud.com/help/en/doc-detail/174671.html#topic2090
# To change your password, see: https://www.alibabacloud.com/help/en/doc-detail/174671.html#section-n3z-64v-v73
username=****
password=****
# Target database to connect to.
connectionProperties=database=****
# ── Tune for your workload ────────────────────────────────────────────────────
# Number of connections created at startup.
initialSize=10
# Minimum number of idle connections.
# For high-throughput scenarios, set this equal to maxActive.
# For workloads with significant traffic spikes, use a smaller value.
minIdle=40
# Maximum number of active connections.
# Set this to match your thread pool size.
maxActive=40
# Maximum usage count per connection before it is recycled.
# Recycling connections periodically prevents load imbalance across LDServer nodes.
druid.phyMaxUseCount=10000
# ── Keep as-is ────────────────────────────────────────────────────────────────
# Initialize the pool on startup.
init=true
# Maximum wait time (ms) to acquire a connection from the pool.
maxWait=30000
# Connection keep-alive settings.
# Changing these may cause unexpected disconnections (ConnectionDisconnectedException).
druid.keepAlive=true
druid.keepAliveBetweenTimeMillis=30000
minEvictableIdleTimeMillis=300000
maxEvictableIdleTimeMillis=600000
timeBetweenEvictionRunsMillis=5000
# Maximum connection lifetime (ms) before recycling.
# Together with phyMaxUseCount, this periodically refreshes connections
# to prevent uneven distribution across frontend nodes.
phyTimeoutMillis=1800000
# Connection validation settings.
validationQuery=SELECT 1
testWhileIdle=true
testOnBorrow=false
testOnReturn=false
# Prepared statement cache — disabled to avoid NoSuchStatement errors.
poolPreparedStatements=false
maxOpenPreparedStatements=-1
druid.maxPoolPreparedStatementPerConnectionSize=-1For the full list of Druid configuration parameters, see DruidDataSource configuration.
Step 2: Initialize the connection pool
Load druid.properties and create the DataSource:
// Load configuration from druid.properties
Properties properties = new Properties();
InputStream inputStream = DruidPoolDemo.class.getClassLoader().getResourceAsStream("druid.properties");
properties.load(inputStream);
// Initialize the connection pool
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);Step 3: Run CRUD operations
All examples below acquire a connection from the pool with dataSource.getConnection() and return it via try-with-resources. Use PreparedStatement for parameterized queries to prevent SQL injection.
Create a table
String tableName = "sql_table_" + new Random().nextInt(1000);
try (Connection connection = dataSource.getConnection()) {
try (Statement statement = connection.createStatement()) {
String sql = "create table if not exists " + tableName
+ "(id VARCHAR, name VARCHAR, primary key(id))";
int ret = statement.executeUpdate(sql);
System.out.println(ret);
}
}Insert data
try (Connection connection = dataSource.getConnection()) {
String sql = "upsert into " + tableName + "(id,name) values(?,?)";
try (PreparedStatement ps = connection.prepareStatement(sql)) {
ps.setString(1, "aa");
ps.setString(2, "bb");
int ret = ps.executeUpdate();
System.out.println(ret);
}
}Query data
try (Connection connection = dataSource.getConnection()) {
String sql = "select * from " + tableName + " where id=?";
try (PreparedStatement ps = connection.prepareStatement(sql)) {
ps.setString(1, "aa");
ResultSet rs = ps.executeQuery();
while (rs.next()) {
String id = rs.getString(1);
String name = rs.getString(2);
System.out.println("id=" + id);
System.out.println("name=" + name);
}
}
}Delete data
try (Connection connection = dataSource.getConnection()) {
String sql = "delete from " + tableName + " where id=?";
try (PreparedStatement ps = connection.prepareStatement(sql)) {
ps.setString(1, "aa");
ps.executeUpdate();
}
}Appendix: How connection pool load balancing works
Druid uses TCP persistent connections, which are more efficient than short-lived connections but can cause uneven load distribution across LDServer nodes in two scenarios:
Burst connection creation
When your application creates many connections rapidly, SLB may not refresh backend node statistics fast enough. Some LDServer nodes end up handling more connections, resulting in higher pressure on those nodes.
Health check anomalies
SLB uses active health checks to detect unhealthy backend nodes. Transient health check failures can cause some LDServer nodes to receive fewer new connections, leading to lower utilization on those nodes.
Resolution
Druid's phyTimeoutMillis and phyMaxUseCount parameters periodically recycle connections in the pool—for example, after 30 minutes or 10,000 executions. This forces the pool to redistribute connections across backend nodes over time, resolving both scenarios without sacrificing throughput. Add both parameters to your configuration by default.
To confirm the parameters are taking effect, call DruidDataSource#getStatData() and DruidDataSource#dump() periodically and check that connections are being recycled at the expected intervals.