更新时间:2024-08-20 GMT+08:00

示例:常用操作

示例1 创建数据库连接、创建表、插入数据

此示例将演示如何基于GaussDB提供的JDBC接口开发应用程序。执行示例前,需要加载驱动,驱动的获取和加载方法请参见JDBC包、驱动类和环境类

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
// DBTest.java
// 演示基于JDBC开发的主要步骤,会涉及创建数据库连接、创建表、插入数据等。
// 认证用的用户名和密码直接写到代码中有很大的安全风险,建议在配置文件或者环境变量中存放(密码应密文存放,使用时解密),确保安全。
// 本示例以用户名和密码保存在环境变量中为例,运行本示例前请先在本地环境中设置环境变量(环境变量名称请根据自身情况进行设置)EXAMPLE_USERNAME_ENV和EXAMPLE_PASSWORD_ENV。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.CallableStatement;
import java.sql.Types;

public class DBTest {

  // 创建数据库连接。
  public static Connection GetConnection(String username, String passwd) {
    String driver = "com.huawei.gaussdb.jdbc.Driver";
    String sourceURL = "jdbc:gaussdb://$ip:$port/database";
    Connection conn = null;
    try {
      // 加载数据库驱动。
      Class.forName(driver).newInstance();
    } catch (Exception e) {
      e.printStackTrace();
      return null;
    }

    try {
      // 创建数据库连接。
      conn = DriverManager.getConnection(sourceURL, username, passwd);
      System.out.println("Connection succeed!");
    } catch (Exception e) {
      e.printStackTrace();
      return null;
    }

    return conn;
  };

  // 执行普通SQL语句,创建customer_t1表。
  public static void CreateTable(Connection conn) {
    Statement stmt = null;
    try {
      stmt = conn.createStatement();

      // 执行普通SQL语句。
      int rc = stmt
          .executeUpdate("CREATE TABLE customer_t1(c_customer_sk INTEGER, c_customer_name VARCHAR(32));");

      stmt.close();
    } catch (SQLException e) {
      if (stmt != null) {
        try {
          stmt.close();
        } catch (SQLException e1) {
          e1.printStackTrace();
        }
      }
      e.printStackTrace();
    }
  }

  // 执行预处理语句,批量插入数据。
  public static void BatchInsertData(Connection conn) {
    PreparedStatement pst = null;

    try {
      // 生成预处理语句。
      pst = conn.prepareStatement("INSERT INTO customer_t1 VALUES (?,?)");
      for (int i = 0; i < 3; i++) {
        // 添加参数。
        pst.setInt(1, i);
        pst.setString(2, "data " + i);
        pst.addBatch();
      }
      // 执行批处理。
      pst.executeBatch();
      pst.close();
    } catch (SQLException e) {
      if (pst != null) {
        try {
          pst.close();
        } catch (SQLException e1) {
        e1.printStackTrace();
        }
      }
      e.printStackTrace();
    }
  }

  // 执行预编译语句,更新数据。
  public static void ExecPreparedSQL(Connection conn) {
    PreparedStatement pstmt = null;
    try {
      pstmt = conn
          .prepareStatement("UPDATE customer_t1 SET c_customer_name = ? WHERE c_customer_sk = 1");
      pstmt.setString(1, "new Data");
      int rowcount = pstmt.executeUpdate();
      pstmt.close();
    } catch (SQLException e) {
      if (pstmt != null) {
        try {
          pstmt.close();
        } catch (SQLException e1) {
          e1.printStackTrace();
        }
      }
      e.printStackTrace();
    }
  }

  // 新建存储过程。
  public static void CreateCallable(Connection conn) {
    Statement stmt = null;
    try {
      stmt = conn.createStatement();
      // 新建函数,返回三个输入值的和。
      stmt.execute("create or replace procedure testproc \n" +
          "(\n" +
          "    psv_in1 in integer,\n" +
          "    psv_in2 in integer,\n" +
          "    psv_inout inout integer\n" +
          ")\n" +
          "as\n" +
          "begin\n" +
          "    psv_inout := psv_in1 + psv_in2 + psv_inout;\n" +
          "end;\n" +
          "/");
    } catch (SQLException e) {
      throw new RuntimeException(e);
    } finally {
      if (stmt != null) {
        try {
          stmt.close();
        } catch (SQLException e) {
          throw new RuntimeException(e);
        }
      }
    }
  }

  // 执行存储过程。
  public static void ExecCallableSQL(Connection conn) {
    CallableStatement cstmt = null;
    try {
      // 存储过程TESTPROC需提前创建。
      cstmt=conn.prepareCall("{? = CALL TESTPROC(?,?,?)}");
      cstmt.setInt(2, 50); 
      cstmt.setInt(1, 20);
      cstmt.setInt(3, 90);
      cstmt.registerOutParameter(4, Types.INTEGER);  // 注册out类型的参数,类型为整型。
      cstmt.execute();
      int out = cstmt.getInt(4);  // 获取out参数。
      System.out.println("The CallableStatment TESTPROC returns:"+out);
      cstmt.close();
    } catch (SQLException e) {
      if (cstmt != null) {
        try {
          cstmt.close();
        } catch (SQLException e1) {
          e1.printStackTrace();
        }
      }
      e.printStackTrace();
    }
  }
  

  /**
   * 主程序,逐步调用各静态方法。
   * @param args
  */
  public static void main(String[] args) {
    // 创建数据库连接。
    String userName = System.getenv("EXAMPLE_USERNAME_ENV");
    String password = System.getenv("EXAMPLE_PASSWORD_ENV");
    Connection conn = GetConnection(userName, password);

    // 创建表。
    CreateTable(conn);

    // 批量插入数据。
    BatchInsertData(conn);

    // 执行预编译语句,更新数据。
    ExecPreparedSQL(conn);

    // 新建存储过程。
    CreateCallable(conn);

    // 执行存储过程。
    ExecCallableSQL(conn);

    // 关闭数据库连接。
    try {
      conn.close();
    } catch (SQLException e) {
      e.printStackTrace();
    }

  }

}

示例2 客户端内存占用过多解决

此示例主要使用setFetchSize调整客户端内存使用,原理是通过数据库游标来分批获取服务器端数据,但会加大网络交互,可能会损失部分性能。

由于游标事务内有效,故需要先关闭自动提交,最后执行手动提交。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// 关闭自动提交。
conn.setAutoCommit(false);

// 新建表。
Statement st = conn.createStatement();
st.execute("create table mytable (cal1 int);");

// 表中插入200行数据。
PreparedStatement pstm = conn.prepareStatement("insert into mytable values (?)");
for (int i = 0; i < 200; i++) {
    pstm.setInt(1, i + 1);
    pstm.addBatch();
}
pstm.executeBatch();
conn.commit();
pstm.close();

// 打开游标,每次获取50行数据。
st.setFetchSize(50);
ResultSet rs = st.executeQuery("SELECT * FROM mytable");
while (rs.next()){
    System.out.println("a row was returned.");
}
conn.commit();
rs.close();

// 关闭服务器游标。
st.setFetchSize(0);
rs = st.executeQuery("SELECT * FROM mytable");
while (rs.next()){
    System.out.println("many rows were returned.");
}
conn.commit();
rs.close();

// Close the statement.
st.close();
conn.close();

执行完毕后可执行如下命令恢复自动提交。

conn.setAutoCommit(true);

示例3 常用数据类型使用

// 前置操作。
String createsql = "create table if not exists t_bit(col_bit bit)";
Statement stmt = conn.createStatement();
stmt.execute(createsql);
stmt.close();
// bit类型使用示例,注意此处bit类型取值范围[0,1]。
Statement st = conn.createStatement();
String sqlstr = "create or replace function fun_1()\n" +
    "returns bit AS $$\n" +
    "select col_bit from t_bit limit 1;\n" +
    "$$\n" +
    "LANGUAGE SQL;";
st.execute(sqlstr);
CallableStatement c = conn.prepareCall("{ ? = call fun_1() }");
// 注册输出类型,位串类型。
c.registerOutParameter(1, Types.BIT);
c.execute();
// 使用Boolean类型获取结果。
System.out.println(c.getBoolean(1));

// float8类型使用示例。
st.execute("create table if not exists t_float(col1 float8)");
PreparedStatement pstm = conn.prepareStatement("insert into t_float values(?)");
pstm.setDouble(1,123456.123);
pstm.execute();
pstm.close();

// 函数返回值为float8的使用示例。
st.execute("create or replace function func_float() " +
    "return float8 " +
    "as declare " +
    "var1 float8; " +
    "begin " +
    " select col1 into var1 from t_float limit 1; " +
    " return var1; " +
    "end;");
CallableStatement cs = conn.prepareCall("{? = call func_float()}");
cs.registerOutParameter(1,Types.DOUBLE);
cs.execute();
System.out.println(cs.getDouble(1));
st.close();

示例4 数据库连接监控功能使用

此示例将演示如何使用JDBC驱动的连接监控功能。

// 以下用例以gaussdbjdbc.jar为例。
// 认证用的用户名和密码直接写到代码中有很大的安全风险,建议在配置文件或者环境变量中存放(密码应密文存放,使用时解密),确保安全。
// 本示例以用户名和密码保存在环境变量中为例,运行本示例前请先在本地环境中设置环境变量(环境变量名称请根据自身情况进行设置)EXAMPLE_USERNAME_ENV和EXAMPLE_PASSWORD_ENV。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class DBMonitorTest {
    // 创建数据库连接。
    public static void main(String[] args){
        String driver = "com.huawei.gaussdb.jdbc.Driver";
        String username = System.getenv("EXAMPLE_USERNAME_ENV");
        String passwd = System.getenv("EXAMPLE_PASSWORD_ENV");
        String sourceURL
            = "jdbc:gaussdb://$ip:$port/database?dbMonitor=true&loggerLevel=debug&loggerFile=dbMonitor.log";
        try {
            // 加载数据库驱动。
            Class.forName(driver).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }

        Connection conn = null;
        Statement statement = null;
        try {
            // 创建数据库连接。
            conn = DriverManager.getConnection(sourceURL, username, passwd);

            // 创建表。
            statement = conn.createStatement();
            String createTableQuery = "CREATE TABLE IF NOT EXISTS mytable (id INT PRIMARY KEY, name VARCHAR(50))";
            statement.executeUpdate(createTableQuery);

            // 插入数据。
            String insertQuery = "INSERT INTO mytable (id, name) VALUES (1, 'John')";
            statement.executeUpdate(insertQuery);

            // 查询数据。
            String selectQuery = "SELECT * FROM mytable ";
            ResultSet resultSet = statement.executeQuery(selectQuery);
            while (resultSet.next()) {
                int id = resultSet.getInt("id");
                String name = resultSet.getString("name");
                System.out.println("id: " + id + ", name: " + name);
            }

            // 删除表。
            String dropTableQuery = "DROP TABLE IF EXISTS mytable";
            statement.executeUpdate(dropTableQuery);
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (statement != null) {
                    statement.close();
                }
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

在日志文件dbMonitor.log中可以看到输出的连接监控信息,具体包括:

Nov 23, 2023 10:30:54 AM com.huawei.gaussdb.jdbc.qos.DataProcess saveQosResult
FINE: {
   "Destination host:port" : "localhost:8000",--服务器的IP和端口。
   "Delay" : "1.00 ms",--网络时延。
   "Jitter" : "0.04ms",--网络抖动。
   "Loss" : "0%",--网络丢包率。
   "DownloadSpeed" : "0.395Mbps",--网络下行速率。
   "UpLoadSpeed" : "0.498Mbps"--网络上行速率。
}

Nov 23, 2023 10:30:56 AM com.huawei.gaussdb.jdbc.CollectDBData saveCollectResult
FINE: {
   "openCount": "1",--应用开启数据库连接的次数。
   "closeCount": "1",--应用关闭数据库连接的次数。
   "abortedCount": "0",--连接异常断开的次数。
   "visitCount": "12",--应用对数据库的访问量。
   "cpuUsage": "20.39%",--客户端机器CPU的使用率。
   "memoryUsage": "98.32%"--客户端机器内存的使用率。
}

示例5 获取驱动版本

Driver.getGSVersion();