使用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;

9. try
10. {
11. //加载驱动。
12. Class.forName(driver);
13. }
14. catch( Exception e )
15. {
16. e.printStackTrace();
17. return null;
18. }

20. try
21. {
22. //创建连接。
23. conn = DriverManager.getConnection(sourceURL, username, passwd);
24. System.out.println("Connection succeed!");
25. }
26. catch(Exception e)
27. {
28. e.printStackTrace();
29. return null;
30. }

32. return conn;
33. };

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

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

调用isValid方法刷新缓存示例

1. // 创建客户端主密钥
2. Connection conn1 = DriverManager.getConnection("url","user","password");

4. // conn1通过调用isValid刷新缓存
5. try {
6. if (!conn1.getConnection().isValid(60)) {
7. conn1.getFileWriter().writeLine("isValid Failed for connection 1");
8. }
9. } catch (SQLException e) {
10. conn1.getFileWriter().writeLine("isValid Failed with error");
11. e.printStackTrace();
12. }

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

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();