diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index f457ae2..b023252 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -37,6 +37,9 @@ jobs:
- name: 'mybatis-plus'
language: 'java'
with_oceanbase_container: false
+ - name: 'mybatis'
+ language: 'java'
+ with_oceanbase_container: true
uses: ./.github/workflows/basic-ci.yml
with:
module: ${{ matrix.module.name }}
diff --git a/java/mybatis/README-CN.md b/java/mybatis/README-CN.md
new file mode 100644
index 0000000..eef9434
--- /dev/null
+++ b/java/mybatis/README-CN.md
@@ -0,0 +1,251 @@
+# Spring Boot 连接 OceanBase 指南(使用 Spring Data JPA)
+
+[English](README.md) | 简体中文
+
+本文介绍如何通过 MyBatis 连接 OceanBase 数据库。
+由于 OceanBase 支持 MySQL 模式与 Oracle 模式,因此可以使用 MySQL 驱动连接 OceanBase。
+## 快速开始
+
+1.在 pom.xml 中首先加入 MySQL 以及 MyBatis 驱动,pom.xml 参考[OceanBase MyBatis 连接示例](https://www.oceanbase.com/docs/community-observer-cn-10000000000900919) 示例。
+
+```xml
+
+
+ mysql
+ mysql-connector-java
+ 8.0.25
+
+
+ org.mybatis
+ mybatis
+ 3.5.4
+
+
+ junit
+ junit
+ 4.13.2
+ test
+
+
+```
+
+ 2.在 src/main/resources 文件夹新建 mybatis-config.xml ,并修改数据库连接信息,指定 mapper.xml 路径。
+
+ mybatis-config.xml
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+3.新建 实体类,以及对应的 Mapper.xml 文件。 本次示例中,我们创建一个 User 实体类。
+```java
+package com.oceanbase.samples.entity;
+
+import java.util.Objects;
+
+public class User {
+ private Integer id;
+ private String name;
+
+ public User() {
+ }
+
+ public User(Integer id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ User user = (User) o;
+ return Objects.equals(id, user.id) && Objects.equals(name, user.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, name);
+ }
+
+ @Override
+ public String toString() {
+ return "User{" +
+ "id=" + id +
+ ", name='" + name + '\'' +
+ '}';
+ }
+}
+```
+4.新建 UserMapper 接口,用于与 UserMapper关联相应的增删改查操作
+```java
+package com.oceanbase.samples.mapper;
+
+public interface UserMapper {
+}
+```
+
+5.新建 UserMapper.xml ,并绑定 UserMapper 接口, 添加相应的增删改查操作。
+```xml
+
+
+
+
+
+
+
+
+
+ delete from user where id = #{id};
+
+
+
+ insert into user (name) values (#{name});
+
+
+
+ update user set name = #{name} where id = #{id};
+
+
+```
+
+6.测试用例,用于测试 UserMapper.xml 中的增删改查操作。
+```java
+package com.oceanbase.samples;
+
+
+import com.oceanbase.samples.entity.User;
+import com.oceanbase.samples.util.SqlSessionUtil;
+import org.apache.ibatis.io.Resources;
+import org.apache.ibatis.jdbc.ScriptRunner;
+import org.apache.ibatis.session.SqlSession;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.InputStreamReader;
+import java.sql.Connection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+
+public class OceanBaseMyBatisTest
+{
+
+
+ @Before
+ public void setUp() throws Exception {
+ // 执行SQL脚本
+ try {
+ Connection connection = SqlSessionUtil.openSession().getConnection();
+ ScriptRunner runner = new ScriptRunner(connection);
+ runner.runScript(new InputStreamReader(Resources.getResourceAsStream("init.sql")));
+ SqlSessionUtil.openSession().commit();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ public void test() {
+ insertTest(SqlSessionUtil.openSession());
+ updateTest(SqlSessionUtil.openSession());
+ selectTest(SqlSessionUtil.openSession());
+ selectWithPagination(SqlSessionUtil.openSession(), 0, 2);
+ deleteTest(SqlSessionUtil.openSession());
+ }
+
+
+
+ public static void insertTest(SqlSession sqlSession) {
+ // Insert data
+ User user = new User();
+ user.setName("Tom");
+ int count = sqlSession.insert("com.oceanbase.samples.mapper.UserMapper.insert", user);
+ System.out.println("Insert count: " + count);
+
+ }
+
+ public static void updateTest(SqlSession sqlSession) {
+ // Update data
+ User user = new User();
+ user.setId(1);
+ user.setName("Jerry");
+ int count = sqlSession.update("com.oceanbase.samples.mapper.UserMapper.update", user);
+ System.out.println("Update count: " + count);
+ }
+
+ public static void selectTest(SqlSession sqlSession) {
+ // Select data
+ List user = sqlSession.selectList("com.oceanbase.samples.mapper.UserMapper.selectUser", 1);
+ user.stream().filter(Objects::nonNull).forEach(System.out::println);
+ }
+
+
+ public static void selectWithPagination(SqlSession sqlSession, int offset, int pageSize) {
+ Map params = new HashMap<>();
+ params.put("offset", offset);
+ params.put("pageSize", pageSize);
+ List users = sqlSession.selectList("com.oceanbase.samples.mapper.UserMapper.selectWithPagination", params);
+ users.stream().filter(Objects::nonNull).forEach(System.out::println);
+ }
+
+ public static void deleteTest(SqlSession sqlSession) {
+ // Delete data
+ int count = sqlSession.delete("com.oceanbase.samples.mapper.UserMapper.delete", 3);
+ System.out.println("Delete count: " + count);
+ }
+
+ @After
+ public void closeSession() {
+ SqlSessionUtil.openSession().close();
+ }
+}
+
+```
+
+
+修改代码中的连接信息,之后你就可以直接使用 run.sh 运行示例代码。
+
+```bash
+sh run.sh
+```
diff --git a/java/mybatis/README.md b/java/mybatis/README.md
new file mode 100644
index 0000000..6c9c3b7
--- /dev/null
+++ b/java/mybatis/README.md
@@ -0,0 +1,251 @@
+# Guide to Connect Spring Boot to OceanBase (Using Spring Data JPA)
+
+English | [简体中文](README-CN.md)
+
+This article introduces how to connect to the OceanBase database through MyBatis.
+Since OceanBase supports MySQL mode and Oracle mode, the MySQL driver can be used to connect to OceanBase.
+## Quick Start
+
+1. First, add the MySQL and MyBatis drivers to the pom.xml file. Refer to the [OceanBase MyBatis Connection Example](https://www.oceanbase.com/docs/community-observer-cn-10000000000900919) for the pom.xml example.
+
+```xml
+
+
+ mysql
+ mysql-connector-java
+ 8.0.25
+
+
+ org.mybatis
+ mybatis
+ 3.5.4
+
+
+ junit
+ junit
+ 4.13.2
+ test
+
+
+```
+
+2. Create a new mybatis-config.xml file in the src/main/resources folder, modify the database connection information, and specify the path for the mapper.xml.
+
+ mybatis-config.xml
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+3. Create a new entity class and the corresponding Mapper.xml file. In this example, we create a User entity class.
+```java
+package com.oceanbase.samples.entity;
+
+import java.util.Objects;
+
+public class User {
+ private Integer id;
+ private String name;
+
+ public User() {
+ }
+
+ public User(Integer id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ User user = (User) o;
+ return Objects.equals(id, user.id) && Objects.equals(name, user.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, name);
+ }
+
+ @Override
+ public String toString() {
+ return "User{" +
+ "id=" + id +
+ ", name='" + name + '\'' +
+ '}';
+ }
+}
+```
+4. Create a new UserMapper interface, which will be associated with the UserMapper for the corresponding CRUD operations.
+```java
+package com.oceanbase.samples.mapper;
+
+public interface UserMapper {
+}
+```
+
+5. Create a new UserMapper.xml file and bind it to the UserMapper interface, and add the corresponding CRUD operations.
+```xml
+
+
+
+
+
+
+
+
+
+ delete from user where id = #{id};
+
+
+
+ insert into user (name) values (#{name});
+
+
+
+ update user set name = #{name} where id = #{id};
+
+
+```
+
+6. Test case, used to test the CRUD operations in UserMapper.xml.
+```java
+package com.oceanbase.samples;
+
+
+import com.oceanbase.samples.entity.User;
+import com.oceanbase.samples.util.SqlSessionUtil;
+import org.apache.ibatis.io.Resources;
+import org.apache.ibatis.jdbc.ScriptRunner;
+import org.apache.ibatis.session.SqlSession;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.InputStreamReader;
+import java.sql.Connection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+
+public class OceanBaseMyBatisTest
+{
+
+
+ @Before
+ public void setUp() throws Exception {
+ // 执行SQL脚本
+ try {
+ Connection connection = SqlSessionUtil.openSession().getConnection();
+ ScriptRunner runner = new ScriptRunner(connection);
+ runner.runScript(new InputStreamReader(Resources.getResourceAsStream("init.sql")));
+ SqlSessionUtil.openSession().commit();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ public void test() {
+ insertTest(SqlSessionUtil.openSession());
+ updateTest(SqlSessionUtil.openSession());
+ selectTest(SqlSessionUtil.openSession());
+ selectWithPagination(SqlSessionUtil.openSession(), 0, 2);
+ deleteTest(SqlSessionUtil.openSession());
+ }
+
+
+
+ public static void insertTest(SqlSession sqlSession) {
+ // Insert data
+ User user = new User();
+ user.setName("Tom");
+ int count = sqlSession.insert("com.oceanbase.samples.mapper.UserMapper.insert", user);
+ System.out.println("Insert count: " + count);
+
+ }
+
+ public static void updateTest(SqlSession sqlSession) {
+ // Update data
+ User user = new User();
+ user.setId(1);
+ user.setName("Jerry");
+ int count = sqlSession.update("com.oceanbase.samples.mapper.UserMapper.update", user);
+ System.out.println("Update count: " + count);
+ }
+
+ public static void selectTest(SqlSession sqlSession) {
+ // Select data
+ List user = sqlSession.selectList("com.oceanbase.samples.mapper.UserMapper.selectUser", 1);
+ user.stream().filter(Objects::nonNull).forEach(System.out::println);
+ }
+
+
+ public static void selectWithPagination(SqlSession sqlSession, int offset, int pageSize) {
+ Map params = new HashMap<>();
+ params.put("offset", offset);
+ params.put("pageSize", pageSize);
+ List users = sqlSession.selectList("com.oceanbase.samples.mapper.UserMapper.selectWithPagination", params);
+ users.stream().filter(Objects::nonNull).forEach(System.out::println);
+ }
+
+ public static void deleteTest(SqlSession sqlSession) {
+ // Delete data
+ int count = sqlSession.delete("com.oceanbase.samples.mapper.UserMapper.delete", 3);
+ System.out.println("Delete count: " + count);
+ }
+
+ @After
+ public void closeSession() {
+ SqlSessionUtil.openSession().close();
+ }
+}
+
+```
+
+
+修改代码中的连接信息,之后你就可以直接使用 run.sh 运行示例代码。
+
+```bash
+sh run.sh
+```
diff --git a/java/mybatis/pom.xml b/java/mybatis/pom.xml
new file mode 100644
index 0000000..1575f2e
--- /dev/null
+++ b/java/mybatis/pom.xml
@@ -0,0 +1,46 @@
+
+ 4.0.0
+
+ com.oceanbase.samples
+ mybatis
+ 1.0-SNAPSHOT
+
+ oceanbase-mysql
+
+
+ UTF-8
+ 1.8
+ 1.8
+
+
+
+
+ mysql
+ mysql-connector-java
+ 8.0.25
+
+
+ org.mybatis
+ mybatis
+ 3.5.4
+
+
+ junit
+ junit
+ 4.13.2
+ test
+
+
+
+
+
+ src/main/resources
+
+ **/**.xml
+ **/**.sql
+
+
+
+
+
diff --git a/java/mybatis/run.sh b/java/mybatis/run.sh
new file mode 100644
index 0000000..0aa77a4
--- /dev/null
+++ b/java/mybatis/run.sh
@@ -0,0 +1,2 @@
+#!/usr/bin/env bash
+mvn test
diff --git a/java/mybatis/src/test/java/com/oceanbase/samples/OceanBaseMyBatisTest.java b/java/mybatis/src/test/java/com/oceanbase/samples/OceanBaseMyBatisTest.java
new file mode 100644
index 0000000..cedfba4
--- /dev/null
+++ b/java/mybatis/src/test/java/com/oceanbase/samples/OceanBaseMyBatisTest.java
@@ -0,0 +1,92 @@
+package com.oceanbase.samples;
+
+
+import com.oceanbase.samples.entity.User;
+import com.oceanbase.samples.util.SqlSessionUtil;
+import org.apache.ibatis.io.Resources;
+import org.apache.ibatis.jdbc.ScriptRunner;
+import org.apache.ibatis.session.SqlSession;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.InputStreamReader;
+import java.sql.Connection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+
+public class OceanBaseMyBatisTest
+{
+
+
+ @Before
+ public void setUp() throws Exception {
+ // 执行SQL脚本
+ try {
+ Connection connection = SqlSessionUtil.openSession().getConnection();
+ ScriptRunner runner = new ScriptRunner(connection);
+ runner.runScript(new InputStreamReader(Resources.getResourceAsStream("init.sql")));
+ SqlSessionUtil.openSession().commit();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ public void test() {
+ insertTest(SqlSessionUtil.openSession());
+ updateTest(SqlSessionUtil.openSession());
+ selectTest(SqlSessionUtil.openSession());
+ selectWithPagination(SqlSessionUtil.openSession(), 0, 2);
+ deleteTest(SqlSessionUtil.openSession());
+ }
+
+
+
+ public static void insertTest(SqlSession sqlSession) {
+ // Insert data
+ User user = new User();
+ user.setName("Tom");
+ int count = sqlSession.insert("com.oceanbase.samples.mapper.UserMapper.insert", user);
+ System.out.println("Insert count: " + count);
+
+ }
+
+ public static void updateTest(SqlSession sqlSession) {
+ // Update data
+ User user = new User();
+ user.setId(1);
+ user.setName("Jerry");
+ int count = sqlSession.update("com.oceanbase.samples.mapper.UserMapper.update", user);
+ System.out.println("Update count: " + count);
+ }
+
+ public static void selectTest(SqlSession sqlSession) {
+ // Select data
+ List user = sqlSession.selectList("com.oceanbase.samples.mapper.UserMapper.selectUser", 1);
+ user.stream().filter(Objects::nonNull).forEach(System.out::println);
+ }
+
+
+ public static void selectWithPagination(SqlSession sqlSession, int offset, int pageSize) {
+ Map params = new HashMap<>();
+ params.put("offset", offset);
+ params.put("pageSize", pageSize);
+ List users = sqlSession.selectList("com.oceanbase.samples.mapper.UserMapper.selectWithPagination", params);
+ users.stream().filter(Objects::nonNull).forEach(System.out::println);
+ }
+
+ public static void deleteTest(SqlSession sqlSession) {
+ // Delete data
+ int count = sqlSession.delete("com.oceanbase.samples.mapper.UserMapper.delete", 3);
+ System.out.println("Delete count: " + count);
+ }
+
+ @After
+ public void closeSession() {
+ SqlSessionUtil.openSession().close();
+ }
+}
diff --git a/java/mybatis/src/test/java/com/oceanbase/samples/entity/User.java b/java/mybatis/src/test/java/com/oceanbase/samples/entity/User.java
new file mode 100644
index 0000000..b0e6615
--- /dev/null
+++ b/java/mybatis/src/test/java/com/oceanbase/samples/entity/User.java
@@ -0,0 +1,49 @@
+package com.oceanbase.samples.entity;
+
+import java.util.Objects;
+
+public class User {
+ private Integer id;
+ private String name;
+
+ public User() {
+ }
+
+ public User(Integer id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ User user = (User) o;
+ return Objects.equals(id, user.id) && Objects.equals(name, user.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, name);
+ }
+
+ @Override
+ public String toString() {
+ return "User{" +
+ "id=" + id +
+ ", name='" + name + '\'' +
+ '}';
+ }
+}
diff --git a/java/mybatis/src/test/java/com/oceanbase/samples/mapper/UserMapper.java b/java/mybatis/src/test/java/com/oceanbase/samples/mapper/UserMapper.java
new file mode 100644
index 0000000..a8ac176
--- /dev/null
+++ b/java/mybatis/src/test/java/com/oceanbase/samples/mapper/UserMapper.java
@@ -0,0 +1,4 @@
+package com.oceanbase.samples.mapper;
+
+public interface UserMapper {
+}
diff --git a/java/mybatis/src/test/java/com/oceanbase/samples/util/SqlSessionUtil.java b/java/mybatis/src/test/java/com/oceanbase/samples/util/SqlSessionUtil.java
new file mode 100644
index 0000000..2abfdf3
--- /dev/null
+++ b/java/mybatis/src/test/java/com/oceanbase/samples/util/SqlSessionUtil.java
@@ -0,0 +1,31 @@
+package com.oceanbase.samples.util;
+
+import org.apache.ibatis.io.Resources;
+import org.apache.ibatis.session.SqlSession;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.apache.ibatis.session.SqlSessionFactoryBuilder;
+
+import java.io.IOException;
+
+/**
+ * SqlSessionUtil
+ */
+public class SqlSessionUtil {
+
+ private SqlSessionUtil() {
+ }
+
+ private static SqlSessionFactory sqlSessionFactory;
+
+ static {
+ try {
+ sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsReader("mybatis-config.xml"));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static SqlSession openSession() {
+ return sqlSessionFactory.openSession();
+ }
+}
diff --git a/java/mybatis/src/test/resources/UserMapper.xml b/java/mybatis/src/test/resources/UserMapper.xml
new file mode 100644
index 0000000..88bc128
--- /dev/null
+++ b/java/mybatis/src/test/resources/UserMapper.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+ delete from user where id = #{id};
+
+
+
+ insert into user (name) values (#{name});
+
+
+
+ update user set name = #{name} where id = #{id};
+
+
diff --git a/java/mybatis/src/test/resources/init.sql b/java/mybatis/src/test/resources/init.sql
new file mode 100644
index 0000000..1956e4c
--- /dev/null
+++ b/java/mybatis/src/test/resources/init.sql
@@ -0,0 +1,15 @@
+CREATE DATABASE IF NOT EXISTS test;
+USE test;
+DROP TABLE IF EXISTS user;
+CREATE TABLE user
+(
+ id INT AUTO_INCREMENT PRIMARY KEY,
+ name VARCHAR(50)
+);
+
+INSERT INTO user (name)
+VALUES ('Bruce');
+INSERT INTO user (name)
+VALUES ('Jack');
+INSERT INTO user (name)
+VALUES ('Tom');
diff --git a/java/mybatis/src/test/resources/mybatis-config.xml b/java/mybatis/src/test/resources/mybatis-config.xml
new file mode 100644
index 0000000..0fc3c1c
--- /dev/null
+++ b/java/mybatis/src/test/resources/mybatis-config.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+