1.Base基础/3.Icon图标/操作/search备份
1.Base基础/3.Icon图标/操作/search备份
EN
文档
关于AntDB
部署与升级
快速入门
使用教程
SQL语言
Oracle兼容
分布式功能
驱动使用说明
运维
调优
工具和插件
高级服务
数据安全
参考
  • 文档首页 /
  • 使用教程 /
  • 驱动使用说明 /
  • 基于JDBC

基于JDBC

更新时间:2024-07-01 14:39:47

JDBC

环境要求

安装环境对应版本的的 java:yum install java

#以JDK8为例
[antdb@host227 ~]$ cat /etc/redhat-release 
CentOS Linux release 7.5.1804 (Core) 
[antdb@host227 ~]$ java -version
openjdk version "1.8.0_222"
OpenJDK Runtime Environment (build 1.8.0_222-b10)
OpenJDK 64-Bit Server VM (build 25.222-b10, mixed mode)

数据库访问权限配置

集中式环境通过修改 pg_hba.conf 文件配置数据库访问权限;

分布式环境通过 MGR 的 ADD HBA 命令配置数据库访问权限。

驱动获取

AntDB 提供的 JDBC 的驱动的下载地址为:AntDB 的 tar 包安装完成后,数据库程序目录(二进制目录)下应该的 client_driver 文件中:

[antdb@localhost]$ cd /home/antdb/app/client_driver
[antdb@localhost client_driver]$ ll
总用量 0
drwxr-xr-x 2 antdb antdb 146  2月 28 10:17 adbjre
drwxr-xr-x 3 antdb antdb  17  2月 28 10:17 adbodbc
drwxr-xr-x 3 antdb antdb  17  2月 28 10:17 psycopg2
drwxr-xr-x 6 antdb antdb  56  2月 28 10:17 unixODBC

# 其中 adbjre 目录下有最新的JDBC驱动:
[antdb@localhost]$ cd /home/antdb/app/client_driver/adbjre
[antdb@localhost adbjre]$ ll
总用量 4200
-rwxr-xr-x 1 antdb antdb 847827  2月 28 10:17 AntDB-1.0.4.jre6.jar
-rwxr-xr-x 1 antdb antdb 854187  2月 28 10:17 AntDB-1.0.4.jre7.jar
-rwxr-xr-x 1 antdb antdb 876188  2月 28 10:17 AntDB-1.0.4.jre8.jar
-rwxr-xr-x 1 antdb antdb 847676  2月 28 10:17 AntDB-2.0.4.jre7.jar
-rwxr-xr-x 1 antdb antdb 870071  2月 28 10:17 AntDB-2.0.4.jre8.jar

JDBC url 连接串

AntDB_jdbc 提供了以下几个 url 连接串,用于连接 AntDB 数据库:

不指定grammar,默认grammar为postgres
jdbc:antdb://${ip}:${port}/${dbname}
指定grammar
jdbc:antdb://${ip}:${port}/${dbname}?grammar=postgres
jdbc:antdb://${ip}:${port}/${dbname}?grammar=oracle

也可对接 pg 数据库:

jdbc:antdb://${ip}:${port}/${dbname}

通过 JDBC 访问数据库的例子

数据库驱动类名
net.antdb.Driver

创建测试用户和测试数据库:

连接到数据库
antdb=# CREATE USER jdbc_usr WITH ENCRYPTED PASSWORD 'jdbc@123' superuser;
CREATE ROLE
antdb=# CREATE DATABASE jdbc_db OWNER jdbc_usr;
CREATE DATABASE

测试程序代码:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class insert_conn {
    //创建数据库连接。
    public static void main(String[] args) throws SQLException,ClassNotFoundException {
        String url = "jdbc:antdb://10.20.16.227:9876/postgres";
        String user = "antdb";
        String password = "xxxx";
        Connection conn = null;
        try {
            System.out.println("connect start");
            //加载数据库驱动。
            Class.forName("net.antdb.Driver");
            //创建数据库连接。
            conn = DriverManager.getConnection(url, user, password);
            System.out.println("connect ok");
            /**
            * 创建表t1
            * 向表t1中插入10条数据
            */
            PreparedStatement psmt = conn.prepareStatement("drop table if exists test cascade");
            psmt.execute();
            System.out.println("drop ok");
            psmt = conn.prepareStatement("create table t1(c1 int not null primary key, c2 text)");
            psmt.execute();
            System.out.println("create ok");
            psmt = conn.prepareStatement("insert into t1 values (1, 'a'),(2,'b'),(3,'c'),(4,'d'),(5,'e'),(6,'f'),(7,'g'),(8,'h'),(9,'i'),(10,'j')");
            psmt.execute();
            System.out.println("insert ok");
            psmt.close();
            //关闭数据库连接。
            conn.close();
            System.out.println("close ok");
        }catch (SQLException ex)
        {
            ex.getStackTrace();
            ex.getMessage();
        }finally {
            if(conn != null) {
                conn.close();
            }
        }
    }
}

编译和运行测试程序

[antdb@host227 test]$ ll
total 916
-rw-r--r-- 1 antdb antdb 931537 Feb 13 16:55 AntDB-2.0.0.jre8.jar
-rw-rw-r-- 1 antdb antdb   1698 Feb 13 17:33 insert_conn.java
[antdb@host227 test]$ javac -cp AntDB-2.0.0.jre8.jar:. insert_conn.java 
[antdb@host227 test]$ java -ea -cp AntDB-2.0.0.jre8.jar:. insert_conn
connect start
Feb 13, 2023 5:44:51 PM org.postgresql.jdbc.PgConnection setGrammarOperation
INFO: set to postgres
connect ok
drop ok
create ok
insert ok
close ok

验证程序运行结果:

[antdb@host227 test]$ adb -d postgres -p 9876 
psql (13.3)
Type "help" for help.

antdb=# \dt
       List of relations
 Schema | Name | Type  | Owner 
--------+------+-------+-------
 public | t1   | table | antdb
(1 row)

antdb=# SELECT * FROM t1;
 c1 | c2 
----+----
  1 | a
  2 | b
  3 | c
  4 | d
  5 | e
  6 | f
  7 | g
  8 | h
  9 | i
 10 | j
(10 rows)

查看和修改事务自动提交

在 Java 中可以使用如下语句进行 autocommit 的查看和设置:

System.out.print("default autocommit is "+connection.getAutoCommit()+"\n"); 
connection.setAutoCommit(false); 
System.out.print("current autocommit is "+connection.getAutoCommit()+"\n");

执行后,输出如下:

default autocommit is true 
current autocommit is false 

在程序中使用的时候,建议设置 autocommit 为 false,手动去控制事务,便于进行业务逻辑的控制。

子事务处理

在数据库事务中,顶层事务控制着各个层次的事务,而嵌套在顶层事务下的事务被称为子事务。子事务控制着每个局部的变化,它可以提交也可以回滚,但其提交操作并不马上生效,只有在其父事务提交后才真正提交。同样,任意一个事务的回滚也会引起它的所有子事务一同回滚。JDBC 支持子事务功能,通过两个设置 autosave 和 cleanupSavepoints 来限制子事务的回滚和提交。autosave 参数控制子事务保存点的自动设置与自动回滚,cleanupSavepoints 参数控制子事务保存点的自动清理。

参数配置

参数组合
  • 不指定 autosave 和 cleanupSavepoints,默认 autosave 为 never,cleanupSavepoints 为 false。

  • 当 autosave 参数设置为 never ,cleanupSavepoints 参数可以为 ture 和 false 任意状态。

  • 当 autosave 参数设置为 always 或 conservative 时,cleanupSavepoints 参数只能设置为 true ,否则通过JDBC与数据库连接建立失败,出现报错:

    net.antdb.util.PsOLException: Invalid parameter value, when autosave is enabled, cleanupsavepoints must be true .
    
  • 子事务处理参数配置 url 连接串示例:

    不指定autosave和cleanupSavepoints,默认autosave为never,cleanupSavepoints为false
    jdbc:antdb://${ip}:${port}/${dbname}
    指定autosave和cleanupSavepoints(示例)
    jdbc:antdb://${ip}:${port}/${dbname}?autosave=always&cleanupSavepoints=true
    

参数说明

参数定义

autosave (string) default never:指定驱动程序在查询失败时应该采取的行为,不指定该参数时默认autosave = never。

  • autosave = always:每次执行查询之前都会设置一个保存点,并在查询出现异常时自动回滚到该保存点。

  • autosave = never:不设置保存点。执行出现异常时不执行回滚操作。

  • autosave=conservative:仅在特定情况下每次执行查询之前都会设置一个保存点,执行自动回滚。例如,当发生像"缓存的语句不能更改返回类型"或"语句 XXX 无效"这样的错误时才会执行回滚操作。

cleanupSavepoints (boolean) default false:清理保存点,决定在自动保存模式下创建的 SAVEPOINT 是否在语句之前释放。不指定该参数时默认 cleanupSavepoints = false。

  • cleanupSavepoints = true:在事务提交或回滚后,自动清理先前设置的保存点。

  • cleanupSavepoints = false:不自动清理保存点,保存点将保留在事务结束后。

参数设置建议
  • autosave 参数:建议用户设置为 always。

  • cleanupSavepoints 参数:建议设置为 true。

子事务相关参数使用示例

下述示例验证了autosave = always,cleanupSavepoints = true 时查询失败能够回滚到自动创建的保存点并能继续执行接下来操作,父事务不中断,只回滚该条失败的子事务,并且不影响前面已提交的子事务的场景。

测试程序代码:

import java.sql.*;

public class test {
	//定义连接参数。
    public static void main(String[] args) throws SQLException {
        String url1 = "jdbc:antdb://10.20.16.227:32003/postgres?autosave=always&cleanupSavepoints=true";
        //不指定 autosave 和 cleanupSavepoints
        String url2 = "jdbc:antdb://10.20.16.227:32003/postgres;
		/**
    	*验证 autosave=always,cleanupSavepoints=true 的情况下,插入数据异常(主键冲突),子事务能回滚到自动创建的保存点并能继续执行子事务操作,事务不中断。
    	*/
		test001(url1);
	}
	//插入数据异常(主键冲突),子事务执行失败,回滚到查询前自动创建的保存点。
	//创建数据库连接。
	public static void test001(String url) throws SQLException {
        String user = "mengzp";
        String password = "xxx";
        Connection conn = null;
        try {
            System.out.println("connect start");
            //创建数据库连接。
            conn = DriverManager.getConnection(url, user, password);
            //关闭自动提交,方便进行子事务测试。
            conn.setAutoCommit(false);
            System.out.println("connect ok");
            /**
            * 创建表test(c1字段设置为主键)
            * 向表test中插入10条数据
            */
            PreparedStatement psmt = conn.prepareStatement("drop table if exists test cascade");
            psmt.execute();
            System.out.println("drop ok");
            psmt = conn.prepareStatement("create table test(c1 int not null primary key, c2 text)");
            psmt.execute();
            System.out.println("create ok");
            psmt = conn.prepareStatement("insert into test values (1, 'a'),(2,'你好'),(3,'c'),(4,'测试'),(5,'e'),(6,'10'),(7,'g'),(8,'写作'),(9,'i'),(10,'j')");
            psmt.execute();
            System.out.println("insert ok");
            //数据插入成功
            psmt = conn.prepareStatement("select * from test order by c1");
            ResultSet rs = psmt.executeQuery();
            while (rs.next()) {
                System.out.println("c1="+rs.getInt(1)+";c2="+rs.getString(2));
            }
            System.out.println("select ok");
            try {
            	//模拟插入数据异常(主键冲突),子事务执行失败,回滚到查询前自动创建的保存点。
                psmt = conn.prepareStatement("insert into test values (1, 'a'),(11,'你好'),(12,'c')");
                psmt.executeQuery();
            } catch (SQLException ex) {
                ex.printStackTrace();
                System.out.println(ex.getStackTrace());
                System.out.println(ex.getMessage());
                System.out.println("insert fail");
            }
            psmt.close();
            //提交事务。因为在服务端可以连接数据库,可以查询到test表,test表包含十条数据。
            conn.commit();
            conn.close();
            System.out.println("close ok");
        } catch (SQLException ex) {
            ex.printStackTrace();
            System.out.println(ex.getStackTrace());
            System.out.println(ex.getMessage());
        } finally {
            if (conn != null) {
                conn.close();
            }
        }
    }
}
import java.sql.*;

public class test {
	//定义连接参数。
    public static void main(String[] args) throws SQLException {
        String url2 = "jdbc:antdb://10.20.16.227:32003/postgres;
		//对比验证:不设置 autosave,cleanupSavepoints 参数默认关闭情况下,插入数据异常(主键冲突),事务中止,提交事务后父事务回滚。
		test002(url2);
	}
    //插入数据异常(主键冲突)导致事务中断,子事务执行失败,回滚整个事务。
    //创建数据库连接。
    public static void test002(String url) throws SQLException {
        String user = "mengzp";
        String password = "xxx";
        Connection conn = null;
        try {
            System.out.println("connect start");
            //创建数据库连接。
            conn = DriverManager.getConnection(url, user, password);
            //关闭自动提交,方便进行子事务测试。
            conn.setAutoCommit(false);
            System.out.println("connect ok");
            /**
            * 创建表test(c1字段设置为主键)
            * 向表test中插入10条数据
            */
            PreparedStatement psmt = conn.prepareStatement("drop table if exists t2 cascade");
            psmt.execute();
            System.out.println("drop ok");
            psmt = conn.prepareStatement("create table t2(c1 int not null primary key, c2 text)");
            psmt.execute();
            System.out.println("create ok");
            psmt = conn.prepareStatement("insert into t2 values (1, 'a'),(2,'你好'),(3,'c'),(4,'测试'),(5,'e'),(6,'10'),(7,'g'),(8,'写作'),(9,'i'),(10,'j')");
            psmt.execute();
            System.out.println("insert ok");
            //数据插入成功
            psmt = conn.prepareStatement("select * from t2 order by c1");
            ResultSet rs = psmt.executeQuery();
            while (rs.next()) {
                System.out.println("c1="+rs.getInt(1)+";c2="+rs.getString(2));
            }
            System.out.println("select ok");
            try {
            	//模拟插入数据异常(主键冲突),子事务执行失败,事务中止。
                psmt = conn.prepareStatement("insert into t2 values (1, 'a'),(11,'你好'),(12,'c')");
                psmt.executeQuery();
            } catch (SQLException ex) {
                ex.printStackTrace();
                System.out.println(ex.getStackTrace());
                System.out.println(ex.getMessage());
                System.out.println("insert fail");
            }
            psmt.close();
            //提交事务。由于主键冲突导致事务中断,未创建保存点,整个事务回滚,表t2未创建成功,在服务端连接数据库查询不到t2表。
            conn.commit();
            conn.close();
            System.out.println("close ok");
        } catch (SQLException ex) {
            ex.printStackTrace();
            System.out.println(ex.getStackTrace());
            System.out.println(ex.getMessage());
        } finally {
            if (conn != null) {
                conn.close();
            }
        }
    }
}

验证程序运行结果:

test001:test 表创建成功,并成功插入十条数据。
test002:t2 表创建失败。
[mengzp@host227 ~]$ adb -d postgres -p 32003
psql (6.3.20 based on PG 13.3)
Type "help" for help.

antdb=# \dt
       List of relations
 Schema | Name | Type  | Owner
--------+------+-------+--------
 public | test | table | mengzp
(1 row)

antdb=# select * from test order by c1;
 c1 |  c2
----+------
  1 | a
  2 | 你好
  3 | c
  4 | 测试
  5 | e
  6 | 10
  7 | g
  8 | 写作
  9 | i
 10 | j
(10 rows)
问题反馈