本篇文章想跟大家分享一下,各种主流开发语言如何连接到 OceanBase 社区版数据库,进行日常开发。这个问题也是社区群里面问的比较多的一个问题之一,希望通过本篇文章,能给各位参与开发的小伙伴提供一些指导。

0. 前置条件

首先我们在 OceanBase test 数据库中创建一个 t1 表,并向里面插入 2 条数据,用作后面所有语言的测试基础表:

1. Java 数据库连接驱动(JDBC)

首先上来肯定要说一下 Java,说 Java 是第一大应用开发语言应该不为过吧?OceanBase 社区版对 MySQL 5.7 的兼容性最好,所以您可以使用 MySQL 5.7 的 JDBC 包(建议使用 mysql-connector-java-5.1.47 版本,MySQL 5.7 对应的 JDBC 版本为 5.1.x),也可以使用 OceanBase 提供的自有 JDBC 包,下面我们分别用代码演示一个简单的示例。

Java 数据库连接(JDBC)是一种 API,它使 Java 能够将 SQL 语句发送到对象关系数据库,如 Oracle、MySQL 数据库。JDBC 支持为 Java 暴露 SQL 数据类型,并快速访问 SQL 数据。

1.1 MySQL JDBC 连接 Demo

我们首先从 https://downloads.mysql.com/archives/c-j/ 下载对应的 5.1.47 的 jar 包,创建一个新的 Demo 项目,把刚才的 jar 包加载到类库中,然后用最朴素的 Java 代码执行增删改查操作,如下:

import java.sql.*;
public class JavaDemo {public static void main(String[] args) throws ClassNotFoundException,SQLException {//1.加载驱动Class.forName("com.mysql.jdbc.Driver");//固定写法,加载驱动//2.用户信息和urlString url="jdbc:mysql://10.211.55.73:2883/test?useUnicode=true&characterEncoding=utf8&&useSSL=true";String username = "root";String password = "observer";//3.连接成功,连接数据库对象 ConnectionConnection connection = DriverManager.getConnection(url,username,password);//4.执行SQL对象 StatementStatement statement = connection.createStatement();//5.执行SQL可能存在的结果,查看返回的结果System.out.println("-------------------当前查询到的数据如下-------------------");ResultSet resultSet = statement.executeQuery("SELECT * FROM t1");//返回的结果集,封装了查询出来的全部结果while(resultSet.next()) {System.out.println("id="+resultSet.getObject("id"));System.out.println("name="+resultSet.getObject("NAME"));}System.out.println("-------------------当前数据库的行数如下-------------------");ResultSet curCount = statement.executeQuery("select count(*) from t1");while(curCount.next()) {System.out.println("当前数据库有数据 "+curCount.getInt(1)+" 行!");}System.out.println("-------------------向该数据库中插入数据-------------------");String insertSql = "insert into t1 values(3,'c')";statement.execute(insertSql);//返回的结果System.out.println("-------------------插入数据后的行数如下-------------------");ResultSet afinCount = statement.executeQuery("select count(*) from t1");while(afinCount.next()) {System.out.println("当前数据库有数据 "+afinCount.getInt(1)+" 行!");}System.out.println("-------------------尝试更新插入进去的数据-------------------");Integer updCount = statement.executeUpdate("update t1 set id=4 where name='c'");System.out.println("更新了 "+updCount+" 行数据!");System.out.println("-------------------尝试进行数据删除-------------------");Boolean del = statement.execute("delete from t1 where name = 'c'");ResultSet afdelCount = statement.executeQuery("select count(*) from t1");while(afdelCount.next()) {System.out.println("当前数据库有数据 "+afdelCount.getInt(1)+" 行!");}//6.释放连接resultSet.close();statement.close();connection.close();}
}

执行结果也一目了然,没问题:

1.2 OB 自研 JDBC 连接 Demo

OceanBase 官方提供了自研的 JDBC 包,名字叫做:oceanbase-client-1.1.10.jar。选用这个包的话,整体的操作方法跟 1.1 部分类似,主要区别为驱动加载和 url 部分的定义

 //1.加载驱动Class.forName("com.alipay.oceanbase.jdbc.Driver");//固定写法,加载驱动//2.用户信息和urlString url="jdbc:oceanbase://10.211.55.73:2883/test";

按照惯例来说,官方自研的 JDBC 驱动在性能和语法兼容性上肯定会更好,当然我没有真正测过性能,大家可以自己测测试试。下面是一个完整 Demo 的增删改查代码:

import java.sql.*;public class JavaOBDemo {public static void main(String[] args) throws ClassNotFoundException,SQLException {//1.加载驱动Class.forName("com.alipay.oceanbase.jdbc.Driver");//固定写法,加载驱动//2.用户信息和urlString url="jdbc:oceanbase://10.211.55.73:2883/test";String username = "root";String password = "observer";//3.连接成功,连接数据库对象 ConnectionConnection connection = DriverManager.getConnection(url,username,password);//4.执行SQL对象 StatementStatement statement = connection.createStatement();//5.执行SQL可能存在的结果,查看返回的结果System.out.println("-------------------当前查询到的数据如下-------------------");ResultSet resultSet = statement.executeQuery("SELECT * FROM t1");//返回的结果集,封装了查询出来的全部结果while(resultSet.next()) {System.out.println("id="+resultSet.getObject("id"));System.out.println("name="+resultSet.getObject("NAME"));}System.out.println("-------------------当前数据库的行数如下-------------------");ResultSet curCount = statement.executeQuery("select count(*) from t1");while(curCount.next()) {System.out.println("当前数据库有数据 "+curCount.getInt(1)+" 行!");}System.out.println("-------------------向该数据库中插入数据-------------------");String insertSql = "insert into t1 values(3,'c')";statement.execute(insertSql);//返回的结果System.out.println("-------------------插入数据后的行数如下-------------------");ResultSet afinCount = statement.executeQuery("select count(*) from t1");while(afinCount.next()) {System.out.println("当前数据库有数据 "+afinCount.getInt(1)+" 行!");}System.out.println("-------------------尝试更新插入进去的数据-------------------");Integer updCount = statement.executeUpdate("update t1 set id=4 where name='c'");System.out.println("更新了 "+updCount+" 行数据!");System.out.println("-------------------尝试进行数据删除-------------------");Boolean del = statement.execute("delete from t1 where name = 'c'");ResultSet afdelCount = statement.executeQuery("select count(*) from t1");while(afdelCount.next()) {System.out.println("当前数据库有数据 "+afdelCount.getInt(1)+" 行!");}//6.释放连接resultSet.close();statement.close();connection.close();}
}

有关 OB 自研 JDBC 的参数调优,请参考官方文档:https://open.oceanbase.com/docs/observer-cn/V3.1.4/10000000000450598

1.3 对常用框架的支持

这也是个经常被问到的问题,我在社区群中不止一次看到有人问 OceanBase 对通用框架/连接池支持怎么样?大家想想,OB 在阿里内部及很多企业级客户都有很深入的应用了,对通用框架的支持已经不会是一个大问题了,简言之:支持的很不错。下面我列举几个官方给出的常用框架支持方式,供大家参考:

1.3.1 MyBatis 连接示例

MyBatis 作为一款应用量排名靠前的框架,深受大家的喜爱。下面给出了一些常用的配置信息,供您参考:

配置依赖

<dependency><groupId>com.alipay.oceanbase</groupId><artifactId>oceanbase-client</artifactId><version>3.2.3</version>
</dependency>
<dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.4</version>
</dependency>

mybatis-config.xml 配置文件

<?xml version="1.0" encoding="UTF8"?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.alipay.oceanbase.jdbc.Driver"/><property name="url" value="jdbc:oceanbase://10.100.xxx.xxx:18817/test?useUnicode=true&amp;characterEncoding=utf-8&amp;useServerPrepStmts=false&amp;useCursorFetch=true"/><property name="username" value="admin@mysql"/><property name="password" value="admin"/></dataSource></environment></environments><!--注册mapper(mapper.xml所在地址)--><mappers><mapper resource="com/test/UserMapper.xml"></mapper></mappers>
</configuration>

mapper.xml 配置文件

<?xml version="1.0" encoding="UTF8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace 是mapper接口,不能填错-->
<mapper namespace="com.test.UserMapper"><select id="selectUser" resultType="com.test.User" fetchSize="40000">select * from user;</select><delete id="delete" >delete from user;</delete>
</mapper>

1.3.2 HiKariCP 连接池配置示例

HiKariCP 以代码轻量且速度非常快著称,以下信息展示了 OceanBase 与该框架的集成方法:

配置依赖 pom.xml

<dependency><groupId>com.alipay.oceanbase</groupId><artifactId>oceanbase-client</artifactId><version>3.2.3</version>
</dependency>
<dependency><groupId>com.zaxxer</groupId><artifactId>HikariCP</artifactId><version>3.3.1</version>
</dependency>

配置文件 jdbc.properties

jdbcUrl=jdbc:oceanbase://10.100.xxx.xxx:18817/test?useSSL=false&useServerPrepStmts=true&serverTimezone=UTC
username=admin@mysql
password=admin
dataSource.cachePrepStmts=true
dataSource.prepStmtCacheSize=250
dataSource.prepStmtCacheSqlLimit=2048
dataSource.useServerPrepStmts=true
dataSource.useLocalSessionState=true
dataSource.rewriteBatchedStatements=true
dataSource.cacheResultSetMetadata=true
dataSource.cacheServerConfiguration=true
dataSource.elideSetAutoCommits=true
dataSource.maintainTimeStats=false

示例代码

 @Testpublic void hikariTest() throws SQLException {HikariConfig config = new HikariConfig("/jdbc.properties");Connection conn = new HikariDataSource(config).getConnection();PreparedStatement drop_table_data_test = conn.prepareStatement("drop table data_test");Statement stmt = conn.createStatement();try {drop_table_data_test.execute();} catch (SQLException e) {}conn.prepareStatement("create table data_test(test1 int)").execute();for (int i = 0; i <= 10; i++) {stmt.executeUpdate("insert into data_test values("+i+")");}ResultSet rs = conn.prepareStatement("select * from data_test;").executeQuery();while (rs.next()){System.out.print(rs.getObject(1)+"\t");}System.out.println();System.out.println("------------------------");stmt.executeUpdate("update data_test set test1 = 100;");ResultSet rs1 = conn.prepareStatement("select * from data_test;").executeQuery();while (rs1.next()){System.out.print(rs1.getObject(1)+"\t");}System.out.println();System.out.println("------------------------");stmt.executeUpdate("delete from data_test");ResultSet rs2 = stmt.executeQuery("select * from data_test;");if (!rs2.next()){System.out.println("数据删除成功");}stmt.close();drop_table_data_test.execute();drop_table_data_test.close();rs.close();conn.close();}

1.3.3 SpringJDBC 连接示例

SpringJDBC 是老牌的持久层框架了,下面也来一个简单的 Demo:

配置依赖

<dependency><groupId>com.alipay.oceanbase</groupId><artifactId>oceanbase-client</artifactId><version>3.2.3</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.0.9.RELEASE</version>
</dependency>

示例代码

预加载静态代码块(为方便测试,此处使用 druid 连接池):

static {Map<String, String> map = new HashMap<String, String>();map.put("url", "jdbc:oceanbase://10.100.xxx.xxx:18815/test");map.put("driverClassName", "com.alipay.oceanbase.jdbc.Driver");map.put("username", "admin@mysql");map.put("password", "admin");try {Class.forName(map.get("driverClassName"));jdbcTemplate = new JdbcTemplate(DruidDataSourceFactory.createDataSource(map));//防止异常语句,没有这两句,会出错jdbcTemplate.execute("set transaction_isolation = 'READ-COMMITTED';");jdbcTemplate.execute("set tx_isolation = 'READ-COMMITTED';");} catch (Exception e) {e.printStackTrace();}
}
 @Testpublic void createByOrcTypeDate(){sql ="create table D_DPRECORD(DEV_ID VARCHAR2(50),"+"CAR_SPEED NUMBER(3),"+"CAP_DATE TIMESTAMP WITH LOCAL TIME ZONE," +"DEV_CHNID VARCHAR2(50) not null," +"TRSFMARK NUMBER(1) default 0," +"CREATE_TIME DATE default sysdate" +");";jdbcTemplate.execute(sql);}
 @Testpublic void addTest(){int i = 1;for (;i<=100;i++){sql = "insert into orc_type_test values ("+i+",'测试数据"+i+"');";jdbcTemplate.execute(sql);}}
 @Testpublic void selectTest(){sql = "select * from orc_type_test;";List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql);for (Map<String,Object> m : maps){System.out.println(m);}}
 @Testpublic void rownumQueryTest() {sql = "select * from D_DPRECORD where rownum <=70 minus (select * from D_DPRECORD where rownum<60);";List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql);for (Map<String, Object> m : maps) {System.out.println(m);}}

1.3.4 其他连接池和框架

这里引入介绍了部分内容,因为 Java 的连接池和框架太多了,所以为了保持篇幅不至于太冗长,不一一列举了,如果大家对其他内容感兴趣,欢迎参考官方文档的《设计规范和约束》–> 《数据库设计最佳实践》中的连接池和框架部分。

2. C/C++ 语言数据库连接驱动

OceanBase Connector/C 是一个基于 C/C++ 的 OceanBase 客户端开发组件,支持 C API Lib 库,我们通常也叫它 libobclient 。允许 C/C++ 程序以一种较为底层的方式访问 OceanBase 分布式数据库集群,以进行数据库连接、数据访问、错误处理和 Prepared Statement 处理等操作。当然您也可以使用 MySQL 官方的客户端开发组件:MySQL C API。但是优先推荐采用 libobclient 进行开发。

2.1 安装 libobclient

在使用该库之前,我们需要先在对应的服务器上安装,例如执行如下命令,从 OceanBase 远程仓库安装,并复制一份到 lib64:

sudo yum install libobclient
sudo cp -r /u01/obclient/lib/libobclnt.so.20 /usr/lib64/

2.2 C++ 语言 Demo

完成了上面的基础库安装后,下面我们还是通过一个例子来展示如何编写 C++ 代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include "mysql.h"using namespace std;void process_result_set(MYSQL *mysql, MYSQL_RES *result)
{printf("row nums: %d\n", mysql_num_rows(result)); //获取行数int j = mysql_num_fields(result);MYSQL_ROW row = mysql_fetch_row(result);// 输出每行结果if (row) {for (int i = 0; i < j; i++) {printf("%s \n", row[i]);}if (mysql_errno(mysql)) {printf("retrive faile: %s\n", mysql_error(mysql));return;}}
}
int main()
{mysql_library_init(0, NULL, NULL);MYSQL *mysql = mysql_init(NULL);char host[] = "10.211.55.73"; char user[] = "root";char passwd[] = "observer";char db[] = "test"; //没有数据库可以选择NULLunsigned int port = 2883;// 使用obclient连接ob的方式如下// obclient -h123.10.12.123 -P2883 -uroot@sys -pobserver/* 使用 CLIENT_MULTI_STATEMENTS 选项连接服务器 (必选)*/if (mysql_real_connect (mysql, host, user, passwd,NULL, port, NULL, CLIENT_MULTI_STATEMENTS) == NULL){printf("mysql_real_connect() failed\n");mysql_close(mysql);mysql_library_end();exit(1);}/*执行多条语句 */int status = mysql_query(mysql,"show parameters like '%obconfig_url%';");if (status){printf("Could not execute statement(s), ret = %d\n", status);mysql_close(mysql);mysql_library_end();exit(0);}/* 处理每个语句的结果 */do {/* 当前语句是否返回数据? */MYSQL_RES* result = mysql_store_result(mysql);if (result){/* 是的; 则处理行并释放结果集 */process_result_set(mysql, result); // 处理执行成功的语句mysql_free_result(result);}else          /* 没有结果集或报错 */{if (mysql_field_count(mysql) == 0){printf("%lld rows affected\n",mysql_affected_rows(mysql));}else  /* 发生报错 */{printf("Could not retrieve result set\n");break;}}/* 是否有更多结果? -1 = 否,>0 = 报错,0 = 是(继续循环)*/if ((status = mysql_next_result(mysql)) > 0)printf("Could not execute statement\n");} while (status == 0);mysql_close(mysql);mysql_library_end();return 0;
}

编译执行返回的结果如下:

[chris@obd ~]$ g++ test.cpp -I /u01/obclient/include -L /u01/obclient/lib -lobclnt -o test
[chris@obd ~]$ ./test
row nums: 3
zone3
observer
10.211.55.76
2882
obconfig_url
(null)URL for OBConfig service
OBSERVER
CLUSTER
DEFAULT
DYNAMIC_EFFECTIVE

4. Python 连接数据库指南

Python 在很多场景下被大量使用,大家所熟知的 OceanBase Deployer,即 obd 也是用 Python 开发的。我们可以通过两个不同的库(Python 2 和 Python 3 有所区别)连接到 OceanBase。下面分别展开:

4.1 Python 3 连接方式

官方推荐在 Python 3 环境下,选用 PyMySQL 库来连接 OceanBase,首先如果您本地没有下载该库,需要先执行 pip 进行安装:

python3 -m pip install PyMySQL

安装完成后,可以通过如下代码进行数据库访问,主要就是注意 import 库的导入:

import pymysqlconn = pymysql.connect(host="10.211.55.73", port=2883,user="root", passwd="observer", db="test")try:with conn.cursor() as cur:cur.execute('SELECT * FROM t1')rows = cur.fetchall()for row in rows:print(f'{row[0]} {row[1]}')finally:conn.close()

执行如上代码返回结果也正常:

4.2 Python 2 连接方式

MySQL-python 是 Python2.X 版本中用于连接 MySQL 服务器的一个库。官方推荐采用该库在 Python 2 上连接 OceanBase。

首先也是需要手工安装该库:

sudo pip install MySQL-python

示例代码及返回结果如下:

import MySQLdbconn= MySQLdb.connect(host='10.211.55.73',port = 2883,user='root',passwd='observer',db ='test'
)try:cur = conn.cursor()cur.execute('SELECT * from t1')ans = cur.fetchall()print(ans)finally:conn.close()
[chris@obd ~]$ python test.py
((1L, 'a'), (2L, 'b'))

5. Golang 驱动链接 OceanBase Demo

在 Golang 开发环境下,推荐采用 Go-SQL-Driver/MySQL 来进行连接。这要求 Go 的版本要在 1.13 之上。

5.1 下载对应的库

go get -u github.com/go-sql-driver/mysql

5.2 Demo 演示

package mainimport ("database/sql""fmt""log"_ "github.com/go-sql-driver/mysql"
)type TS struct {Id         intName       string
}func select_all() {conn := "root:obsever@tcp(10.211.55.73:2883)/test"db, err := sql.Open("mysql", conn)if err != nil {log.Fatal(err)}defer db.Close()if err != nil {log.Fatal(err)}res, err := db.Query("SELECT * FROM t1")if err != nil {log.Fatal(err)}defer res.Close()if err != nil {log.Fatal(err)}for res.Next() {var t TSerr := res.Scan(&t.Id, &t.Name)if err != nil {log.Fatal(err)}fmt.Printf("%v\n", t)}
}func main() {select_all()
}

执行结果截图如下,此处注意环境变量 GO111MODULE的设置,否则会去查找 mod 文件并导致无法执行:

各种语言如何连接到 OceanBase相关推荐

  1. 意出望外的一次相遇|利楚初探 OceanBase

    武汉利楚商务服务有限公司(简称"利楚")成立于 2011 年,是国内最早从事聚合支付技术研发和应用的高新技术企业之一,也是国内领先的商户数字化经营运营商.旗下拥有聚合支付中台&qu ...

  2. python编程小游戏-python趣味入门——写几个常玩的游戏

    文档介绍 利用python写"猜数字","猜词语","谁是卧底"这三个游戏,从而快速掌握python编程的入门知识,包括python语法/列 ...

  3. ChunJunOceanBase联合方案首次发布:构建一体化数据集成方案

    8月27日,ChunJun社区与OceanBase社区联合组织的开源线下Meetup成功举办,会上重磅发布了「OceanBase&ChunJun:构建一体化数据集成方案」. 这是OceanBa ...

  4. 桌面图标icon替换客制图标。图标要比原始图标大,要求一致。应用图标去掉四周白边,保持原有比例。

    /vendor/mediatek/proprietary/packages/apps/Launcher3/ src/com/android/launcher3/icons/IconCache.java ...

  5. macos 切换账户_如何在macOS上设置访客用户帐户

    macos 切换账户 If you loan your Mac to a friend or family member, even for a short time, you may not wan ...

  6. python简单小游戏代码-python基础练习之几个简单的游戏

    文档介绍 利用python写"猜数字","猜词语","谁是卧底"这三个游戏,从而快速掌握python编程的入门知识,包括python语法/列 ...

  7. Win11 22000.918(KB5016691)正式版发布,解决一系列问题!

    微软于今日发布了Win11 22000.918新版本系统,此次更新解决了与 USB 打印相关和阻止 Windows 11 SE 信任某些 Microsoft Store 应用程序等问题,想要了解更多的 ...

  8. python基础编程练习_python基础练习之几个简单的游戏

    文档介绍 利用python写"猜数字","猜词语","谁是卧底"这三个游戏,从而快速掌握python编程的入门知识,包括python语法/列 ...

  9. 利用python制作几个简单的游戏

    文档介绍 利用python写"猜数字","猜词语","谁是卧底"这三个游戏,从而快速掌握python编程的入门知识,包括python语法/列 ...

  10. python简单游戏程序-python基础练习之几个简单的游戏

    文档介绍 利用python写"猜数字","猜词语","谁是卧底"这三个游戏,从而快速掌握python编程的入门知识,包括python语法/列 ...

最新文章

  1. matlab反馈模型,—倒立摆状态反馈系统的建模及matlab仿真.docx
  2. 深度探索C++ 对象模型(3)-默认构造函数Default Constructor
  3. 以游戏演绎1200多年前的古诗——《画境长恨歌》叙事设计思路分享
  4. java+redis+lua生成自动增长的ID序列号
  5. 电池供电的电容麦_太阳能航空障碍灯供电机制设计
  6. 30 分钟带你学透快应用界面开发的最正确姿势
  7. java 静态传值到构造器_java 静态初始化块,初始化块,构造器执行顺序
  8. border-radius导致overflow:auto 或者 overflow:hidden失效,溢出问题解决方法
  9. 下载EPM包详细运行日志
  10. Python模块 - itertools循环器模块
  11. java web 机试_java web 机试
  12. javascript的对象内容对比
  13. 20190226杂七杂八
  14. Qt三方库开发技术:Qt应用内部打开PDF文件
  15. 测井曲线wis文件格式转换为ASCII文本格式小软件的开发(C与Python结合开发)
  16. HI3519移植samba服务器
  17. linux 打开关闭CPU超线程和查看逻辑CPU的个数
  18. Roaring Bitmap 原理及实践
  19. 浏览器有网微信没网络连接服务器,电脑可以登陆微信但是浏览器无法联网是怎么回事儿...
  20. Android笔记本处理器,惠普或推Android笔记本:配Tegra处理器

热门文章

  1. 我的2011--衣带渐宽终不悔,为伊消得人憔悴
  2. css flex实现经典的三栏布局
  3. 中药学(综合练习)题库【1】
  4. 使用matlab导入excel表格带有时间的数据并绘制曲线
  5. 用Hight-Speed Charting绘制时间电压动态曲线
  6. AMD处理器的发展历程
  7. 有符号数的二进制表示方式
  8. 面部皮肤200种问题_史上最全的皮肤病图谱,我竟然全部看完了……
  9. 数据库的挂起(suspending)和恢复(resuming)
  10. web学习(3)--别踩白块儿(HTML版)(web入门)