我知道硬编码任何东西都是不好的。通常我们通过配置文件来做大部分的环境变量。例如,数据库属性、项目配置、log4j、输入、输出。
但是今天我看到有人写了这样的代码:
public void updateExistedRecord(SgsnMapping sgsnMapping) throws Exception {
PreparedStatement ps = null;
try {
String updateSql = "";
updateSql += "UPDATE " + schema + "." + tableSgsnMapping + " SET ";
//other where clause
ps = dbConn.prepareStatement(updateSql);
ps.executeUpdate();
} catch (Exception ex) {
logger.error("Error when update an existing record on " + tableSgsnMapping + " table.n" + ex.getMessage(), ex);
throw ex;
} finally {
SqlHelper.close(ps);
}
}
重点是表-tableSgsnMapping,它是以这样的方式写在其他地方的
:private String tableSgsnMapping = ConstantManager.TABLE_SGSN_MAPPING;
反过来,TABLE_SGSN_MAPPING在其他地方定义:
public final static String TABLE_SGSN_MAPPING = "OBDUA_SGSN_MAPPING";
是不是太过分了?该表不会更改其名称,它将始终存在。为什么不在程序中对其进行硬编码?为什么?
使用从字符串创建的语句(即使它们在常量中)存在更严重的问题 - 您可能会打开 SQL 注入的大门。从安全角度来看,最好改用预准备语句,通过setXXX()
方法设置参数,而不是像问题中那样连接字符串。
预准备语句的文本定义为使用它的类中的常量字符串,并带有参数的占位符。例如:
private static final String query =
"update dbName.tableName set field = ? where condition = ?";
tableSgsnMapping
的值总是ConstantManager.TABLE_SGSN_MAPPING
?然后我会使用这个常量,也许作为静态导入来节省一些空间。将其重新分配给局部变量可能会使读者感到困惑,并在意外更改其值时引入错误。
表的名称可能不会像您所说的那样更改。但谁知道未来呢?
但我的主要优点ConstantManager.TABLE_SGSN_MAPPING
是,表名和列名通常在代码的不同语句和位置多次使用。使用常量,您可以确定,在一个很少使用的 SQL 语句中没有关于这些事情的拼写错误。在这个角落里,我最喜欢的是:表名是否是复数形式?("客户"与"客户")。我只是不想每次都考虑这个问题 - 通过使用常量。