
# 常用操作示例
#### 示例1 创建数据库连接、创建表、插入数据
此示例将演示如何基于GaussDB提供的JDBC接口开发应用程序。执行示例前，需要先加载驱动，驱动加载方法请参见[加载驱动](https://support.huaweicloud.com/centralized-m-comp-devg-v8-gaussdb/gaussdb-81-0371.html#ZH-CN_TOPIC_0000002559099233)。
```
// 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.mysql.jdbc.Driver";
    String sourceURL = "jdbc:mysql://$ip:$port/database?useSSL=false&allowPublicKeyRetrieval=true";
    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();
    }
  }
  /**
   * 主程序，逐步调用各静态方法。
   * @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);
    // 关闭数据库连接。
    try {
      conn.close();
    } catch (SQLException e) {
      e.printStackTrace();
    }
  }
}
```
上述示例的运行结果为：
```
Connection succeed!
```
#### 示例2 批量查询
此示例主要使用setFetchSize调整客户端内存使用，原理是通过数据库游标来分批获取服务端数据，但会加大网络交互，可能会损失部分性能。
由于游标事务内有效，故需要先关闭自动提交，最后执行手动提交。
```
// 认证用的用户名和密码直接写到代码中有很大的安全风险，建议在配置文件或者环境变量中存放（密码应密文存放，使用时解密），确保安全。
// 本示例以用户名和密码保存在环境变量中为例，运行本示例前请先在本地环境中设置环境变量（环境变量名称请根据自身情况进行设置）EXAMPLE_USERNAME_ENV和EXAMPLE_PASSWORD_ENV。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.PreparedStatement;
public class Batch {
    public static void main(String[] args) throws SQLException {
        String driver = "com.mysql.jdbc.Driver";
        String username = System.getenv("EXAMPLE_USERNAME_ENV");
        String passwd = System.getenv("EXAMPLE_PASSWORD_ENV");
        String sourceURL = "jdbc:mysql://$ip:$port/database?useSSL=false&allowPublicKeyRetrieval=true";
        Connection conn = null;
        try {
            // 加载数据库驱动。
            Class.forName(driver).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            // 创建数据库连接。
            conn = DriverManager.getConnection(sourceURL, username, passwd);
            System.out.println("Connection succeed!");
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 关闭自动提交。
        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);
        int fetchCount = 0;
        ResultSet rs = st.executeQuery("SELECT * FROM mytable");
        while (rs.next()) {
            fetchCount++;
        }
        System.out.println(fetchCount == 200);
        conn.commit();
        rs.close();
        // 关闭服务器游标。
        st.setFetchSize(0);
        fetchCount = 0;
        rs = st.executeQuery("SELECT * FROM mytable");
        while (rs.next()) {
            fetchCount++;
        }
        System.out.println(fetchCount == 200);
        conn.commit();
        rs.close();
        // Close the statement.
        st.close();
        conn.close();
    }
}
```
上述示例的运行结果为：
```
Connection succeed!
true
true
```
执行完毕后可执行如下命令恢复自动提交。
```
conn.setAutoCommit(true);
```
#### 示例3 常用数据类型使用
```
// 认证用的用户名和密码直接写到代码中有很大的安全风险，建议在配置文件或者环境变量中存放（密码应密文存放，使用时解密），确保安全。
// 本示例以用户名和密码保存在环境变量中为例，运行本示例前请先在本地环境中设置环境变量（环境变量名称请根据自身情况进行设置）EXAMPLE_USERNAME_ENV和EXAMPLE_PASSWORD_ENV。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.sql.CallableStatement;
import java.sql.SQLException;
import java.sql.PreparedStatement;
import java.sql.Types;
public class Type {
    public static void main(String[] args) throws SQLException {
        String driver = "com.mysql.jdbc.Driver";
        String username = System.getenv("EXAMPLE_USERNAME_ENV");
        String passwd = System.getenv("EXAMPLE_PASSWORD_ENV");
        String sourceURL = "jdbc:mysql://$ip:$port/database?useSSL=false&allowPublicKeyRetrieval=true";
        Connection conn = null;
        try {
            // 加载数据库驱动。
            Class.forName(driver).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            // 创建数据库连接。
            conn = DriverManager.getConnection(sourceURL, username, passwd);
            System.out.println("Connection succeed!");
        } catch (Exception e) {
            e.printStackTrace();
        }
        Statement st = conn.createStatement();
        // bit类型使用示例。
        st.execute("create table if not exists t_bit(col_bit bit)");
        PreparedStatement pstm1 = conn.prepareStatement("insert into t_bit values(?)");
        pstm1.setBoolean(1,true);
        pstm1.execute();
        pstm1.close();
        ResultSet rs1 = st.executeQuery(" select col_bit from t_bit;");
        while (rs1.next()) {
            System.out.println(rs1.getBoolean(1));
        }
        rs1.close();
        // float8类型使用示例。
        st.execute("create table if not exists t_float(col1 float8)");
        PreparedStatement pstm2 = conn.prepareStatement("insert into t_float values(?)");
        pstm2.setDouble(1, 123456.123);
        pstm2.execute();
        pstm2.close();
        ResultSet rs2 = st.executeQuery(" select col1 from t_float;");
        while (rs2.next()) {
            System.out.println(rs2.getDouble(1));
        }
        rs2.close();
        st.close();
        // 关闭数据库连接。
        try {
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
```
上述示例的运行结果为：
```
Connection succeed!
false
123456.123
```
#### 示例4 使用流式读功能
流式读功能：读取数据时，服务端一次获取全部数据，发送到客户端socket缓冲区中，缓冲区占满则暂停，有空余则继续向缓冲区中发送数据，同时JVM逐行从缓冲区中读取数据。
优势是处理结果快，不会造成JVM内存溢出。劣势是只能向后遍历，数据处理完毕之前或者statement关闭之前，当前连接不能执行其他操作。
```
// 认证用的用户名和密码直接写到代码中有很大的安全风险，建议在配置文件或者环境变量中存放（密码应密文存放，使用时解密），确保安全。
// 本示例以用户名和密码保存在环境变量中为例，运行本示例前请先在本地环境中设置环境变量（环境变量名称请根据自身情况进行设置）EXAMPLE_USERNAME_ENV和EXAMPLE_PASSWORD_ENV。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Stream {
    // 创建数据库连接。
    public static Connection getConnection(String username, String passwd) {
        String driver = "com.mysql.jdbc.Driver";
        String sourceURL = "jdbc:mysql://$ip:$port/database?useSSL=false&allowPublicKeyRetrieval=true";
        Connection conn = null;
        try {
            //加载驱动。
            Class.forName(driver);
        } 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语句，创建t_user表。
    public static void CreateTable(Connection conn) {
        Statement stmt = null;
        try {
            stmt = conn.createStatement();
            //执行普通SQL语句。
            stmt.executeUpdate("DROP TABLE IF EXISTS t_user");
            stmt.executeUpdate("CREATE TABLE t_user(id int, name VARCHAR(20));");
            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 t_user VALUES (?,?)");
            for (int i = 0; i < 20; i++) {
                //添加参数。
                pst.setInt(1, i + 1);
                pst.setString(2, "name " + (i + 1));
                pst.addBatch();
            }
            //执行批处理。
            pst.executeBatch();
            pst.close();
        } catch (SQLException e) {
            if (pst != null) {
                try {
                    pst.close();
                } catch (SQLException e1) {
                    e1.printStackTrace();
                }
            }
            e.printStackTrace();
        }
    }
    // 开启流式读，查询t_user表中内容。
    public static void StreamingQuery(Connection conn) {
        PreparedStatement pst = null;
        ResultSet resultSet = null;
        try {
            // 查询表t_user中的所有值。
            pst = conn.prepareStatement("SELECT * FROM t_user");
            pst.setFetchSize(Integer.MIN_VALUE);
            resultSet = pst.executeQuery();
            while (resultSet.next()) {
                System.out.println(resultSet.getInt(1));
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            if (resultSet != null) {
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    throw new RuntimeException(e);
                }
            }
            if (pst != null) {
                try {
                    pst.close();
                } catch (SQLException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
    public static void main(String[] args) throws Exception {
        String userName = System.getenv("EXAMPLE_USERNAME_ENV");
        String password = System.getenv("EXAMPLE_PASSWORD_ENV");
        Connection conn = getConnection(userName, password);
        CreateTable(conn);
        BatchInsertData(conn);
        StreamingQuery(conn);
        //关闭数据库连接。
        try {
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
```
上述示例的运行结果为：
```
Connection succeed!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
```
![](https://support.huaweicloud.com/centralized-m-comp-devg-v8-gaussdb/public_sys-resources/notice_3.0-zh-cn.png)
使用流式读功能时，结果集使用完之后，需要执行resultSet.close()或者statement.close()操作，否则当前连接将不可用。
