运行时确定的数组(或列表)值的 JDBC

Posted

技术标签:

【中文标题】运行时确定的数组(或列表)值的 JDBC【英文标题】:JDBC for array (or list) values determined at run time 【发布时间】:2020-08-18 13:12:11 【问题描述】:

我正怀着浓厚的兴趣看这篇帖子How to insert array values in mysql database using java。但刚开始我发现 MySQL Workbench 拒绝了用于表创建和更新(插入)的指示 sql 语句。

我最终将 R 中的单行数据框加载到我的 MySQL 演示数据库中以创建表 itemtable。这并不理想,因为项目值旨在为整数,但从 R 中这样加载会将字段创建为双精度。

itemtable 字段是“time”、“item1”、“item2”、“duration” 初始行值为 0.0, 1, 1, 0.0

我创建了一个 Item 类:

public class Item 
    String name;
    double value;   
    public Item(String name, double value)  
        this.name = name;
        this.value = value;
    

在我的实际应用程序中,项目要复杂得多,并且价值是在不同时间计算的。所以我使用 LinkedList 来保存这些。就像我在 R 中所做的那样,作为其他数据表的输入,项目的数量因模型而异。

完整的测试代码 - 有效!!!如下:

public class Item 
    String name;
    double value;   
    public Item(String name, double value)  
        this.name = name;
        this.value = value;
    


import java.sql.*;
import java.util.LinkedList;
 
public class ItemTest 
    public static void main(String[] args) throws SQLException  
        Connection conn = null;
        PreparedStatement pstmt = null;
        Statement stmt = null;
        ResultSet rs = null;        
        String dbUrl = "jdbc:mysql://localhost:3306/demo?useSSL=false";
        String user = "student";
        String pass = "student";
        LinkedList<Item> itemList = new LinkedList<>();
        itemList.add(new Item("item1", 0.0));
        itemList.add(new Item("item2", 1.0));
        double timeNow = 30.0;
        double duration = 0.0;
        String qMarks = "";
        String names = "";
        for(int i = 0; i < itemList.size(); i++) 
            qMarks = qMarks + "?,";
            names = names + itemList.get(i).name + ",";
        
        System.out.println(qMarks);
        System.out.println(names);
        String pquery = "insert into itemtable(time," + names +
                "duration) values(?," + qMarks + "?)";
        System.out.println(pquery);
   
        try 
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/demo", "student" , "student");
            pstmt = conn.prepareStatement(pquery);
            pstmt.setDouble(1, timeNow);
            for(int i = 0; i<itemList.size(); i++) 
                pstmt.setDouble(i+2, itemList.get(i).value);
            
            pstmt.setDouble(itemList.size()+2, duration);
            int count = pstmt.executeUpdate();
            System.out.println(count + " inserted");
              
            stmt = conn.createStatement();
            rs = stmt.executeQuery("select * from itemtable");
            while (rs.next()) 
        System.out.println(rs.getDouble("time") + ", " + rs.getDouble("item1"));
            
        
        catch (SQLException exc)            
        
        finally 
            if (rs != null) rs.close();            
            if (stmt != null) stmt.close();
            if (conn != null) conn.close();
               
    

在 MySQL Workbench 中确认表插入的完整验证。

如果我能在 java 代码中创建 itemtable 还是不错的。

【问题讨论】:

请提供更多信息。您使用什么 sql 语句?你得到什么错误? MySQL 不支持 ARRAY 作为数据类型。这就是为什么无论你怎么努力,你都不会得到预期的结果。 【参考方案1】:

正如链接的 SO 帖子告诉您的那样:SQL 的“ARRAY”概念(由 JDBC 的 .setArray 和 .getArray 以及 java.sql.Array 反映)在 mysql 中不起作用。完全没有。

我建议您使用更好的数据库引擎,例如 postgres。否则,好吧,你不能有数组;您可以尝试做的是制作一个表格来表示它。 DB中通常的多对一内容:不是“数组”,而是第二个表,其中包含整个数据集中所有数组中每个“槽”的1行:此“数组表”中的每一行都包含数据以及参考。

所以,例如:

-- This works in PSQL:
CREATE TABLE example (id integer, whatever text, names text[], PRIMARY KEY(id));
-- but the above does not work in MySQL, so there do e.g.:

CREATE TABLE example (id integer, whatever text, PRIMARY KEY(id));
CREATE TABLE example_names (id integer, example_id integer, name text, PRIMARY KEY(id));
CREATE INDEX example_names_lnk ON example_names(example_id);

【讨论】:

【参考方案2】:

事实证明,我尝试对在运行时定义数量的列表项执行的操作确实与尝试在 MySQL 表中输入数组不同,我现在明白这是无法完成的。我很欣赏前面的讨论,这激发了我对所需解决方案的兴趣。

create table sql 以直接的方式生成,在运行时处理未知内容的关键是使用 item 列的循环构建查询字符串。一个循环为 create 语句和prepared 语句构建了内部字符串项。

所以在java代码中创建表的sql是直截了当的。项目值现在可以是预期的整数。

        String qMarks = "";
        String names = "";
        String items = "";
        for(int i = 0; i < itemList.size(); i++) 
            qMarks = qMarks + "?,";
            names = names + itemList.get(i).name + ",";
            items = items + itemList.get(i).name +" INTEGER,";
        
        String createsql = "CREATE TABLE ITEMTABLE (" +
                            "time DOUBLE, " + items +
                            "duration DOUBLE)";

【讨论】:

以上是关于运行时确定的数组(或列表)值的 JDBC的主要内容,如果未能解决你的问题,请参考以下文章

字典、列表还是数组? [关闭]

在运行时格式化字符串

VB列表框属性的问题

Python:当列表仅在运行时确定时,如何将可迭代列表传递给 zip?

转换为指向运行时确定大小的数组的指针

如何使用 Spring 管理具有不同 jdbc(或休眠?)的多个“运行时注意到”数据库连接?