3

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

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

现在,在 Java 中,我有一个与数据库内容匹配的对象数组。我需要使用数组值为此数据库表创建插入/更新/删除语句。

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

但这变得很困难,因为我需要提前从插入中删除空字段。例如,如果以上两个不为空:

 INSERT INTO test(4, 2, 1);

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

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

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

PS:我不想使用完整的 ORM 库,这似乎有点矫枉过正。

4

3 回答 3

1

我会建议这样的事情:

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

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

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

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

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

6.1.5 将 JDBC NULL 作为 IN 参数发送

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

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

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

我希望这对你有用!

于 2012-09-14T19:14:11.633 回答
1

高级算法:

  1. 存储一个列名数组(与输入参数的顺序相同)——我们称之为allColumnNames——作为类的一个字段。
  2. 调用该方法时,创建两个新的空List<String>s,一个表示列名,一个表示值 - 我们称这些为columnNamesListand columnValuesList
  3. 遍历输入数组,对于每个非空元素,添加allColumnNames[i]到.columnNamesListvalues[i]columnValuesList
  4. 通过将,INSERT INTO tablename中的每个值的逗号分隔列表和 中的每个值的逗号分隔列表连接在一起来构建插入语句。columnNamesVALUEScolumnValuesList
于 2012-09-14T18:52:04.423 回答
0

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

于 2012-09-14T19:36:25.580 回答