
# 创建和调用存储过程
此示例将演示如何基于GaussDB提供的JDBC接口开发应用程序。本示例演示如何连接数据库、创建和调用存储过程。
代码运行的前提条件：根据实际情况添加opengaussjdbc.jar包（例如用户使用IDE执行代码，则需要在本地IDE添加opengaussjdbc.jar包）。
```
// 认证用的用户名和密码直接写到代码中有很大的安全风险，建议在配置文件或者环境变量中存放(密码应密文存放，使用时解密)，确保安全；
// 本示例以用户名和密码保存在环境变量中为例，运行本示例前请先在本地环境中设置环境变量(环境变量名称请根据自身情况进行设置)EXAMPLE_USERNAME_ENV和EXAMPLE_PASSWORD_ENV。
// $ip、$port、database需要用户自行修改。
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.opengauss.jdbc.Driver";
    String sourceURL = "jdbc:opengauss://$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;
  };
  
  // 创建存储过程。
  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 {
      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);
    // 创建存储过程。
    CreateCallable(conn);
    //执行存储过程。
    ExecCallableSQL(conn);
    //关闭数据库连接。
    try {
      conn.close();
    } catch (SQLException e) {
      e.printStackTrace();
    }
  }
}
```
上述示例的运行结果为：
```
Connection succeed!
The CallableStatment TESTPROC returns:160
```
