华为云用户手册

  • 通过本地文件导入导出数据 在使用JAVA语言基于 GaussDB 进行二次开发时,可以使用CopyManager接口,通过流方式,将数据库中的数据导出到本地文件或者将本地文件导入数据库中,文件格式支持 CS V、TEXT等格式。 代码运行的前提条件: 根据实际情况添加opengaussjdbc.jar包(例如用户使用IDE执行代码,则需要在本地IDE添加opengaussjdbc.jar包)。 在数据库中创建表migration_table和migration_table_1,并在migration_table表中插入数据。 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 // 认证用的用户名和密码直接写到代码中有很大的安全风险,建议在配置文件或者环境变量中存放(密码应密文存放,使用时解密),确保安全。 // 本示例以用户名和密码保存在环境变量中为例,运行本示例前请先在本地环境中设置环境变量(环境变量名称请根据自身情况进行设置)EXAMPLE_USERNAME_ENV和EXAMPLE_PASSWORD_ENV。 // $ip、$port、database需要用户自行修改。 import java.sql.Connection; import java.sql.DriverManager; import java.io.IOException; import java.io.FileInputStream; import java.io.FileOutputStream; import java.sql.SQLException; import com.huawei.opengauss.jdbc.copy.CopyManager; import com.huawei.opengauss.jdbc.core.BaseConnection; public class Copy{ public static void main(String[] args) { String urls = new String("jdbc:opengauss://$ip:$port/database"); //数据库URL String username = System.getenv("EXAMPLE_USERNAME_ENV"); //用户名 String password = System.getenv("EXAMPLE_PASSWORD_ENV"); //密码 String tablename = new String("migration_table"); //定义表信息 String tablename1 = new String("migration_table_1"); //定义表信息 String driver = "com.huawei.opengauss.jdbc.Driver"; Connection conn = null; try { Class.forName(driver); conn = DriverManager.getConnection(urls, username, password); } catch (ClassNotFoundException e) { e.printStackTrace(System.out); } catch (SQLException e) { e.printStackTrace(System.out); } // 将SELECT * FROM migration_table查询结果导出到本地文件d:/data.txt try { copyToFile(conn, "d:/data.txt", "(SELECT * FROM migration_table)"); } catch (SQLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } //将d:/data.txt中的数据导入到migration_table_1中。 try { copyFromFile(conn, "d:/data.txt", tablename1); } catch (SQLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } // 将migration_table_1中的数据导出到本地文件d:/data1.txt try { copyToFile(conn, "d:/data1.txt", tablename1); } catch (SQLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } // 使用copyIn把数据从文件中导入数据库, public static void copyFromFile(Connection connection, String filePath, String tableName) throws SQLException, IOException { FileInputStream fileInputStream = null; try { CopyManager copyManager = new CopyManager((BaseConnection)connection); fileInputStream = new FileInputStream(filePath); copyManager.copyIn("COPY " + tableName + " FROM STDIN", fileInputStream); } finally { if (fileInputStream != null) { try { fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } } // 使用copyOut把数据从数据库中导出到文件中 public static void copyToFile(Connection connection, String filePath, String tableOrQuery) throws SQLException, IOException { FileOutputStream fileOutputStream = null; try { CopyManager copyManager = new CopyManager((BaseConnection)connection); fileOutputStream = new FileOutputStream(filePath); copyManager.copyOut("COPY " + tableOrQuery + " TO STDOUT", fileOutputStream); } finally { if (fileOutputStream != null) { try { fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } } } 上述示例的运行结果为:本地d盘两个文件data.txt和data1.txt、数据库表migration_table_1,和数据库表migration_table数据相同。 父主题: 典型应用开发示例
  • 获取函数返回值 JDBC调用函数时获取返回值,以下示例展示返回值类型为bit和float8两种数据类型,其他数据类型可参考本示例。 代码运行的前提条件:根据实际情况添加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.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.huawei.opengauss.jdbc.Driver"; String username = System.getenv("EXAMPLE_USERNAME_ENV"); String passwd = System.getenv("EXAMPLE_PASSWORD_ENV"); String sourceURL = "jdbc:opengauss://$ip:$port/database"; 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(); } // 建表。 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(); // 关闭数据库连接。 try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } 上述示例的运行结果为: Connection succeed! false 123456.123 当前JDBC不支持调用返回数据类型为money的存储过程和函数。 父主题: 典型应用开发示例
  • 创建和调用存储过程 此示例将演示如何基于GaussDB提供的JDBC接口开发应用程序。本示例演示如何连接数据库、创建和调用存储过程。 代码运行的前提条件:根据实际情况添加opengaussjdbc.jar包(例如用户使用IDE执行代码,则需要在本地IDE添加opengaussjdbc.jar包)。 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 // 认证用的用户名和密码直接写到代码中有很大的安全风险,建议在配置文件或者环境变量中存放(密码应密文存放,使用时解密),确保安全; // 本示例以用户名和密码保存在环境变量中为例,运行本示例前请先在本地环境中设置环境变量(环境变量名称请根据自身情况进行设置)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 父主题: 典型应用开发示例
  • 自动寻主场景 某客户存在一套集中式数据库实例,包含1主2备三个节点{node1,node2,node3},其中node1为主节点,node2、node3为备节点。 客户希望应用连接能建立在主DN上,并在发生主备切换时,自动选择新的主节点建连,则url可参考如下配置: jdbc:opengauss://node1,node2,node3/database?targetServerType=master
  • 高性能场景 某客户对于相同sql可能多次执行,仅是传参不同,为了提升执行效率,可开启prepareThreshold参数,避免重复生成执行计划,url可参考如下配置。 jdbc:opengauss://node1/database?prepareThreshold=5 某客户一次查询1000万数据,为避免同时返回造成内存溢出,可使用defaultRowFetchSize,url可参考如下配置。 jdbc:opengauss://node1/database?defaultRowFetchSize=50000 某客户需要批量插入1000万数据,为提升效率,可使用batchMode,url可参考如下配置。 jdbc:opengauss://node1/database?batchMode=on
  • 容灾场景 某客户有两套数据库实例,其中A数据库实例为生产数据库实例,B数据库实例为容灾数据库实例。当客户执行容灾切换时,A数据库实例将降为容灾数据库实例,B数据库实例将升为生产数据库实例。此时为了避免修改配置文件导致的应用重启或重新发版。客户可在初始配置文件时,即将A、B数据库实例写入连接串中。此时在主数据库实例不可连接时,驱动将尝试对容灾数据库实例建连。例如A数据库实例为{node1,node2,node3}。B数据库实例为{node4,node5,node6}。 则url可参考如下进行配置: jdbc:opengauss://node1,node2,node3,node4,node5,node6/database?priorityServers=3
  • 获取结果集中的数据 ResultSet对象提供了丰富的方法,以获取结果集中的数据。获取数据常用的方法如表4所示,其他方法请参考JDK官方文档。 表4 ResultSet对象的常用方法 方法 描述 getInt(int columnIndex) 按列标获取int型数据。 getInt(String columnLabel) 按列名获取int型数据。 getString(int columnIndex) 按列标获取String型数据。 getString(String columnLabel) 按列名获取String型数据。 getDate(int columnIndex) 按列标获取Date型数据 getDate(String columnLabel) 按列名获取Date型数据。
  • 获取结果集中光标的位置 对于可滚动的结果集,可调用定位方法来改变光标的位置。JDBC驱动程序提供了获取结果集中光标所处位置的方法。获取光标位置的方法如表3所示。 表3 获取结果集光标的位置 方法 描述 isFirst() 是否在第一行。 isLast() 是否在最后一行。 isBeforeFirst() 是否在第一行之前。 isAfterLast() 是否在最后一行之后。 getRow() 获取当前在第几行。
  • 在结果集中定位 ResultSet对象具有指向其当前数据行的光标。最初,光标被置于第一行之前,next方法将光标移动到下一行。因为该方法在ResultSet对象没有下一行时返回false,所以可以在while循环中使用它来迭代结果集。但对于可滚动的结果集,JDBC驱动程序提供更多的定位方法,使ResultSet指向特定的行。定位方法如表2所示。 表2 在结果集中定位的方法 方法 描述 next() 把ResultSet向下移动一行。 previous() 把ResultSet向上移动一行。 beforeFirst() 把ResultSet定位到第一行之前。 afterLast() 把ResultSet定位到最后一行之后。 first() 把ResultSet定位到第一行。 last() 把ResultSet定位到最后一行。 absolute(int row) 把ResultSet移动到参数指定的行数。 relative(int rows) rows为正数表示把ResultSet向下移动rows行,rows为负数表示把ResultSet向上移动(-rows)行。
  • 设置结果集类型 不同类型的结果集有各自的应用场景,应用程序需要根据实际情况选择相应的结果集类型。在执行SQL语句过程中,需要先创建相应的语句对象,而部分创建语句对象的方法提供了设置结果集类型的功能。具体的参数设置如表1所示。涉及的Connection的方法如下: 1 2 3 4 5 6 7 8 //创建一个Statement对象,该对象将生成具有给定类型和并发性的ResultSet对象。 createStatement(int resultSetType, int resultSetConcurrency); //创建一个PreparedStatement对象,该对象将生成具有给定类型和并发性的ResultSet对象。 prepareStatement(String sql, int resultSetType, int resultSetConcurrency); //创建一个CallableStatement对象,该对象将生成具有给定类型和并发性的ResultSet对象。 prepareCall(String sql, int resultSetType, int resultSetConcurrency); 表1 结果集类型 参数 描述 resultSetType 表示结果集的类型,具体有三种类型: ResultSet.TYPE_FORWARD_ONLY:ResultSet只能向前移动。是缺省值。 ResultSet.TYPE_SCROLL_SENSITIVE:在修改后重新滚动到修改所在行,可以看到修改后的结果。 ResultSet.TYPE_SCROLL_INSENSITIVE:对可修改例程所做的编辑不进行显示。 说明: 结果集从数据库中读取了数据之后,即使类型是ResultSet.TYPE_SCROLL_SENSITIVE,也不会看到由其他事务在这之后引起的改变。调用ResultSet的refreshRow()方法,可进入数据库并从其中取得当前游标所指记录的最新数据。 resultSetConcurrency 表示结果集的并发,具体有两种类型: ResultSet.CONCUR_READ_ONLY:如果不从结果集中的数据建立一个新的更新语句,不能对结果集中的数据进行更新。 ResultSet.CONCUR_UPDATEABLE:可改变的结果集。对于可滚动的结果集,可对结果集进行适当的改变。
  • 创建和调用存储过程(入参为复合数据类型) 以下用例展示A兼容模式下,入参为复合数据类型的存储过程创建和调用情况。前置条件是数据库建连完成、连接对象为conn。 创建存储过程test_proc如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 // 在数据库创建复合数据类型。 CREATE TYPE compfoo AS (f1 int, f3 text); // 在数据库中创建如下存储过程,它带有out参数。 create or replace procedure test_proc ( psv_in in compfoo, psv_out out compfoo ) as begin psv_out := psv_in; end; / 调用存储过程test_proc如下: 设置参数behavior_compat_options='proc_outparam_override'后,调用Connection的prepareCall方法创建调用语句对象cs。 1 2 3 Statement statement = conn.createStatement(); statement.execute("set behavior_compat_options='proc_outparam_override'"); CallableStatement cs = conn.prepareCall("{ CALL TEST_PROC(?,?) }"); 调用CallableStatement的set方法设置参数。 1 2 3 4 PGobject pGobject = new PGobject(); pGobject.setType("public.compfoo"); // 设置复合类型名,格式为“schema.typename”。 pGobject.setValue("(1,demo)"); // 绑定复合类型值,格式为“(value1,value2)”。 cs.setObject(1, pGobject); 调用CallableStatement的registerOutParameter方法注册输出参数。 1 2 // 注册out类型的参数,类型为复合类型,格式为“schema.typename”。 cs.registerOutParameter(2, Types.STRUCT, "public.compfoo"); 调用CallableStatement的execute方法执行SQL语句。 1 cs.execute(); 调用CallableStatement的getObject方法获取输出参数。 1 2 3 4 PGobject result = (PGobject)cs.getObject(2); // 获取out参数 result.getValue(); // 获取复合类型字符串形式值。 result.getArrayValue(); //获取复合类型数组形式值,以复合数据类型字段顺序排序。 result.getStruct(); //获取复合类型子类型名,按创建顺序排序。 调用CallableStatement的close方法关闭调用语句对象cs。 1 cs.close(); A兼容模式开启参数后,调用存储过程必须使用{call proc_name(?,?)}形式调用,调用函数必须使用{? = call func_name(?,?)}形式调用(等号左侧的“?”为函数返回值的占位符,用于注册函数返回值)。 参数behavior_compat_options='proc_outparam_override'变更后,业务需要重新建立连接,否则无法正确调用存储过程和函数。 函数和存储过程中包含复合类型时,参数的绑定与注册需要使用schema.typename形式。
  • 执行预编译SQL语句 预编译语句是只编译和优化一次,可以通过设置不同的参数值多次使用。由于已经预先编译好,后续使用会减少执行时间。因此,如果多次执行一条语句,请选择使用预编译语句。 前置条件是执行以上的预处理语句,customer_t1表已经批量插入数据。执行预编译SQL语句,更新数据的命令如下: 调用Connection接口的prepareStatement方法创建预编译语句对象pstmt。 1 PreparedStatement pstmt = conn.prepareStatement("UPDATE customer_t1 SET c_customer_name = ? WHERE c_customer_sk = 1"); 调用PreparedStatement接口的setString方法设置参数。 1 pstmt.setString(1, "new Data"); 调用PreparedStatement接口的executeUpdate方法执行预编译SQL语句。 1 int rowcount = pstmt.executeUpdate(); 调用PreparedStatement接口的close方法关闭预编译语句对象pstmt。 1 pstmt.close(); PrepareStatement设置绑定参数后,最终会构建成一个B报文或U报文,在下一步执行SQL语句时发给服务端。但是B报文或U报文有最大长度限制(不能超过1023MB),如果一次绑定数据过大,可能因报文过长导致异常。因此PrepareStatement设置绑定参数时需要注意评估和控制绑定数据的大小,避免出现超出报文上限要求的现象。
  • 创建和调用存储过程 GaussDB支持通过JDBC调用存储过程,前置条件是数据库建连完成、连接对象为conn。 创建存储过程testproc如下: 1 2 3 4 5 6 7 8 9 10 11 12 //在数据库中创建如下存储过程,它带有out参数。 create or replace procedure testproc ( psv_in1 in integer, psv_in2 in integer, psv_inout inout integer ) as begin psv_inout := psv_in1 + psv_in2 + psv_inout; end; / 调用存储过程testproc如下: 调用Connection的prepareCall方法创建调用语句对象cstmt。 1 CallableStatement cstmt = conn.prepareCall("{? = CALL TESTPROC(?,?,?)}"); 调用CallableStatement的setInt方法设置参数。 1 2 3 cstmt.setInt(2, 50); cstmt.setInt(1, 20); cstmt.setInt(3, 90); 调用CallableStatement的registerOutParameter方法注册输出参数。 1 cstmt.registerOutParameter(4, Types.INTEGER); //注册out类型的参数,类型为整型。 调用CallableStatement的execute方法执行SQL语句。 1 cstmt.execute(); 调用CallableStatement的getInt方法获取out输出参数。 1 int out = cstmt.getInt(4); 调用CallableStatement的close方法关闭调用语句对象cstmt。 1 cstmt.close(); 当游标作为存储过程的返回值时,如果使用JDBC调用该存储过程,返回的游标将不可用。 存储过程不能和普通SQL在同一条语句中执行。 存储过程中inout类型参数必须注册出参。 很多数据库类如Connection、Statement和ResultSet都有close()方法,在使用完对象后应把它们关闭。Connection对象的关闭将间接关闭所有与它关联的Statement对象,Statement对象的关闭将间接关闭ResultSet对象。 一些JDBC驱动程序提供命名参数的方法来设置参数。命名参数的方法允许根据名称而不是顺序来设置参数,若参数有默认值,则可以不用指定参数值就可以使用此参数的默认值。即使存储过程中参数的顺序发生了变更,也不必修改应用程序。目前 GaussDB数据库 的JDBC驱动程序不支持此方法。 GaussDB数据库不支持带有输出参数的函数,也不支持存储过程和函数参数默认值。 conn.prepareCall("{? = CALL TESTPROC(?,?,?)}"),执行存储过程绑定参数时,可以按照占位符的顺序绑定参数,注册第一个参数为出参。也可以按照存储过程中的参数顺序绑定参数,注册第四个参数为出参,上述用例为此场景,注册第四个参数为出参。
  • 执行普通SQL语句 应用程序通过执行SQL语句来操作数据库,支持对XML类型数据进行SELECT、UPDATE、INSERT、DELETE等操作。 前置条件是已经连接数据库,连接对象为conn。执行普通SQL语句,创建customer_t1表的命令如下: 调用Connection接口的createStatement方法创建语句对象stmt。 1 Statement stmt = conn.createStatement(); 调用Statement接口的executeUpdate方法执行SQL语句。 1 int rc = stmt.executeUpdate("CREATE TABLE customer_t1(c_customer_sk INTEGER, c_customer_name VARCHAR(32));"); 调用Statement接口的close方法关闭语句对象stmt。 1 stmt.close(); 数据库中收到的一次执行请求(不在事务块中),如果含有多条语句,将会被打包成一个事务,事务块中不支持vacuum操作。如果其中有一个语句失败,那么整个请求都将会被回滚。 使用Statement执行多语句时应以“;”作为各语句间的分隔符,存储过程、函数、匿名块不支持多语句执行。当preferQueryMode=simple,语句执行不进行解析逻辑,此场景下无法使用";"作为多语句间的分隔符。 “/”可用作创建单个存储过程、函数、匿名块、包体的结束符。当preferQueryMode=simple,语句执行不进行解析逻辑,此场景下无法使用"/"作为结束符。 由于JDBC会对PrepareStatement中的sql语句进行缓存,可能导致内存膨胀,如果JVM内存较小,建议调整preparedStatementCacheSizeMiB或者preparedStatementCacheQueries。
  • 以UDS方式连接 Unix domain socket用于同一主机上不同进程间的数据交换,通过添加junixsocket获取套接字工厂使用。 前置条件:引用junixsocket-core-XXX.jar、junixsocket-common-XXX.jar、junixsocket-native-common-XXX.jar,XXX为版本号,引用的这些jar包版本号需要一致。 使用NonValidatingFactory通道连接数据库的命令如下: 导入java.sql.Connection、java.sql.DriverManager、java.util.Properties。 此外,用户需要根据实际的应用场景,再导入其他的接口和类,具体请参见JDBC接口参考。 import java.sql.Connection; import java.sql.DriverManager; import java.util.Properties; 指定数据库的用户名和密码。 用户名和密码直接写到代码中有很大的安全风险,建议在环境变量中存放。并将用户名和密码设置为Properties对象的属性值。 String userName = System.getenv("EXAMPLE_USERNAME_ENV"); String password = System.getenv("EXAMPLE_PASSWORD_ENV"); Properties properties = new Properties(); properties.setProperty("user", userName); properties.setProperty("password", password); 加载驱动。 在代码运行工具(如IDE)中添加opengaussjdbc.jar包。 执行以下命令加载数据库驱动程序“com.huawei.opengauss.jdbc.Driver”。 String driver = "com.huawei.opengauss.jdbc.Driver"; Class.forName(driver); 指定数据库的$ip、$port、database、socketFactory和socketFactoryArg。 $ip和$port需要用户自行修改,连接主机名database必须设置为“localhost”,socketFactory设置为org.newsclub.net.unix.AFUNIXSocketFactory$FactoryArg,socketFactoryArg设置为[path-to-the-unix-socket],实现以UDS方式连接数据库。socketFactory和socketFactoryArg参数的具体说明,详见socketFactory和socketFactoryArg。 socketFactoryArg参数配置根据真实路径进行配置,与GUC参数unix_socket_directory的值保持一致。 Connection conn = DriverManager.getConnection("jdbc:opengauss://$ip:$port/database?socketFactory=org.newsclub.net.unix" + ".AFUNIXSocketFactory$FactoryArg&socketFactoryArg=[path-to-the-unix-socket]",properties); System.out.println("Connection Successful!"); 父主题: 连接数据库
  • 方式二:使用证书认证 前置条件:用户已经获取服务端所需要的证书和私钥文件,并完成服务端配置;同时已经获取客户端所需要的client.crt客户端证书、cacert.pem根证书、client.key.pk8客户端私钥文件,以下3介绍如何将证书和私钥文件配置在客户端。关于证书生成和获取、服务端配置的具体操作,请联系管理员或参见Openssl相关文档和命令。 使用客户端配置证书的方式连接数据库的命令如下: 导入java.sql.Connection、java.sql.DriverManager、java.util.Properties。 此外,用户需要根据实际的应用场景,再导入其他的接口和类,具体请参见JDBC接口参考。 import java.sql.Connection; import java.sql.DriverManager; import java.util.Properties; 指定数据库sourceURL($ip、$port、database需要用户自行修改)、用户名和密码。 用户名和密码直接写到代码中有很大的安全风险,建议在环境变量中存放。 String sourceURL = "jdbc:opengauss://$ip:$port/database"; Properties urlProps = new Properties(); urlProps.setProperty("user", System.getenv("EXAMPLE_USERNAME_ENV")); urlProps.setProperty("password", System.getenv("EXAMPLE_PASSWORD_ENV")); 设置SSL属性为true,在客户端配置client.crt客户端证书、cacert.pem根证书、client.key.pk8客户端私钥。 urlProps.setProperty("ssl", "true"); urlProps.setProperty("sslcert", "client.crt"); urlProps.setProperty("sslrootcert", "cacert.pem"); urlProps.setProperty("sslkey", "client.key.pk8"); 客户端私钥文件使用前,需要将client.key转化为client.key.pk8格式: /** * openssl pkcs8 -topk8 -outform DER -in client.key -out client.key.pk8 -nocrypt * openssl pkcs8 -topk8 -inform PEM -in client.key -outform DER -out client.key.der -v1 PBE-MD5-DES * openssl pkcs8 -topk8 -inform PEM -in client.key -outform DER -out client.key.der -v1 PBE-SHA1-3DES * 以上算法由于安全级别较低,不推荐使用。 * 如果客户需要采用更高级别的私钥加密算法,启用bouncycastle或者其他第三方私钥解密密码包后可以使用的私钥加密算法如下: * openssl pkcs8 -in client.key -topk8 -outform DER -out client.key.der -v2 AES128 * openssl pkcs8 -in client.key -topk8 -outform DER -out client.key.der -v2 aes-256-cbc -iter 1000000 * openssl pkcs8 -in client.key -topk8 -out client.key.der -outform Der -v2 aes-256-cbc -v2prf hmacWithSHA512 * 启用bouncycastle:使用jdbc的项目引入依赖:bcpkix-jdk15on.jar包,版本建议:1.65以上。 */ 配置sslmode。 sslmode设置值:require、verify-ca、verify-full,参数介绍详见sslmode。客户根据应用场景选择一种即可。 /* 设置sslmode为require */ urlProps.setProperty("sslmode", "require"); /* 设置sslmode为verify-ca */ urlProps.setProperty("sslmode", "verify-ca"); /* 设置sslmode为verify-full(Linux下验证) */ urlProps.setProperty("sslmode", "verify-full"); 加载驱动。 在代码运行工具(如IDE)中添加opengaussjdbc.jar包。 执行以下命令加载数据库驱动程序“com.huawei.opengauss.jdbc.Driver”。 Class.forName("com.huawei.opengauss.jdbc.Driver"); 创建数据库连接。 调用DriverManager.getConnection(String url, Properties info),进行数据库连接。 Connection conn = DriverManager.getConnection(sourceURL,urlProps);
  • 方式一:使用NonValidatingFactory通道 前置条件:用户已经获取服务端所需要的证书和私钥文件,并完成服务端配置。关于证书生成和获取、服务端配置的具体操作,请联系管理员或参见Openssl相关文档和命令。 使用NonValidatingFactory通道的方式连接数据库的命令如下: 导入java.sql.Connection、java.sql.DriverManager、java.util.Properties。 此外,用户需要根据实际的应用场景,再导入其他的接口和类,具体请参见JDBC接口参考。 import java.sql.Connection; import java.sql.DriverManager; import java.util.Properties; 指定数据库sourceURL($ip、$port、database需要用户自行修改)、用户名和密码。 用户名和密码直接写到代码中有很大的安全风险,建议在环境变量中存放。 String sourceURL = "jdbc:opengauss://$ip:$port/database"; Properties urlProps = new Properties(); urlProps.setProperty("user", System.getenv("EXAMPLE_USERNAME_ENV")); urlProps.setProperty("password", System.getenv("EXAMPLE_PASSWORD_ENV")); 设置SSL属性为true,使用NonValidatingFactory通道。 urlProps.setProperty("ssl", "true"); urlProps.setProperty("sslfactory","com.huawei.opengauss.jdbc.ssl.NonValidatingFactory"); 加载驱动。 在代码运行工具(如IDE)中添加opengaussjdbc.jar包。 执行以下命令加载数据库驱动程序“com.huawei.opengauss.jdbc.Driver”。 Class.forName("com.huawei.opengauss.jdbc.Driver"); 创建数据库连接。 调用DriverManager.getConnection(String url, Properties info),进行数据库连接。 Connection conn = DriverManager.getConnection(sourceURL,urlProps);
  • 创建数据库连接的接口介绍 JDBC提供了三种接口,用于创建数据库连接。url、info、user、password参数描述,请参见表1。 接口一:DriverManager.getConnection(String url)。该方式需要把数据库用户名、密码写在url中,有一定的安全风险,因此不推荐使用。 接口二:DriverManager.getConnection(String url, String user, String password)。具体请参见采用接口二连接数据库。 接口三:DriverManager.getConnection(String url, Properties info)。具体请参见采用接口三连接数据库。
  • 加载驱动方式介绍 加载驱动有两种方式: 在代码中创建连接之前任意位置隐含装载: Class.forName("com.huawei.opengauss.jdbc.Driver"); 在JVM启动时参数传递,jdbctest为测试用例程序的名称。 java -Djdbc.drivers=com.huawei.opengauss.jdbc.Driver jdbctest 由于GaussDB在JDBC的使用上与PG的使用方法保持兼容,所以同时在同一进程内使用两个JDBC驱动的时候,可能会类名冲突。 相比于PG驱动,GaussDB JDBC驱动主要做了以下特性的增强: 支持SHA256加密方式登录。 支持对接实现sf4j接口的第三方日志框架。 支持容灾切换。
  • 采用接口二连接数据库 使用DriverManager.getConnection(String url, String user, String password)接口创建数据库连接,命令如下: 导入java.sql.Connection和java.sql.DriverManager。 java.sql.Connection是数据库连接接口,通过java.sql.DriverManager的 getConnection() 方法让应用程序连接到数据库。此外,用户需要根据实际的应用场景,再导入其他的接口和类,具体请参见JDBC接口参考。 1 2 import java.sql.Connection; import java.sql.DriverManager; 指定数据库sourceURL($ip、$port、database需要用户自行修改)、用户名和密码。 用户名和密码直接写到代码中有很大的安全风险,建议在环境变量中存放。 String sourceURL = "jdbc:opengauss://$ip:$port/database"; String userName = System.getenv("EXAMPLE_USERNAME_ENV"); String password = System.getenv("EXAMPLE_PASSWORD_ENV"); 加载驱动。 在代码运行工具(如IDE)中添加opengaussjdbc.jar包。 执行以下命令加载数据库驱动程序“com.huawei.opengauss.jdbc.Driver”。 String driver = "com.huawei.opengauss.jdbc.Driver"; Class.forName(driver); 创建数据库连接。 调用DriverManager.getConnection(String url, String user, String password),进行数据库连接。 Connection conn = DriverManager.getConnection(sourceURL, userName, password);
  • 采用接口三连接数据库 使用DriverManager.getConnection(String url, Properties info)接口创建数据库连接,命令如下: 导入java.sql.Connection、java.sql.DriverManager、java.util.Properties。 java.util.Properties的setProperty() 方法,用于设置Properties 对象的属性值。此外,用户需要根据实际的应用场景,再导入其他的接口和类,具体请参见JDBC接口参考。 1 2 3 import java.sql.Connection; import java.sql.DriverManager; import java.util.Properties; 指定数据库sourceURL($ip、$port、database需要用户自行修改)、用户名和密码。 用户名和密码直接写到代码中有很大的安全风险,建议在环境变量中存放。 String sourceURL = "jdbc:opengauss://$ip:$port/database"; String userName = System.getenv("EXAMPLE_USERNAME_ENV"); String password = System.getenv("EXAMPLE_PASSWORD_ENV"); 创建Properties 对象,并将userName和password设置为该对象的属性值。 Properties info = new Properties(); info.setProperty("user", userName); info.setProperty("password", password); 加载驱动。 在代码运行工具(如IDE)中添加opengaussjdbc.jar包。 执行以下命令加载数据库驱动程序“com.huawei.opengauss.jdbc.Driver”。 String driver = "com.huawei.opengauss.jdbc.Driver"; Class.forName(driver); 创建数据库连接。 调用DriverManager.getConnection(String url, Properties info),进行数据库连接。 1 Connection conn = DriverManager.getConnection(sourceURL, info);
  • 连接方式介绍 连接数据库的方式通常是根据安全性、性能、可扩展性和实现复杂度等因素进行选择的。下面是3种方式连接数据库的优缺点以及选择原则: 表1 不同方式的优缺点以及选择原则 连接方式 优点 缺点 选择原则 非加密方式 简单易实现,无需额外的加密和解密操作。 性能较高,因为不需要进行加密/解密操作,减少了数据传输的开销。 安全性较低,数据在传输过程中容易被窃听或篡改。 不适合传输敏感信息,可能违反隐私保护法规。 只适用于内部网络或对安全性要求不高的环境。 SSL方式 提供了加密传输,数据在传输过程中得到保护,安全性较高。 支持客户端/服务器身份验证,增强了安全性。 配置和管理相对复杂,需要证书的颁发和更新。 可能会增加一些性能开销,特别是在加密和解密大量数据时。 适用于对数据传输安全性要求较高的环境,如金融、医疗等行业。 UDS方式 适用于本地通信,不经过网络,传输速度快。 不需要额外的网络开销,不容易受到网络攻击。 仅限于在同一台主机上的进程间通信,无法用于远程连接。 适用于本地通信的场景,如本地服务和应用之间的数据交换。 父主题: 连接数据库
  • 获取驱动jar包 从发布包中获取驱动jar包,包名为GaussDB-Kernel-数据库版本号-操作系统-64bit-Jdbc.tar.gz。解压后JDBC的驱动jar包: gsjdbc4.jar:主类名为“org.postgresql.Driver”,数据库连接的url前缀为“jdbc:postgresql”。该驱动包适用于从PostgreSQL迁移业务的场景,驱动类和加载路径与迁移前保持一致,但接口支持情况不完全一致,未支持的接口需要业务侧进行调整。 opengaussjdbc.jar:主类名为“com.huawei.opengauss.jdbc.Driver”,数据库连接的url前缀为“jdbc:opengauss”,推荐使用此驱动包。如果遇到同一JVM进程内需要同时访问PostgreSQL及GaussDB的场景,请使用此驱动包。 各驱动包只是驱动类加载路径和url前缀不同,接口功能上相同。 gsjdbc200.jar:该驱动包适用于从Gauss200迁移业务的场景,驱动类和加载路径与迁移前保持一致,但接口支持情况不完全一致,未支持的接口需要业务侧进行调整。 不能使用gsjdbc4.jar驱动包操作PostgreSQL数据库,虽然部分版本能够建连成功,但部分接口行为与PostgreSQL JDBC不同,可能导致未知错误。 不能使用PostgreSQL的驱动包操作GaussDB数据库,虽然部分版本能够建连成功,但部分接口行为与GaussDB JDBC不同,可能导致未知错误。
  • 配置JDK1.8 客户端需配置JDK1.8。JDK支持Windows、Linux等多种平台。下面以Windows为例,配置方法如下: DOS窗口(windows下的命令提示符)输入以下命令查看JDK版本。 java -version 确认为JDK1.8版本。如果未安装JDK,请从官方网站下载安装包并安装。 根据如下步骤配置系统环境变量。 右键单击“我的电脑”,选择“属性”。 在“系统”页面左侧导航栏单击“高级系统设置”。 在“系统属性”页面,“高级”页签上单击“环境变量”。 在“环境变量”页面上,“系统变量”区域单击“新建”或“编辑”配置系统变量。变量说明请参见表1。 表1 变量说明 变量名 操作 变量值 JAVA_HOME 若存在,则单击“编辑”。 若不存在,则单击“新建”。 JAVA的安装目录。 例如:C:\Program Files\Java\jdk1.8.0_131 Path 单击“编辑”。 若配置了JAVA_HOME,则在变量值的最前面加上: %JAVA_HOME%\bin 若未配置JAVA_HOME,则在变量值的最前面加上 JAVA安装的全路径: C:\Program Files\Java\jdk1.8.0_131\bin CLASSPATH 单击“新建”。 .;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar
  • 开发规范 如果用户在APP的开发中,使用了连接池机制,那么需要遵循如下规范: 如果在连接中设置了GUC参数,那么在将连接归还连接池之前,必须使用“SET SESSION AUTHORIZATION DEFAULT;RESET ALL;”将连接的状态清空。 如果使用了临时表,那么在将连接归还连接池之前,必须将临时表删除。 否则,连接池里面的连接就是有状态的,会对用户后续使用连接池进行操作的正确性带来影响。 应用程序开发驱动兼容性说明如表1所示: 表1 兼容性说明 驱动 兼容性说明 JDBC、Go、ODBC、libpq、Psycopg、ecpg 驱动前向兼容数据库,若需使用驱动与数据库同步增加的新特性,须升级数据库。 behavior_compat_options='proc_outparam_override' 重载参数仅在A兼容模式可用。 在多线程环境下使用驱动: JDBC驱动程序不是线程安全的,不保证连接上的方法是同步的。由调用者来同步对驱动程序的调用。 父主题: 应用程序开发教程
  • JDBC JDBC(Java Database Connectivity,Java数据库连接)是用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问接口。它允许Java应用程序通过SQL语句来执行数据库操作,包括查询、插入、更新和删除数据等。 以下是JDBC的一些关键特点和用法: 数据库连接管理:JDBC允许应用程序建立与数据库的连接,并管理这些连接的生命周期。 SQL执行: 使用JDBC,可以执行SQL查询、更新、删除等操作。这通过在Java代码中构建SQL语句并将其发送到数据库来实现。 事务管理:JDBC支持事务管理,可以通过JDBC API来启动、提交或回滚事务,确保数据库操作的一致性和完整性。 异常处理: JDBC定义了一组异常类来处理数据库操作期间可能发生的各种异常情况,开发人员可以使用try-catch块来捕获和处理这些异常。 批处理操作:JDBC提供了批处理功能,允许一次性执行多个SQL语句,从而提高数据库操作的效率。 元数据访问: 通过JDBC,可以获取数据库的元数据信息,如表结构、列名、数据类型等,从而动态地构建SQL查询或根据数据库结构进行操作。 总的来说,JDBC提供了一个灵活且强大的桥梁,使Java应用程序能够与各种不同的数据库进行交互,从而实现数据的持久化和管理。GaussDB库提供了对JDBC 4.0特性的支持,需要使用JDK1.8版本编译程序代码,不支持JDBC桥接ODBC方式。 基于JDBC开发详细教程请参见基于JDBC开发。
  • DDL 【建议】在GaussDB中,建议DDL(建表、COMMENT等)操作统一执行。在批处理作业中尽量避免DDL操作。避免大量并发事务对性能的影响。 【建议】在非日志表(unlogged table)使用完后,立即执行数据清理(TRUNCATE)操作。因为在异常场景下,GaussDB不保证非日志表(unlogged table)数据的安全性。 【建议】临时表和非日志表的存储方式建议和基表相同。当基表为行存表时,临时表和非日志表也推荐创建为行存表。 【建议】索引字段的总长度不超过50字节。否则,索引大小会膨胀比较严重,带来较大的存储开销,同时索引性能也会下降。 【建议】不要使用DROP…CASCADE方式删除对象,除非已经明确对象间的依赖关系,以免误删。
  • 数据加载和卸载 【建议】在INSERT语句中显式给出插入的字段列表。例如: 1 INSERT INTO task(name,id,comment) VALUES ('task1','100','第100个任务'); 【建议】在批量数据入库之后,或者数据增量达到一定阈值后,建议对表进行ANALYZE操作,防止统计信息不准确而导致的执行计划劣化。 【建议】如果要清理表中的所有数据,建议使用TRUNCATE TABLE方式,不要使用DELETE TABLE方式。DELETE TABLE方式删除性能差,且不会释放那些已经删除了的数据占用的磁盘空间。
  • 释放连接 【建议】推荐使用连接池限制应用程序的连接数。每执行一条SQL就连接一次数据库,是一种不好的SQL编写习惯。 【建议】在应用程序完成作业任务之后,应当及时断开和GaussDB的连接,释放资源。建议在任务中设置session超时时间参数。 【建议】使用JDBC连接池,在将连接释放给连接池前,需要执行以下操作,重置会话环境。否则,可能会因为历史会话信息导致的对象冲突。 如果在连接中设置了GUC参数,那么在将连接归还连接池之前,必须使用“SET SESSION AUTHORIZATION DEFAULT;RESET ALL;”将连接的状态清空。 如果使用了临时表,那么在将连接归还连接池之前,必须将临时表删除。
  • 连接参数 【关注】第三方工具通过JDBC连接GaussDB时,JDBC向GaussDB发起连接请求,会默认添加以下配置参数,详见JDBC代码ConnectionFactoryImpl类的实现。 params = { { "user", user }, { "database", database }, { "client_encoding", "UTF8" }, { "DateStyle", "ISO" }, { "extra_float_digits", "3" }, { "TimeZone", createPostgresTimeZone() }, }; 这些参数可能会导致JDBC客户端的行为与gsql客户端的行为不一致,例如,Date数据显示方式、浮点数精度表示、timezone显示。 如果实际期望和这些配置不符,建议在java连接设置代码中显式设定这些参数。 【建议】通过JDBC连接数据库时,会设置extra_float_digits=3,gsql中设置为extra_float_digits=0,可能会使同一条数据在JDBC显示和gsql显示的精度不同。 【建议】对于精度敏感的场景,建议使用numeric类型。 【建议】通过JDBC连接数据库时,应该保证下面三个时区设置一致: JDBC客户端所在主机的时区。 GaussDB数据库实例所在主机的时区。 GaussDB数据库实例配置过程中时区。 时区设置相关的操作,请联系管理员。
共100000条