代码之家  ›  专栏  ›  技术社区  ›  LIN LEE

使用带有WebSocket参数绑定的executeUpdate()时,为什么在TDengine中遇到Stmt API使用错误,如何解决?

  •  0
  • LIN LEE  · 技术社区  · 1 年前

    描述

    我正试图通过具有参数绑定的WebSocket连接插入200000个数据点(一次一个)。当我使用 executeUpdate() 方法,它抛出一个错误(0x22a):“Stmt API使用错误。”有趣的是,第一个数据点被成功插入,但从第二个数据点开始,我遇到了这个API使用错误。登录 taosAdapter 还显示了与以下错误类似的错误:

    image

    但是,如果我更换 executeUpdate() 具有 execute() ,代码成功运行,程序和 taosAdapter 报告任何错误。

    为了改进代码,我尝试创建一个 TSWSPreparedStatement 对于循环的每次迭代。这样 executeUpdate 方法成功运行,没有出现错误,并且数据插入成功。然而 taosAdapter 日志仍然显示了上面图像中描述的错误类型。

    以下是重现该问题的代码:

    import com.taosdata.jdbc.ws.TSWSPreparedStatement;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.sql.Statement;
    import java.sql.Timestamp;
    
    public class TestWSParamExecuteUpdate {
        private static final int RECORDS_PER_TABLE = 200000;
    
        public static void main(String[] args) throws SQLException {
            System.load("/usr/local/lib/libtaos.dylib");
            insertData();
        }
    
        private static void insertData() throws SQLException {
            long start = System.currentTimeMillis();
            try (final Connection conn = getConnection()) {
                createTable(conn);
    
                final String psql = "INSERT INTO power.d0 USING power.meters TAGS('California.SanFrancisco', 2) VALUES(?, ?, ?, ?)";
    
                try (final TSWSPreparedStatement pst = (TSWSPreparedStatement) conn.prepareStatement(psql)) {
                    System.out.println("-> Inserting data <-");
    
                    for (int i = 1; i <= RECORDS_PER_TABLE; i++) {
                        String[] parts = getRowData(i).split(",");
    
                        // Bind data columns
                        pst.setTimestamp(1, new Timestamp(Long.parseLong(parts[1]))); // ts
                        pst.setFloat(2, Float.parseFloat(parts[2])); // current
                        pst.setInt(3, Integer.parseInt(parts[3])); // voltage
                        pst.setFloat(4, Float.parseFloat(parts[4])); // phase
    
                        pst.executeUpdate(); // pst.execute() works without errors
    
                        if (i % 5000 == 0) {
                            System.out.println("------------Inserted data " + i);
                        }
                    }
                    System.out.println("Execution completed");
                } catch (SQLException e) {
                    System.out.println("ERROR Message: " + e.getMessage());
                    System.out.println("ERROR Code: " + e.getErrorCode());
                    e.printStackTrace();
                }
            }  catch (SQLException e) {
                System.out.println("ERROR Message: " + e.getMessage());
                System.out.println("ERROR Code: " + e.getErrorCode());
                e.printStackTrace();
            } finally {
                System.out.println("-> Data insertion took " + (System.currentTimeMillis() - start) + "ms <-");
            }
        }
    private static Connection getConnection() throws SQLException {
        System.out.println("-> Establishing connection <-");
        String jdbcUrl = "jdbc:TAOS-RS://localhost:6041/?batchfetch=true";
        return DriverManager.getConnection(jdbcUrl, "root", "taosdata");
    }
    
    private static void createTable(Connection conn) throws SQLException {
        System.out.println("-> Creating a database and hyper table <-");
        try (Statement stmt = conn.createStatement()) {
            stmt.execute("DROP DATABASE IF EXISTS power");
            stmt.execute("CREATE DATABASE IF NOT EXISTS power KEEP 3650");
            stmt.executeUpdate("USE power");
            stmt.execute("CREATE STABLE IF NOT EXISTS meters (ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT)" +
                    "TAGS (location BINARY(64), groupId INT)");
        }
    }
    
    private static String getRowData(int i) {
        final long time = 1691478964333L + i;
        return "d0," + time + ",10.30000,219,0.31000,California.SanFrancisco,2";
    }
    }
    

    环境

    macOS(版本:13.3.1(22E261),处理器:3.6 GHz四核英特尔酷睿i3,内存:16GB,磁盘空间:121GB)

    TDengine客户端版本:3.2.2.0

    TDengine服务器版本:3.2.2.0(客户端和服务器都在同一台机器上)

    taos jdbcdriver版本:3.2.4

    JDK版本:JDK 1.8

    1 回复  |  直到 1 年前
        1
  •  0
  •   Elliott Frisch    1 年前

    我认为没有充分的理由明确使用 TSWSPreparedStatement 而不是 PreparedStatement 。假设你真的想使用 分批 您需要调用 PreparedStatement.addBatch() Statement.executeBatch() 。有点像

    private static void insertData() throws SQLException {
        long start = System.currentTimeMillis();
        try (final Connection conn = getConnection()) {
            createTable(conn);
    
            final String psql = "INSERT INTO power.d0 USING power.meters TAGS('California.SanFrancisco', 2) VALUES(?, ?, ?, ?)";
    
            try (final PreparedStatement pst = conn.prepareStatement(psql)) {
                System.out.println("-> Inserting data <-");
                for (int i = 1; i <= RECORDS_PER_TABLE; i++) {
                    String[] parts = getRowData(i).split(",");
    
                    // Bind data columns
                    pst.setTimestamp(1, new Timestamp(Long.parseLong(parts[1]))); // ts
                    pst.setFloat(2, Float.parseFloat(parts[2])); // current
                    pst.setInt(3, Integer.parseInt(parts[3])); // voltage
                    pst.setFloat(4, Float.parseFloat(parts[4])); // phase
    
                    pst.addBatch();
                    if (i % 5000 == 0) {
                        pst.executeBatch();
                        System.out.println("------------Inserted data " + i);
                    }
                }
                pst.executeBatch();
                System.out.println("Execution completed");
            } catch (SQLException e) {
                System.out.println("ERROR Message: " + e.getMessage());
                System.out.println("ERROR Code: " + e.getErrorCode());
                e.printStackTrace();
            }
        } catch (SQLException e) {
            System.out.println("ERROR Message: " + e.getMessage());
            System.out.println("ERROR Code: " + e.getErrorCode());
            e.printStackTrace();
        } finally {
            System.out.println("-> Data insertion took " + (System.currentTimeMillis() - start) + "ms <-");
        }
    }