From 2df0eb320be16b318acd207a6391b9f57dd58df6 Mon Sep 17 00:00:00 2001 From: liuyuanli Date: Tue, 15 Mar 2022 17:31:15 +0800 Subject: [PATCH 1/2] add English version of Java SDK quickstart documentation --- docs/en/java_sdk.md | 530 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 530 insertions(+) create mode 100644 docs/en/java_sdk.md diff --git a/docs/en/java_sdk.md b/docs/en/java_sdk.md new file mode 100644 index 00000000000..3e5340f81f7 --- /dev/null +++ b/docs/en/java_sdk.md @@ -0,0 +1,530 @@ +# Java SDK Quick Start + +Notice: The Java SDK currently only supports the cluster version, and the standalone version is planned to be supported in the next version v0.5.0. + +## 1. Java SDK package installation + +### Java SDK package installation on Linux +configure maven pom + +```xml + + com.4paradigm.openmldb + openmldb-jdbc + 0.4.3 + + + com.4paradigm.openmldb + openmldb-native + 0.4.3 + +``` +### Java SDK package installation on Mac +configure maven pom + +```xml + + com.4paradigm.openmldb + openmldb-jdbc + 0.4.3 + + + com.4paradigm.openmldb + openmldb-native + 0.4.3-macos + +``` +Notice: Since openmldb-native contains the C++ static library compiled by OpenMLDB, the default is the linux static library. On macOS, the version of the above openmldb-native needs to be changed to `0.4.3-macos`, and the version of openmldb-jdbc remains unchanged . + +## 2. Java SDK Quick Start + +### 2.1 Create SqlClusterExecutor + +First, configure the OpenMLDB connection parameters + +```java +SdkOption option = new SdkOption(); +option.setZkCluster("127.0.0.1:2181"); +option.setZkPath("/openmldb"); +option.setSessionTimeout(10000); +option.setRequestTimeout(60000); + +``` + +Next, create an Executor using SdkOption. SqlClusterExecutor is multi-threaded safe to execute SQL operations. In the actual environment, just create one `SqlClusterExecutor`: + +```java +sqlExecutor = new SqlClusterExecutor(option); +``` + +### 2.2 Create database + +Create a database using the `SqlClusterExecutor::createDB()` interface: + +```java +sqlExecutor.createDB("db_test"); +``` + +### 2.3 Create table + +Create a table using the `SqlClusterExecutor::executeDDL(db, createTableSql)` interface: + +```java +String createTableSql = "create table trans(c1 string,\n" + + " c3 int,\n" + + " c4 bigint,\n" + + " c5 float,\n" + + " c6 double,\n" + + "c7 timestamp,\n" + + " c8 date,\n" + + "index(key=c1, ts=c7));"; +sqlExecutor.executeDDL("", createTableSql); +``` + +### 2.4 Insert data into the table + +#### 2.4.1 Insert data directly + +The first step, use the `SqlClusterExecutor::getInsertPreparedStmt(db, insertSql)` interface to get the InsertPrepareStatement. + +The second step, use the `Statement::execute()` interface to execute the insert statement. + +```java +String insertSql = "insert into trans values(\"aa\",23,33,1.4,2.4,1590738993000,\"2020-05-04\");"; +PreparedStatement pstmt = null; +try { + pstmt = sqlExecutor.getInsertPreparedStmt(db, insertSql); + Assert.assertTrue(pstmt.execute()); +} catch (SQLException e) { + e.printStackTrace(); + Assert.fail(); +} finally { + if (pstmt != null) { + try { + // PrepareStatement must be closed after it is used up + pstmt.close(); + } catch (SQLException throwables) { + throwables.printStackTrace(); + } + } +} +``` + +#### 2.4.2 Use placeholder to execute insert statement + +The first step, use the `SqlClusterExecutor::getInsertPreparedStmt(db, insertSqlWithPlaceHolder)` interface to get the InsertPrepareStatement. + +The second step, call the `PreparedStatement::setType(index, value)` interface to fill data into InsertPrepareStatement. + +The third step, use the `Statement::execute()` interface to execute the insert statement. + +```java +String insertSqlWithPlaceHolder = "insert into trans values(\"aa\", ?, 33, ?, 2.4, 1590738993000, \"2020-05-04\");"; +PreparedStatement pstmt = null; +try { + pstmt = sqlExecutor.getInsertPreparedStmt(db, insertSqlWithPlaceHolder); + pstmt.setInt(1, 24); + pstmt.setInt(2, 1.5f); + pstmt.execute(); +} catch (SQLException e) { + e.printStackTrace(); + Assert.fail(); +} finally { + if (pstmt != null) { + try { + // PrepareStatement must be closed after it is used up + pstmt.close(); + } catch (SQLException throwables) { + throwables.printStackTrace(); + } + } +} +``` + +### 2.5 Execute SQL batch query + +Use the `SqlClusterExecutor::executeSQL(selectSql)` interface to execute SQL batch query statements: + +```java +String selectSql = "select * from trans;"; +java.sql.ResultSet result = sqlExecutor.executeSQL(db, selectSql); +``` + +Access query results: + +```java +// Access the result set ResultSet, and output the first three columns of data +try { + while (result.next()) { + System.out.println(resultSet.getString(1) + "," + resultSet.getInt(2) "," + resultSet.getLong(3)); + } +} catch (SQLException e) { + e.printStackTrace(); +} finally { + try { + if (result != null) { + result.close(); + } + } catch (SQLException throwables) { + throwables.printStackTrace(); + } + +} +``` + +### 2.6 Execute SQL on-demand queries + +The first step, use the `SqlClusterExecutor::getRequestPreparedStmt(db, selectSql)` interface to get the RequestPrepareStatement. + +The second step, call the `PreparedStatement::setType(index, value)` interface to set the request data. Please call the setType interface and configure a legal value according to the data type corresponding to each column in the data table. + +The third step, call the `Statement::executeQuery()` interface to execute the request query statement. + +```java +String selectSql = "SELECT c1, c3, sum(c4) OVER w1 as w1_c4_sum FROM trans WINDOW w1 AS " + + "(PARTITION BY trans.c1 ORDER BY trans.c7 ROWS BETWEEN 2 PRECEDING AND CURRENT ROW);"; +PreparedStatement pstmt = null; +ResultSet resultSet = null; +/* +c1 string,\n" + + " c3 int,\n" + + " c4 bigint,\n" + + " c5 float,\n" + + " c6 double,\n" + + "c7 timestamp,\n" + + " c8 date,\n" + +*/ +try { + // The first step, get RequestPrepareStatement + pstmt= sqlExecutor.getRequestPreparedStmt(db, selectSql); + + // The second step, execute the request mode, you need to set a line of request data in RequestPreparedStatement + pstmt.setString(1, "bb"); + pstmt.setInt(2, 24); + pstmt.setLong(3, 34l); + pstmt.setFloat(4, 1.5f); + pstmt.setDouble(5, 2.5); + pstmt.setTimestamp(6, new Timestamp(1590738994000l)); + pstmt.setDate(7, Date.valueOf("2020-05-05")); + + // Calling executeQuery will execute the select sql, the result in resultSet + resultSet = pstmt.executeQuery(); + + // access resultSet + Assert.assertEquals(resultSet.getMetaData().getColumnCount(), 3); + Assert.assertTrue(resultSet.next()); + Assert.assertEquals(resultSet.getString(1), "bb"); + Assert.assertEquals(resultSet.getInt(2), 24); + Assert.assertEquals(resultSet.getLong(3), 34); + + // The returned result set of a normal request query contains only one row of results, so the result of the second call to resultSet.next() is false + Assert.assertFalse(resultSet.next()); + +} catch (SQLException e) { + e.printStackTrace(); + Assert.fail(); +} finally { + try { + if (resultSet != null) { + // need to close after result is used up + resultSet.close(); + } + if (pstmt != null) { + pstmt.close(); + } + } catch (SQLException throwables) { + throwables.printStackTrace(); + } +} +``` + +### 2.7 Delete table + +Use the `SqlClusterExecutor::executeDDL(db, dropTableSql)` interface to delete a table: + +```java +String dropTableSql = "drop table trans;"; +sqlExecutor.executeDDL(db, dropTableSql); +``` + +### 2.8 Delete database + +Use the `SqlClusterExecutor::dropDB(db)` interface to drop the specified database: + +```java +sqlExecutor.dropDB(db); +``` + +## 3. Complete Java SDK usage example + +```java +import com._4paradigm.openmldb.jdbc.CallablePreparedStatement; +import com._4paradigm.openmldb.sdk.*; +import com._4paradigm.openmldb.sdk.impl.SqlClusterExecutor; +import org.testng.Assert; + +import java.sql.*; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +public class Demo { + + private SqlExecutor sqlExecutor = null; + private String db = "mydb16"; + private String table = "trans"; + private String sp = "sp"; + + public static void main(String[] args) { + Demo demo = new Demo(); + try { + // Initialize the construction of SqlExecutor + demo.init(); + demo.createDataBase(); + demo.createTable(); + // Insert by insert statement + demo.insertWithoutPlaceholder(); + // Insert by way of placeholder. The placeholder method will not compile sql repeatedly, and its performance will be much better than direct insert + demo.insertWithPlaceholder(); + // Execute the select statement + demo.select(); + // Execute sql in request mode + demo.requestSelect(); + // Delete table + demo.dropTable(); + // Delete the database + demo.dropDataBase(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void init() throws SqlException { + SdkOption option = new SdkOption(); + option.setZkCluster("172.27.128.37:7181"); + option.setZkPath("/rtidb_wb"); + option.setSessionTimeout(10000); + option.setRequestTimeout(60000); + // sqlExecutor is multi-threaded safe to execute sql operations, and only one can be created in the actual environment + sqlExecutor = new SqlClusterExecutor(option); + } + + private void createDataBase() { + Assert.assertTrue(sqlExecutor.createDB(db)); + } + + private void dropDataBase() { + Assert.assertTrue(sqlExecutor.dropDB(db)); + } + + private void createTable() { + String createTableSql = "create table trans(c1 string,\n" + + " c3 int,\n" + + " c4 bigint,\n" + + " c5 float,\n" + + " c6 double,\n" + + "c7 timestamp,\n" + + " c8 date,\n" + + "index(key=c1, ts=c7));"; + Assert.assertTrue(sqlExecutor.executeDDL(db, createTableSql)); + } + + private void dropTable() { + String dropTableSql = "drop table trans;"; + Assert.assertTrue(sqlExecutor.executeDDL(db, dropTableSql)); + } + + private void getInputSchema(String selectSql) { + try { + Schema inputSchema = sqlExecutor.getInputSchema(db, selectSql); + Assert.assertEquals(inputSchema.getColumnList().size(), 7); + Column column = inputSchema.getColumnList().get(0); + Assert.assertEquals(column.getColumnName(), "c1"); + Assert.assertEquals(column.getSqlType(), Types.VARCHAR); + Assert.assertEquals(column.isConstant(), false); + Assert.assertEquals(column.isNotNull(), false); + } catch (SQLException throwables) { + throwables.printStackTrace(); + } + } + + private void insertWithoutPlaceholder() { + String insertSql = "insert into trans values(\"aa\",23,33,1.4,2.4,1590738993000,\"2020-05-04\");"; + PreparedStatement pstmt = null; + try { + pstmt = sqlExecutor.getInsertPreparedStmt(db, insertSql); + Assert.assertTrue(pstmt.execute()); + } catch (SQLException e) { + e.printStackTrace(); + Assert.fail(); + } finally { + if (pstmt != null) {try { + // PrepareStatement must be closed after it is used up + pstmt.close(); + } catch (SQLException throwables) { + throwables.printStackTrace(); + } + } + } + } + + private void insertWithPlaceholder() { + String insertSql = "insert into trans values(\"aa\", ?, 33, ?, 2.4, 1590738993000, \"2020-05-04\");"; + PreparedStatement pstmt = null; + try { + pstmt = sqlExecutor.getInsertPreparedStmt(db, insertSql); + ResultSetMetaData metaData = pstmt.getMetaData(); + setData(pstmt, metaData); + Assert.assertTrue(pstmt.execute()); + } catch (SQLException e) { + e.printStackTrace(); + Assert.fail(); + } finally { + if (pstmt != null) { + try { + pstmt.close(); + } catch (SQLException throwables) { + throwables.printStackTrace(); + } + } + } + } + + private void select() { + String selectSql = "select * from trans;"; + java.sql.ResultSet result = sqlExecutor.executeSQL(db,selectSql); + int num = 0; + try { + while (result.next()) { + num++; + } + } catch (SQLException e) { + e.printStackTrace(); + } finally { + try { + if (result != null) { + result.close(); + } + } catch (SQLException throwables) { + throwables.printStackTrace(); + } + + } + // result data analysis refer to the requestSelect method below + Assert.assertEquals(num, 2); + } + + private void requestSelect() { + String selectSql = "SELECT c1, c3, sum(c4) OVER w1 as w1_c4_sum FROM trans WINDOW w1 AS " + + "(PARTITION BY trans.c1 ORDER BY trans.c7 ROWS BETWEEN 2 PRECEDING AND CURRENT ROW);"; + PreparedStatement pstmt = null; + ResultSet resultSet = null; + try { + pstmt = sqlExecutor.getRequestPreparedStmt(db, selectSql); + // If you are executing deployment, you can get preparedstatement by name + //pstmt = sqlExecutor.getCallablePreparedStmt(db, deploymentName); + ResultSetMetaData metaData = pstmt.getMetaData(); + // To execute the request mode, you need to set a line of request data in RequestPreparedStatement + setData(pstmt, metaData); + // Calling executeQuery will execute the select sql, and then put the result in resultSet + resultSet = pstmt.executeQuery(); + + Assert.assertTrue(resultSet.next()); + Assert.assertEquals(resultSet.getMetaData().getColumnCount(), 3); + Assert.assertEquals(resultSet.getString(1), "bb"); + Assert.assertEquals(resultSet.getInt(2), 24); + Assert.assertEquals(resultSet.getLong(3), 34); + Assert.assertFalse(resultSet.next()); + } catch (SQLException e) { + e.printStackTrace(); + Assert.fail(); + } finally { + try { + if (resultSet != null) { + // need to close after result is used up + resultSet.close(); + } + if (pstmt != null) { + pstmt.close(); + } + } catch (SQLException throwables) { + throwables.printStackTrace(); + } + } + } + + private void batchRequestSelect() { + String selectSql = "SELECT c1, c3, sum(c4) OVER w1 as w1_c4_sum FROM trans WINDOW w1 AS " + + "(PARTITION BY trans.c1 ORDER BY trans.c7 ROWS BETWEEN 2 PRECEDING AND CURRENT ROW);"; + PreparedStatement pstmt = null; + ResultSet resultSet = null; + try { + List list = new ArrayList(); + pstmt = sqlExecutor.getBatchRequestPreparedStmt(db, selectSql, list); + // If you are executing deployment, you can get preparedstatement by name + // pstmt = sqlExecutor.getCallablePreparedStmtBatch(db, deploymentName); + ResultSetMetaData metaData = pstmt.getMetaData(); + // To execute request mode, you need to set PreparedStatement to request data + // Set how many pieces of data to send in a batch + int batchSize = 5; + for (int idx = 0; idx < batchSize; idx++) { + setData(pstmt, metaData); + // After each row of data is set, addBatch needs to be called once + pstmt.addBatch(); + } + // Calling executeQuery will execute the select sql, and then put the result in resultSet + resultSet = pstmt.executeQuery(); + // Take out the feature results corresponding to each data in turn + while (resultSet.next()) { + Assert.assertEquals(resultSet.getMetaData().getColumnCount(), 3); + Assert.assertEquals(resultSet.getString(1), "bb"); + Assert.assertEquals(resultSet.getInt(2), 24); + Assert.assertEquals(resultSet.getLong(3), 34); + } + } catch (SQLException e) { + e.printStackTrace(); + Assert.fail(); + } finally { + try { + if (resultSet != null) { + //result need to close after use + resultSet.close(); + } + if (pstmt != null) { + pstmt.close(); + } + } catch (SQLException throwables) { + throwables.printStackTrace(); + } + } + } + + + private void setData(PreparedStatement pstmt, ResultSetMetaData metaData) throws SQLException { + for (int i = 0; i < metaData.getColumnCount(); i++) { + int columnType = metaData.getColumnType(i + 1); + if (columnType == Types.BOOLEAN) { + pstmt.setBoolean(i + 1, true); + } else if (columnType == Types.SMALLINT) { + pstmt.setShort(i + 1, (short) 22); + } else if (columnType == Types.INTEGER) { + pstmt.setInt(i + 1, 24); + } else if (columnType == Types. BIGINT) { + pstmt.setLong(i + 1, 34l); + } else if (columnType == Types.FLOAT) { + pstmt.setFloat(i + 1, 1.5f); + } else if (columnType == Types.DOUBLE) { + pstmt.setDouble(i + 1, 2.5); + } else if (columnType == Types.TIMESTAMP) { + pstmt.setTimestamp(i + 1, new Timestamp(1590738994000l)); + } else if (columnType == Types.DATE) { + pstmt.setDate(i + 1, Date.valueOf("2020-05-05")); + } else if (columnType == Types.VARCHAR) { + pstmt.setString(i + 1, "bb"); + } else { + throw new SQLException("set data failed"); + } + } + } +} +``` From b8c2d2c9cee5eb0f6637b781e55157f1bf8bd08a Mon Sep 17 00:00:00 2001 From: liuyuanli Date: Fri, 18 Mar 2022 09:53:19 +0800 Subject: [PATCH 2/2] Fixed and optimized some descriptions --- docs/en/java_sdk.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/en/java_sdk.md b/docs/en/java_sdk.md index 3e5340f81f7..38ae915dd37 100644 --- a/docs/en/java_sdk.md +++ b/docs/en/java_sdk.md @@ -51,7 +51,7 @@ option.setRequestTimeout(60000); ``` -Next, create an Executor using SdkOption. SqlClusterExecutor is multi-threaded safe to execute SQL operations. In the actual environment, just create one `SqlClusterExecutor`: +Next, create an Executor using SdkOption. SqlClusterExecutor is thread-safe to execute SQL operations. In the actual environment, just create one `SqlClusterExecutor`: ```java sqlExecutor = new SqlClusterExecutor(option); @@ -172,7 +172,7 @@ try { } ``` -### 2.6 Execute SQL on-demand queries +### 2.6 SQL Queries in the request mode The first step, use the `SqlClusterExecutor::getRequestPreparedStmt(db, selectSql)` interface to get the RequestPrepareStatement. @@ -255,7 +255,7 @@ Use the `SqlClusterExecutor::dropDB(db)` interface to drop the specified databas sqlExecutor.dropDB(db); ``` -## 3. Complete Java SDK usage example +## 3. A Complete Java SDK usage example ```java import com._4paradigm.openmldb.jdbc.CallablePreparedStatement;