Connect your Java application to an ApsaraDB RDS for PostgreSQL instance with Always confidential database enabled. This document covers EncJDBC (recommended, zero business code changes), EncDB SDK (explicit encrypt/decrypt calls), psql, and the Data Management (DMS) console.
Prerequisites
Before you begin, ensure that you have:
The Always confidential database feature enabled. See Enable the Always confidential database feature
Sensitive data columns defined. See Define sensitive data
Connection details for your RDS instance: hostname, port, database name, username, and password. See View and change the endpoints and port numbers of an ApsaraDB RDS for PostgreSQL instance
Java 1.8 or later, Maven 3.9.2, and IntelliJ IDEA Community Edition 2022.3.2 (or equivalent)
Security note
Store your master encryption key (MEK) in a secure location and never expose it in plaintext. The Always confidential database does not generate, store, or back up your MEK. If you lose your MEK, the data it encrypted becomes permanently inaccessible.
Choose a client method
| Method | Description | Business code changes |
|---|---|---|
| EncJDBC | Automatically identifies encrypted columns and handles encryption/decryption transparently | Not required (recommended) |
| EncDB SDK | Requires explicit encrypt/decrypt calls in your application code | Required |
| psql | Command-line tool; returns ciphertext for encrypted columns | Not required |
| DMS console | Visual query interface; returns ciphertext for encrypted columns | Not required |
EncJDBC
EncJDBC works exactly like standard Java Database Connectivity (JDBC). Only the driver class and connection URL differ — no changes to your insert, update, or query logic are needed. This is the recommended approach for Java applications.
What happens under different conditions:
| Condition | Result |
|---|---|
| EncJDBC connected, MEK correct | Values are transparently encrypted on write and decrypted on read |
| EncJDBC connected, wrong MEK | Error on connect (error code 0xf7070000) |
| psql or DMS connected | Encrypted columns appear as ciphertext |
Step 1: Download and install the driver
Download encjdbc-1.0.6.jar from the EncJDBC driver package.
This driver requires minor engine version 20230830 or later, with EncDB version 1.1.13 or later on the RDS instance.
Install the JAR to your local Maven repository:
mvn install:install-file \
-DgroupId=com.alibaba.encdb \
-DartifactId=encjdbc \
-Dversion=1.0.6 \
-Dpackaging=jar \
-Dfile=<path-to-encjdbc-1.0.6.jar>Step 2: Add Maven dependencies
Add the following to your pom.xml:
<dependencies>
<dependency>
<groupId>com.alibaba.encdb</groupId>
<artifactId>encjdbc</artifactId>
<version>1.0.6</version>
</dependency>
<!-- BouncyCastle crypto libraries -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.62</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.62</version>
</dependency>
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.23</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>24.1.1-jre</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.4</version>
</dependency>
<dependency>
<groupId>org.jgrapht</groupId>
<artifactId>jgrapht-core</artifactId>
<!-- jgrapht does not support Java 1.8 since 1.5.0 -->
<version>1.4.0</version>
</dependency>
</dependencies>Step 3: Connect and query
The connection URL uses the encjdbc:postgresql:// scheme. All other JDBC operations — createStatement, PreparedStatement, ResultSet — work as usual.
Do not hardcode password or mek in production code. Load them from environment variables or an external configuration file.
Connection URL format:
String dbUrl = String.format(
"encjdbc:postgresql://%s:%s/%s?mek=%s&enc_algo=%s",
hostname, port, dbname, mek, encAlgo
);
Class.forName("com.alibaba.encdb.encjdbc.EncDriver");
Connection dbConnection = DriverManager.getConnection(dbUrl, username, password);Connection URL parameters:
Use & to concatenate multiple parameters in the URL.
Complete example:
// Replace with your instance connection details
String hostname = "hostname";
String port = "port";
String dbname = "db";
String username = "user";
String password = "password"; // Load from environment variable in production
// Use a strong MEK generated by openssl rand -hex 16 or KMS
String mek = "00112233445566778899aabbccddeeff";
String encAlgo = "SM4_128_CBC";
String dbUrl = String.format(
"encjdbc:postgresql://%s:%d/%s?mek=%s&enc_algo=%s",
hostname, port, dbname, mek, encAlgo
);
Class.forName("com.alibaba.encdb.encjdbc.EncDriver");
Connection dbConnection = DriverManager.getConnection(dbUrl, username, password);
// Create table
dbConnection.createStatement().executeUpdate("DROP TABLE IF EXISTS example");
dbConnection.createStatement().executeUpdate(
"CREATE TABLE example (id INTEGER, name VARCHAR, price enc_int4, miles enc_float4, secret enc_text, PRIMARY KEY (id))"
);
// Insert data
PreparedStatement stmt = dbConnection.prepareStatement(
"INSERT INTO example (id, name, price, miles, secret) VALUES(?,?,?,?,?)"
);
int price = 1234;
float miles = 12.34f;
String secret = "aliyun";
stmt.setInt(1, 1);
stmt.setString(2, "name");
stmt.setInt(3, price);
stmt.setFloat(4, miles);
stmt.setString(5, secret);
stmt.execute();
// Query — EncJDBC transparently decrypts encrypted columns
String sqlCmd = "SELECT * FROM example WHERE price > ?";
PreparedStatement queryStmt = dbConnection.prepareStatement(sqlCmd);
queryStmt.setInt(1, 100);
ResultSet rs = queryStmt.executeQuery();
while (rs.next()) {
int id = rs.getInt(1);
String name = rs.getString(2);
int p = rs.getInt(3);
float m = rs.getFloat(4);
String s = rs.getString(5);
System.out.println(id + ", " + name + ", " + p + ", " + m + ", " + s);
}Expected output:
1, name, 1234, 12.34, aliyunEncJDBC handles all encryption and decryption automatically. Apart from the driver class name and the encjdbc:postgresql:// URL scheme, no other code changes are needed.
EncDB SDK
Use EncDB SDK when your application needs explicit control over encryption and decryption. Unlike EncJDBC, EncDB SDK requires you to call cryptor.encrypt(...) before writing data and cryptor.decryptXxx(...) after reading it.
Step 1: Download and install the SDK
Download libencdb-1.2.12.jar from the EncDB SDK package.
This SDK requires minor engine version 20230830 or later, with EncDB version 1.1.13 or later on the RDS instance.
Install the JAR to your local Maven repository:
mvn install:install-file \
-DgroupId=com.alibaba.encdb \
-DartifactId=libencdb \
-Dversion=1.2.12 \
-Dpackaging=jar \
-Dfile=<path-to-libencdb-1.2.12.jar>Step 2: Add Maven dependencies
<dependencies>
<dependency>
<groupId>com.alibaba.encdb</groupId>
<artifactId>libencdb</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.70</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.70</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.23</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.1-jre</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>
</dependencies>Step 3: Initialize the SDK and query
The EncDB SDK uses a standard JDBC connection string (jdbc:postgresql://) and a separate EncdbSDK object for key management. In most cases, configure setMek and setEncAlgo; all other parameters use sensible defaults.
Do not hardcode password or mek in production code. Load them from environment variables or an external configuration file.
SDK initialization pattern:
// Standard PostgreSQL JDBC connection
String dbUrl = String.format(
"jdbc:postgresql://%s:%s/%s?binaryTransfer=true",
hostname, port, dbname
);
Class.forName("org.postgresql.Driver");
Connection dbConnection = DriverManager.getConnection(dbUrl, username, password);
// Initialize the EncDB SDK with your MEK and encryption algorithm
String mek = ...;
Constants.EncAlgo encAlgo = ...;
EncdbSDK sdk = EncdbSDKBuilder.newInstance()
.setDbConnection(dbConnection)
.setMek(mek)
.setEncAlgo(encAlgo)
.build();
Cryptor cryptor = sdk.getCryptor();
// Use cryptor to encrypt before writing and decrypt after reading:
// byte[] cipherBytes = cryptor.encrypt("tableName", "columnName", value);
// int plainInt = cryptor.decryptInt(rs.getBytes(columnIndex));SDK initialization parameters:
Complete example:
// Replace with your instance connection details
String hostname = "hostname";
String port = "port";
String dbname = "db";
String username = "user";
String password = "password"; // Load from environment variable in production
// Establish a standard PostgreSQL JDBC connection
String dbUrl = String.format(
"jdbc:postgresql://%s:%s/%s?binaryTransfer=true",
hostname, port, dbname
);
Class.forName("org.postgresql.Driver");
Connection dbConnection = DriverManager.getConnection(dbUrl, username, password);
// Initialize the SDK — use a strong MEK in production
String mek = "00112233445566778899aabbccddeeff";
Constants.EncAlgo encAlgo = Constants.EncAlgo.SM4_128_CBC;
EncdbSDK sdk = EncdbSDKBuilder.newInstance()
.setDbConnection(dbConnection)
.setMek(mek)
.setEncAlgo(encAlgo)
.build();
Cryptor cryptor = sdk.getCryptor();
// Create table
dbConnection.createStatement().executeUpdate("DROP TABLE IF EXISTS example");
dbConnection.createStatement().executeUpdate(
"CREATE TABLE example (id INTEGER, name VARCHAR, price enc_int4, miles enc_float4, secret enc_text, PRIMARY KEY (id))"
);
// Insert data — encrypt each sensitive column value before binding
PreparedStatement stmt = dbConnection.prepareStatement(
"INSERT INTO example (id, name, price, miles, secret) VALUES(?,?,?,?,?)"
);
int price = 1234;
float miles = 12.34f;
String secret = "aliyun";
stmt.setInt(1, 1);
stmt.setString(2, "name");
stmt.setBytes(3, cryptor.encrypt("example", "price", price));
stmt.setBytes(4, cryptor.encrypt("example", "miles", miles));
stmt.setBytes(5, cryptor.encrypt("example", "secret", secret));
stmt.execute();
// Query — decrypt each encrypted column after reading
String sqlCmd = "SELECT * FROM example WHERE price > ?";
stmt = dbConnection.prepareStatement(sqlCmd);
stmt.setBytes(1, cryptor.encrypt("example", "price", 100));
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
int id = rs.getInt(1);
String name = rs.getString(2);
price = cryptor.decryptInt(rs.getBytes(3));
miles = cryptor.decryptFloat(rs.getBytes(4));
String text = cryptor.decryptString(rs.getBytes(5));
System.out.println(id + ", " + name + ", " + price + ", " + miles + ", " + text);
}Expected output:
1, name, 1234, 12.34, aliyunSDK API reference
psql
Run queries against Always confidential databases using psql. Encrypted columns appear as ciphertext — psql does not decrypt them.
For example, executing SELECT * FROM example; returns:

In the output, id and name are plaintext columns. price, miles, and secret are ciphertext columns. The encrypted data cannot be viewed on the RDS instance, which prevents unauthorized access from both inside and outside the database server.
DMS console
Use the Data Management (DMS) console to query Always confidential databases visually. Like psql, DMS returns ciphertext for encrypted columns.

In the output, id and name are plaintext columns, and price, miles, and secret are ciphertext columns.
FAQ
What causes `org.postgresql.util.PSQLException: ERROR: db_process_msg_api: process message failure - returned 0xf7070000`?
Error code 0xf7070000 means the MEK could not be imported. Data encrypted with one MEK cannot be accessed with a different MEK. This error most often occurs when the same account connects to the same Always confidential database with different MEK values across sessions. Always use the same MEK for a given database.
What causes `java.lang.IllegalAccessError: class com.alibaba.encdb.common.SymCrypto ... cannot access class com.sun.crypto.provider.SunJCE`?
This error occurs when the JDK version is newer than expected and inter-module access is restricted. Add the following VM option when running your program:
--add-exports=java.base/com.sun.crypto.provider=ALL-UNNAMED