All Products
Search
Document Center

Lindorm:Use Druid to develop applications

Last Updated:Mar 28, 2026

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:

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=-1

For 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.