使用JDBC操作密态数据库

连接密态数据库

连接密态数据库需要使用驱动包gsjdbc4.jar,具体JDBC连接参数参考基于JDBC开发章节介绍。JDBC支持密态数据库相关操作,需要设置enable_ce=1,示例如下。

  1. public static Connection getConnect(String username, String passwd)
  2. {
  3. //驱动类。
  4. String driver = "org.opengauss.Driver";
  5. //数据库连接描述符。
  6. String sourceURL = "jdbc:opengauss://10.10.0.13:8000/postgres?enable_ce=1";
  7. Connection conn = null;
  8. try
  9. {
  10. //加载驱动。
  11. Class.forName(driver);
  12. }
  13. catch( Exception e )
  14. {
  15. e.printStackTrace();
  16. return null;
  17. }
  18. try
  19. {
  20. //创建连接。
  21. conn = DriverManager.getConnection(sourceURL, username, passwd);
  22. System.out.println("Connection succeed!");
  23. }
  24. catch(Exception e)
  25. {
  26. e.printStackTrace();
  27. return null;
  28. }
  29. return conn;
  30. };

使用JDBC操作密态数据库 - 图1 说明:

  • 【建议】使用JDBC操作密态数据库时,一个数据库连接对象对应一个线程,否则,不同线程变更可能导致冲突。

  • 【建议】使用JDBC操作密态数据库时,不同connection对密态配置数据有变更,由客户端调用isvalid方法保证connection能够持有变更后的密态配置数据,此时需要保证参数refreshClientEncryption为1(默认值为1),在单客户端操作密态数据场景下,refreshClientEncryption参数可以设置为0。

调用isValid方法刷新缓存示例

  1. // 创建客户端主密钥
  2. Connection conn1 = DriverManager.getConnection("url","user","password");
  3. // conn1通过调用isValid刷新缓存
  4. try {
  5. if (!conn1.getConnection().isValid(60)) {
  6. conn1.getFileWriter().writeLine("isValid Failed for connection 1");
  7. }
  8. } catch (SQLException e) {
  9. conn1.getFileWriter().writeLine("isValid Failed with error");
  10. e.printStackTrace();
  11. }

执行密态等值查询相关的创建密钥语句

  1. // 创建客户端主密钥
  2. Connection conn = DriverManager.getConnection("url","user","password");
  3. Statement stmt = conn.createStatement();
  4. int rc = stmt.executeUpdate("CREATE CLIENT MASTER KEY ImgCMK1 WITH ( KEY_STORE = localkms, KEY_PATH = \"key_path_value\" , ALGORITHM = RSA_2048));

使用JDBC操作密态数据库 - 图2 说明: 创建密钥之前需要使用gs_ktool工具提前生成密钥,才能创建CMK成功。

  1. // 创建列加密密钥
  2. int rc2 = stmt.executeUpdate("CREATE COLUMN ENCRYPTION KEY ImgCEK1 WITH VALUES (CLIENT_MASTER_KEY = ImgCMK1, ALGORITHM = AEAD_AES_256_CBC_HMAC_SHA256);");

执行密态等值查询相关的创建加密表的语句

  1. int rc3 = stmt.executeUpdate("CREATE TABLE creditcard_info (id_number int, name varchar(50) encrypted with (column_encryption_key = ImgCEK1, encryption_type = DETERMINISTIC),credit_card varchar(19) encrypted with (column_encryption_key = ImgCEK1, encryption_type = DETERMINISTIC));");
  2. // 插入数据
  3. int rc4 = stmt.executeUpdate("INSERT INTO creditcard_info VALUES (1,'joe','6217986500001288393');");
  4. // 查询加密表
  5. ResultSet rs = null;
  6. rs = stmt.executeQuery("select * from creditcard_info where name = 'joe';");
  7. // 关闭语句对象
  8. stmt.close();

执行加密表的预编译SQL语句

  1. // 调用Connection的prepareStatement方法创建预编译语句对象。
  2. PreparedStatement pstmt = con.prepareStatement("INSERT INTO creditcard_info VALUES (?, ?, ?);");
  3. // 调用PreparedStatement的setShort设置参数。
  4. pstmt.setInt(1, 2);
  5. pstmt.setString(2, "joy");
  6. pstmt.setString(3, "6219985678349800033");
  7. // 调用PreparedStatement的executeUpdate方法执行预编译SQL语句。
  8. int rowcount = pstmt.executeUpdate();
  9. // 调用PreparedStatement的close方法关闭预编译语句对象。
  10. pstmt.close();

执行加密表的批处理操作

  1. // 调用Connection的prepareStatement方法创建预编译语句对象。
  2. Connection conn = DriverManager.getConnection("url","user","password");
  3. PreparedStatement pstmt = conn.prepareStatement("INSERT INTO batch_table (id, name, address) VALUES (?,?,?)");
  4. // 针对每条数据都要调用setShort设置参数,以及调用addBatch确认该条设置完毕。
  5. int loopCount = 20;
  6. for (int i = 1; i < loopCount + 1; ++i) {
  7. pstmt.setInt(1, i);
  8. pstmt.setString(2, "Name " + i);
  9. pstmt.setString(3, "Address " + i);
  10. // Add row to the batch.
  11. pstmt.addBatch();
  12. }
  13. // 调用PreparedStatement的executeBatch方法执行批处理。
  14. int[] rowcount = pstmt.executeBatch();
  15. // 调用PreparedStatement的close方法关闭预编译语句对象。
  16. pstmt.close();