有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Java中SQL的动态填充(从带null的数组)

举一个简单的例子来说明我的问题:

//Create database table allowing nulls.
CREATE TABLE test(one int not null, two int null, three int not null);

现在,在Java中,我有一个与数据库内容匹配的对象数组。我需要使用数组值为此数据库表创建insert/update/delete语句

Object[] arr = { 4, null, 1 };
String sql = GenereateInsert(arr);

但是这会变得很困难,因为我需要提前在insert中省略空字段。例如,如果上面的两个不为空:

 INSERT INTO test(4, 2, 1);

一切都很容易。但如果为空,我需要声明为:

 INSERT INTO test(one, three) values(4, 1);

我正在处理的表有50列以上,所以我不想手动执行此操作,它将无法管理。那么,人们通常如何解决这个问题呢?这一定是一种普遍的情况

PS:我不想使用完整的ORM库,这似乎有些过分


共 (3) 个答案

  1. # 1 楼答案

    不确定是否有其他数据库系统,但在postgres中可以按如下方式插入空值:

    CREATE TABLE test(
      id       SERIAL PRIMARY KEY,
      val1     INTEGER DEFAULT NULL,
      val2     INTEGER DEFAULT NULL,
      val3     INTEGER DEFAULT NULL
    );
    
    INSERT INTO test(val1, val2, val3) VALUES(DEFAULT, DEFAULT, DEFAULT);
    

    也可以用相同的方法执行set语句:

    UPDATE test SET val1 = DEFAULT, val2 = 123, val3 = DEFAULT WHERE id = 3;
    

    因此,

    Stringbuilder sqlStmt = new StringBuilder();
    sqlStmt.append("INSERT INTO test(val1, val2, val3) VALUES(");
    sqlStmt.append(((val1 == null) ? "DEFAULT" : val1.toString()));
    sqlStmt.append(" , ");
    sqlStmt.append(((val2 == null) ? "DEFAULT" : val2.toString()));
    sqlStmt.append(" , ");
    sqlStmt.append(((val3 == null) ? "DEFAULT" : val3.toString()));
    sqlStmt.append(";");
    statement.execute(sqlStmt.toString());
    

    如果有很多这样的循环,那么使用for-each循环可能更有意义

  2. # 2 楼答案

    我建议这样做:

    1. 运行类似SELECT * FROM <TABLE_NAME> LIMIT 1的查询。使用^{}检索列名及其列类型。将其存储在HashMap中,并将键存储在ArrayList中

    2. 现在使用ArrayList中的键作为列名创建一个PreparedStatement我想这不难做到

    3. 现在,考虑到数组中的数据,以及您知道它们来自HashMap的SQL类型这一事实,您可以轻松地使用此信息将从数组中获得的值映射到生成的PreparedStatement的?

    现在的问题是如何处理null。因为您知道列的类型,如果您得到的值是null,那么您可以使用^{}将它们设置为null

    另外,我只想指出,according to this document,这里有一个关于setXXX(…)的重要指南

    6.1.5 Sending JDBC NULL as an IN parameter

    The setNull method allows a programmer to send a JDBC NULL (a generic SQL NULL) value to the database as an IN parameter. Note, however, that one must still specify the JDBC type of the parameter.

    A JDBC NULL will also be sent to the database when a Java null value is passed to a setXXX method (if it takes Java objects as arguments). The method setObject, however, can take a null value only if the JDBC type is specified.

    这意味着您可以发送null作为setXX(...)方法的参数值,而实际上不必显式调用setNull(..)方法

    我希望这对你有用

  3. # 3 楼答案

    高级算法:

    1. 存储一个列名数组(和输入参数的顺序相同)——让我们将其称为allColumnNames——作为类的字段
    2. 调用该方法时,创建两个新的空List<String>,一个表示列名,一个表示值-让我们调用它们columnNamesListcolumnValuesList
    3. 迭代输入数组,对于每个非空元素,将allColumnNames[i]添加到columnNamesList,将values[i]添加到columnValuesList
    4. 通过将INSERT INTO tablenamecolumnNamesVALUES中的每个值的逗号分隔列表以及columnValuesList中的每个值的逗号分隔列表连接在一起,构建insert语句