繁体   English   中英

Java中带有空值的SQL中SQL的动态填充

[英]Dynamic population of SQL in Java from array with nulls

举一个简单的问题例子:

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

这很难,因为我需要事先从插入中省略空字段。 例如,如果以上两个不为null:

 INSERT INTO test(4, 2, 1);

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

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

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

PS:我不想使用完整的ORM库,这看起来有点过分。

一个高级算法:

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

我会建议这样的事情:

  1. 运行SELECT * FROM <TABLE_NAME> LIMIT 1类的查询。 使用ResultSetMetaData检索columnNames及其columnType。 将其存储在HashMap中,并将其存储在ArrayList中

  2. 现在使用ArrayList中的键作为columnNames创建PreparedStatement 我想这并不难

  3. 现在给出数组中的数据,事实上你知道它们来自HashMap的SQL类型,你可以轻松地使用这些信息来映射你从数组中得到的值? 您生成的PreparedStatement。

现在的问题是如何处理null 好吧,因为你知道列的类型,如果你得到的值是null那么你可以使用PreparedStatement.setNull(...)将它们设置为null。

另外,只是想指出, 根据这个文档 ,有一个关于JDBC的setXXX(...)的重要指南:

6.1.5将JDBC NULL作为IN参数发送

setNull方法允许程序员将JDBC NULL(通用SQL NULL)值作为IN参数发送到数据库。 但请注意,仍必须指定参数的JDBC类型。

当Java null值传递给setXXX方法时(如果它将Java对象作为参数),JDBC NULL也将被发送到数据库。 但是,只有指定了JDBC类型,方法setObject才能获取空值。

这意味着你可以发送null作为setXX(...)方法的参数值,你真的不必显式调用setNull(..)方法。

我希望这对你有用!

不确定其他数据库系统,但在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循环做这件事可能更有意义。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM