首批通过分布式安全可靠测评,为关键业务系统打造
TestContainers Java 连接 OceanBase 数据库示例程序
更新时间:2026-04-10 11:58:35
TestContainers 是一套开源的Java 库,它支持使用 Docker 容器进行自动化集成测试。 本文介绍了如何通过 TestContainers 连接并使用 OceanBase 数据库。
前提条件
- 您已下载、安装并启动 Docker。
- 您已下载并安装 IntelliJ IDEA。
- 您已下载 JDK 1.8.0。
- (可选)您已下载并在 IntelliJ IDEA 中配置 Maven。
安装后检查
检查 Docker 是否安装成功:
docker -v您无需手动启动 Docker,后续步骤中运行示例程序时,会自动启/停 Docker。
检查 JDK 是否安装成功:
java -version检查 Maven 是否安装成功:
mvn -version(可选)检查 IntelliJ IDEA 中配置 Maven 是否正确:
本文仅提供简单的示例工程供您参考。如果您需要尝试开发更为复杂的示例,可以下载适合您开发环境版本的 Maven,并通过如下路径,在 IntelliJ IDEA 中完成配置。
检查 Maven 是否安装成功:
mvn -version打开 IntelliJ IDEA,点击 IntelliJ IDEA > Settings > Build,Execution,Development > Build Tools > Maven,在 Maven home path 配置 Maven 安装包所在路径。

操作步骤
- 将您已下载的工程示例代码解压,并使用 IDEA 打开工程示例代码。
- 运行路径 src > test > java 下的工程示例 ExampleTest。
- 返回如下结果,说明数据库连接成功,示例工程执行正确。
...
53575 [main] INFO com.oceanbase.example.ExampleTest - Connect to OceanBase docker container successfully.
53577 [main] INFO com.oceanbase.example.ExampleTest - Prepare database and table.
53892 [main] INFO com.oceanbase.example.ExampleTest - Insert data to table `testcontainers`.`person`.
53928 [main] INFO com.oceanbase.example.ExampleTest - Query rows from `testcontainers`.`person`.
53932 [main] INFO com.oceanbase.example.ExampleTest - Row 0: name Adam, age 28.
53932 [main] INFO com.oceanbase.example.ExampleTest - Row 1: name Eve, age 26.
项目代码介绍
点击 Testcontainers 下载项目代码,是一个名称为 TestcontainersDemo.zip 的压缩包。
解压后,得到一个名为 TestcontainersDemo 的文件夹。目录结构如下所示:
JDBCDemo
├── src
│ └── test
│ └── java
│ └── ExampleTest.java
└── pom.xml
文件说明:
src:源代码根目录。test:主代码目录,包含应用程序的主要逻辑。java:Java 源代码目录。ExampleTest.java:主类,包含创建表和插入数据等逻辑。pom.xml:Maven 项目的配置文件,用于管理项目的依赖和构建设置。
pom.xml 代码介绍
pom.xml 文件是 Maven 项目的配置文件,定义了项目的依赖项、插件和构建规则等信息。Maven 是一个 Java 项目管理工具,可以自动下载依赖项、编译和打包项目等操作。
本文 pom.xml 文件的代码主要包括以下几个部分:
文件声明语句。
声明本文件是一个 XML 文件,使用的 XML 版本是
1.0,字符编码方式是UTF-8。代码如下:
<?xml version="1.0" encoding="UTF-8"?>配置 POM 的命名空间和 POM 模型版本。
- 通过
xmlns指定 POM 的命名空间为http://maven.apache.org/POM/4.0.0。 - 通过
xmlns:xsi指定 XML 命名空间http://www.w3.org/2001/XMLSchema-instance。 - 通过
xsi:schemaLocation指定 POM 的命名空间为http://maven.apache.org/POM/4.0.0和 POM 的 XSD 文件的位置为http://maven.apache.org/xsd/maven-4.0.0.xsd。 - 通过
<modelVersion>元素指定了该 POM 文件使用的 POM 模型版本为4.0.0。
代码如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <!-- 其他配置 --> </project>- 通过
配置基本信息。
- 通过
<groupId>指定项目所属组织为com.example。 - 通过
<artifactId>指定项目的名称为JDBCDemo。 - 通过
<version>项目的版本号为1.0-SNAPSHOT。
代码如下:
<groupId>org.example</groupId> <artifactId>JDBCDemo</artifactId> <version>1.0-SNAPSHOT</version>- 通过
配置项目所依赖的外部包,每项都有 groupId,artifactId 和 version 定义。
1. 通过 `<groupId>` 指定依赖项所属的组织。 2. 通过 `<artifactId>` 指定依赖项的名称。 3. 通过 `<version>` 指定依赖项的版本号。 4. 通过 `<scope>` 指定依赖项的作用范围,即依赖仅在测试时使用。 **代码如下:** ```java <dependencies> <dependency> //如果您使用的是 MySQL 的 JDBC,那么需要替换这里的 groupId,artifactId 和 version 信息。 <groupId>com.oceanbase</groupId> <artifactId>oceanbase-client</artifactId> <version>2.4.9</version> </dependency> <dependency> <groupId>org.testcontainers</groupId> <artifactId>oceanbase</artifactId> <version>1.19.7</version> <scope>test</scope> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> <version>2.17.1</version> <scope>test</scope> </dependency> </dependencies> ```
ExampleTest.java 代码介绍
ExampleTest.java 文件是示例程序的一部分,它使用 Testcontainers 框架和 JUnit 创建了一个测试的 Java 类。
建立了一个使用 Testcontainers 运行 OceanBase 数据库容器的测试环境,并定义了一些测试类的基本设置。
代码如下:
import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; // 测试类定义开始 public class ExampleTest { // 创建一个SLF4J Logger实例,记录类ExampleTest的日志 private static final Logger LOG = LoggerFactory.getLogger(ExampleTest.class); // 创建OceanBase容器实例,使用指定的Docker镜像,并配置环境变量 public static final OceanBaseCEContainer CONTAINER = new OceanBaseCEContainer("oceanbase/oceanbase-ce:4.2.2") .withEnv("MODE", "slim") // 设置环境变量MODE为slim .withEnv("FASTBOOT", "true") // 设置环境变量FASTBOOT为true .withLogConsumer(new Slf4jLogConsumer(LOG)); // 添加日志消费者,使用SLF4J记录容器日志 // 在所有测试开始前执行此方法,进行环境准备 @BeforeClass public static void startContainers() { // 异步启动CONTAINER,并等待启动完成 Startables.deepStart(Stream.of(CONTAINER)).join(); // 输出容器启动的相关信息,包括Docker镜像名、容器主机地址和映射端口 LOG.info( "OceanBase docker container started, image: {}, host: {}, sql port: {}, rpc port:{}.", CONTAINER.getDockerImageName(), CONTAINER.getHost(), CONTAINER.getMappedPort(2881), CONTAINER.getMappedPort(2882)); } // 所有测试结束后执行此方法,进行资源清理 @AfterClass public static void closeContainers() { // 关闭容器 CONTAINER.close(); // 记录容器停止日志 LOG.info("OceanBase docker container stopped."); } ```编写测试逻辑。
代码如下:
// 测试数据库的增加和查询操作 @Test public void test() { // 数据库和表的名称 String database = "testcontainers"; String table = "person"; // 格式化数据库和表的完整名字,使用反引号来避免SQL关键字冲突 String tableName = String.format("`%s`.`%s`", database, table); // 输出尝试连接到OceanBase容器的日志 LOG.info( "Try to connect to OceanBase docker container with url: {}.", CONTAINER.getJdbcUrl()); // 创建与OceanBase容器的数据库连接 try (Connection connection = CONTAINER.createConnection("?useSSL=false")) { LOG.info("Connect to OceanBase docker container successfully."); LOG.info("Prepare database and table.");创建表。
代码如下:
// 创建数据库和表 try (Statement statement = connection.createStatement()) { statement.execute("CREATE DATABASE IF NOT EXISTS " + database); statement.execute("USE " + database); statement.execute( "CREATE TABLE IF NOT EXISTS " + table + " (name VARCHAR(50), age INT)"); } catch (SQLException e) { throw new RuntimeException(e); }插入数据。
代码如下:
LOG.info("Insert data to table {}.", tableName); try (PreparedStatement ps = connection.prepareStatement("INSERT INTO " + tableName + " values(?, ?)")) { ps.setString(1, "Adam"); ps.setInt(2, 28); ps.executeUpdate(); ps.setString(1, "Eve"); ps.setInt(2, 26); ps.executeUpdate(); }查询数据。
代码如下:
LOG.info("Query rows from {}.", tableName); try (PreparedStatement ps = connection.prepareStatement( "SELECT * from " + tableName, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)) { ResultSet rs = ps.executeQuery(); int count = 0; while (rs.next()) { LOG.info("Row {}: name {}, age {}.", count++, rs.getString(1), rs.getInt(2)); }异常处理。
执行以上数据库操作的过程中发生任何异常,这些异常将被捕捉,并打印错误信息以及堆栈跟踪详情。
代码如下:
} catch (SQLException e) { // 如果出现异常,转抛运行时异常 throw new RuntimeException(e); }
完整的代码展示
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.oceanbase.example</groupId>
<artifactId>testcontainers-java</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.oceanbase</groupId>
<artifactId>oceanbase-client</artifactId>
<version>2.4.9</version>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>oceanbase</artifactId>
<version>1.19.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.17.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
package com.oceanbase.example;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testcontainers.containers.output.Slf4jLogConsumer;
import org.testcontainers.lifecycle.Startables;
import org.testcontainers.oceanbase.OceanBaseCEContainer;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.stream.Stream;
public class ExampleTest {
private static final Logger LOG = LoggerFactory.getLogger(ExampleTest.class);
public static final OceanBaseCEContainer CONTAINER =
new OceanBaseCEContainer("oceanbase/oceanbase-ce:4.2.2")
.withEnv("MODE", "slim")
.withEnv("FASTBOOT", "true")
.withLogConsumer(new Slf4jLogConsumer(LOG));
@BeforeClass
public static void startContainers() {
Startables.deepStart(Stream.of(CONTAINER)).join();
LOG.info(
"OceanBase docker container started, image: {}, host: {}, sql port: {}, rpc port:{}.",
CONTAINER.getDockerImageName(),
CONTAINER.getHost(),
CONTAINER.getMappedPort(2881),
CONTAINER.getMappedPort(2882));
}
@AfterClass
public static void closeContainers() {
CONTAINER.close();
LOG.info("OceanBase docker container stopped.");
}
@Test
public void test() {
String database = "testcontainers";
String table = "person";
String tableName = String.format("`%s`.`%s`", database, table);
LOG.info(
"Try to connect to OceanBase docker container with url: {}.",
CONTAINER.getJdbcUrl());
try (Connection connection = CONTAINER.createConnection("?useSSL=false")) {
LOG.info("Connect to OceanBase docker container successfully.");
LOG.info("Prepare database and table.");
try (Statement statement = connection.createStatement()) {
statement.execute("CREATE DATABASE IF NOT EXISTS " + database);
statement.execute("USE " + database);
statement.execute(
"CREATE TABLE IF NOT EXISTS " + table + " (name VARCHAR(50), age INT)");
} catch (SQLException e) {
throw new RuntimeException(e);
}
LOG.info("Insert data to table {}.", tableName);
try (PreparedStatement ps =
connection.prepareStatement("INSERT INTO " + tableName + " values(?, ?)")) {
ps.setString(1, "Adam");
ps.setInt(2, 28);
ps.executeUpdate();
ps.setString(1, "Eve");
ps.setInt(2, 26);
ps.executeUpdate();
}
LOG.info("Query rows from {}.", tableName);
try (PreparedStatement ps =
connection.prepareStatement(
"SELECT * from " + tableName,
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY)) {
ResultSet rs = ps.executeQuery();
int count = 0;
while (rs.next()) {
LOG.info("Row {}: name {}, age {}.", count++, rs.getString(1), rs.getInt(2));
}
assert count == 2;
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
相关文档
- Testcontainers for Java 官方文档
- 使用 OceanBase 的 Docker 镜像需要使用 GenericContainer,你可以参考文档 OceanBase Module
点击下载 TestcontainersDemo 示例工程