此代码用于更新sql中的客户数据。如何简化此代码?还有另一种方法吗?
if (!clienteOld.getNome().equalsIgnoreCase(clienteNew.getNome())) {
stmt.executeUpdate("UPDATE CLIENTES SET NOME = '" + clienteNew.getNome() + "' WHERE ID = " + id1 + ";");
criarLog("Ficha do cliente: " + clienteOld.getNome() + " foi atualizada -- NOME=" + clienteNew.getNome());
}
if (!clienteOld.getDataNascimento().equalsIgnoreCase(clienteNew.getDataNascimento())) {
stmt.executeUpdate("UPDATE CLIENTES SET DATA_NASCI = '" + clienteNew.getDataNascimento() + "' WHERE ID = " + id1 + ";");
criarLog("Ficha do cliente: " + clienteOld.getNome() + " foi atualizada -- DATA NASCIMENTO=" + clienteNew.getDataNascimento());
}
if (!clienteOld.getMorada().equalsIgnoreCase(clienteNew.getMorada())) {
stmt.executeUpdate("UPDATE CLIENTES SET MORADA = '" + clienteNew.getMorada() + "' WHERE ID = " + id1 + ";");
criarLog("Ficha do cliente: " + clienteOld.getNome() + " foi atualizada -- MORADA=" + clienteNew.getMorada());
}
if (!clienteOld.getPais().equalsIgnoreCase(clienteNew.getPais())) {
stmt.executeUpdate("UPDATE CLIENTES SET PAIS = '" + clienteNew.getPais() + "' WHERE ID = " + id1 + ";");
criarLog("Ficha do cliente: " + clienteOld.getNome() + " foi atualizada -- PAIS=" + clienteNew.getPais());
}
if (!clienteOld.getNacionalidade().equalsIgnoreCase(clienteNew.getNacionalidade())) {
stmt.executeUpdate("UPDATE CLIENTES SET NACIONALIDADE = '" + clienteNew.getNacionalidade() + "' WHERE ID = " + id1 + ";");
criarLog("Ficha do cliente: " + clienteOld.getNome() + " foi atualizada -- NACIONALIDADE=" + clienteNew.getNacionalidade());
}
if (!clienteOld.getBI().equalsIgnoreCase(clienteNew.getBI())) {
stmt.executeUpdate("UPDATE CLIENTES SET BI = '" + clienteNew.getBI() + "' WHERE ID = " + id1 + ";");
criarLog("Ficha do cliente: " + clienteOld.getNome() + " foi atualizada -- BI=" + clienteNew.getBI());
}
if (!clienteOld.getTipoIndentificaçao().equalsIgnoreCase(clienteNew.getTipoIndentificaçao())) {
stmt.executeUpdate("UPDATE CLIENTES SET TIPO_IDENT = '" + clienteNew.getTipoIndentificaçao() + "' WHERE ID = " + id1 + ";");
criarLog("Ficha do cliente: " + clienteOld.getNome() + " foi atualizada -- TIPO IDENTIFICAÇAO=" + clienteNew.getTipoIndentificaçao());
}
答案 0 :(得分:1)
尝试以下逻辑:
StringBuilder sql = new StringBuilder("UPDATE CLIENTES SET ");
Map<String, String> cols = new HashMap<>();
if (!clienteOld.getNome().equalsIgnoreCase(clienteNew.getNome())) {
cols.put("NOME", clienteNew.getNome());
}
if (!clienteOld.getDataNascimento().equalsIgnoreCase(clienteNew.getDataNascimento())) {
cols.put("DATA_NASCI", clienteNew.getDataNascimento());
}
// and the other if statements
然后,您可以迭代地图并构建实际的更新语句:
int cnt = 0;
for (Map.Entry<Integer, Integer> entry : cols.entrySet()) {
if (cnt > 0) sql.append(", ");
sql.append(entry.getKey()).append(" = '").append(entry.getValue()).append("'");
++cnt;
}
sql.append(" WHERE ID = ").append(id1).append(";");
但是请注意,这种方法不是SQL注入安全的 。如果这些值来自外部,例如UI,那么您绝对应该使用准备好的语句。对每个if条件使用单独的语句本质上没有错。我只是回答表明,如果合适,您可以清理当前的方法。
答案 1 :(得分:1)
if (!oldClient.getName().equalsIgnoreCase(newClient.getName())) {
stmt.executeUpdate("UPDATE CLIENTS SET NAME = '" + newClient.getName() +
"' WHERE ID = " + id1 + ";");
}
if (!oldClient.getBirthDate().equalsIgnoreCase(newClient.getBirthDate())) {
stmt.executeUpdate("UPDATE CLIENTS SET BIRTH = '" + newClient.getBirthDate() +
"' WHERE ID = " + id1 + ";");
}
可以改写为
if (!oldClient.getName().equalsIgnoreCase(newClient.getName()) ||
!oldClient.getBirthDate().equalsIgnoreCase(newClient.getBirthDate())) {
stmt.executeUpdate("UPDATE CLIENTS SET NAME = '" + newClient.getName() +
"', BIRTH = '" + newClient.getBirthDate() +
"' WHERE ID = " + id1 + ";");
}
这将更好地执行,因为它执行一个SQL语句而不是两个。与之相比,当您只需要设置一列时就可以设置两列的事实可能没有多大意义。
注意:
如果尝试“优化”设置的列数,则代码会更加复杂;参见蒂姆的答案。
这可能应该使用PreparedStatement
和语句参数来完成,以避免SQL注入。如果遵循上述模式,则直接使用PreparedStatement
所需的更改。
答案 2 :(得分:0)
首先,您可以使用一个查询来更新每个字段:
"UPDATE CLIENTES SET DATA_NASCI "
+ "MORADA = '" + clienteNew.getMorada() + "'"
+ "PAIS = '" + clienteNew.getPais() + "'"
+ "NACIONALIDADE = '" + clienteNew.getNacionalidade() + "'"
+ "BI = '" + clienteNew.getBI() + "'"
+ "TIPO_IDENT = '" + clienteNew.getTipoIndentificaçao() + "'"
+ "WHERE ID = " + id1 + ";"
请使用PreparedStatement
代替它,这样会更安全!
您要做的就是使用条件检查是否只有一个字段发生了更改(以防止事务不执行任何操作):
if (!clienteOld.getNome().equalsIgnoreCase(clienteNew.getNome()))
|| (clienteOld.getDataNascimento().equalsIgnoreCase(clienteNew.getDataNascimento()))
|| (!clienteOld.getMorada().equalsIgnoreCase(clienteNew.getMorada()))
|| (!clienteOld.getPais().equalsIgnoreCase(clienteNew.getPais()))
|| (!clienteOld.getNacionalidade().equalsIgnoreCase(clienteNew.getNacionalidade()))
|| (!clienteOld.getBI().equalsIgnoreCase(clienteNew.getBI()))
|| (!clienteOld.getTipoIndentificaçao().equalsIgnoreCase(clienteNew.getTipoIndentificaçao()))
这可能有点冗长...所以为什么不使用Stream和一些函数引用来比较并构建要更新的值映射呢?
首先,我们的示例为Bean
类:
class Bean {
String firstname, lastname;
public Bean(String firstname, String lastname) {
this.firstname = firstname;
this.lastname = lastname;
}
public String getFirstname() {
return firstname;
}
public String getLastname() {
return lastname;
}
}
然后,我们创建一个Column name
和Function
的映射,该函数将允许我们使用Bean
的吸气剂:
Map<String, Function<Bean, String>> functions = new HashMap<>();
functions.put("FIRSTNAME", Bean::getFirstname);
functions.put("LASTNAME", Bean::getLastname);
然后,使用final
实例(在谓词中使用)
final Bean clienteNew = new Bean("Foo", "Bar");
final Bean clienteOld = new Bean("Foo", "Boo");
Map<String, String> values = functions.entrySet()
.stream()
//filter only the value that changed between clienteOld and clienteNew
.filter(entry -> !entry.getValue().apply(clienteOld).equals(entry.getValue().apply(clienteNew)))
//then collect the map `name -> new value`
.collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue().apply(clienteNew)));
System.out.println(values);
{LASTNAME = Bar}
这将为您提供一个Map<String, String>
,可用于仅创建我们想要/需要编辑的列即可创建PreparedStatement
。
如果您有一个新字段,只需将映射添加到functions
映射中就可以了。 (使用原始类型会变得更加复杂...)