使用流式读功能
流式读功能:读取数据时,服务端一次获取全部数据,发送到客户端socket缓冲区中,缓冲区占满则暂停,有空余则继续向缓冲区中发送数据,同时JVM逐行从缓冲区中读取数据。
优势是处理结果快,不会造成JVM内存溢出。劣势是只能向后遍历,数据处理完毕之前或者statement关闭之前,当前连接不能执行其他操作。
代码运行的前提条件:根据实际情况添加gaussdbjdbc.jar包(例如用户使用IDE执行代码,则需要在本地IDE添加gaussdbjdbc.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 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
// 认证用的用户名和密码直接写到代码中有很大的安全风险,建议在配置文件或者环境变量中存放(密码应密文存放,使用时解密),确保安全。 // 本示例以用户名和密码保存在环境变量中为例,运行本示例前请先在本地环境中设置环境变量(环境变量名称请根据自身情况进行设置)EXAMPLE_USERNAME_ENV和EXAMPLE_PASSWORD_ENV。 // $ip、$port、database需要用户自行修改。 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.huawei.gaussdb.jdbc.Driver"; String sourceURL = "jdbc:gaussdb://$ip:$port/database?enableStreamingQuery=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
使用流式读功能时,结果集使用完之后,需要执行resultSet.close()或者statement.close()操作,否则当前连接将不可用。