我正在尝试修改一些Java现有代码(我没有完成),我发现查询没有使用prepare语句完成。 因为我有很多代码,我试图尽可能少地修改它。 所以没有像
那样的方法public void executeInsertStmt(String strQuery, String param1, String param2) {
...
...
PreparedStatement preparedStatement = cnx.prepareStatement(stringRequest);
preparedStatement.setString(1, param1);
preparedStatement.setString(2, param2);
}
我想做那样的事情(我不确定这是最好的解决方案)。
public void executeInsertStmt(String strQuery, ArrayList<ArrayList<Object>> parameters) {
PreparedStatement preparedStatement = cnx.prepareStatement(stringRequest);
int counter=1;
for (final ArrayList<Object> eachParam : parameters) {
switch(DataTypes.valueOf(eachParam.get(0).toString().toUpperCase()))
{
case STRING:
preparedStatement.setString(counter, (String)eachParam.get(1));
break;
case DATE:
preparedStatement.setDate(counter, (Date)eachParam.get(1));
break;
case INT:
preparedStatement.setInt(counter, (Integer)eachParam.get(1));
break;
default:
preparedStatement.setString(counter, (String)eachParam.get(1));
break;
}
counter++;
}
}
然后有这样的事情:
strQuery = "insert into toto values (?,?)";
ArrayList<Object> paramToPass1 = new ArrayList<Object>();
paramToPass1.add("String");
paramToPass1.add("TheValueForTheString");
ArrayList<Object> paramToPass2 = new ArrayList<Object>();
paramToPass2.add("String");
paramToPass2.add("TheValueForTheString2");
ArrayList<ArrayList<Object>> paramToPass = new ArrayList<ArrayList<Object>>();
paramToPass.add(paramToPass1);
paramToPass.add(paramToPass2);
executeInsertStmt(strQuery,paramToPass);
因为我有许多不同参数的查询,这种方法对我来说是最好的。 我不需要为每种类型的查询做一个方法。
你怎么想。
这有什么不对吗? 是最好的方式吗?
感谢您的任何想法。
答案 0 :(得分:1)
您应该为参数使用对象表示,而不是大小为2的ArrayList<Object>
。此外,您不需要自己的DataType
枚举,已经有java.sql.Types
类。最重要的是,setObject()
上的PreparedStatement
方法可识别这些类型的值,因此您不需要switch
语句或调用特定于类型的PreparedStatement.set..()
方法。
这是一个具有参数对象表示的解决方案,利用java.sql.Types
和preparedStatement.setObject()
对这些类型的支持,并使您与类型常量值隔离。
首先,参数的对象表示:
import java.sql.Types;
public class ParamDescriptor {
// Constructor itself is private, we are encapsulating so that
// you don't need to write java.sql.Types constants yourself
private ParamDescriptor(int dataType, Object value) {
_dataType = dataType;
_value = value;
}
// Factory methods for actual instantiation
public static ParamDescriptor forInt (int paramVal) {
return new ParamDescriptor (Types.INTEGER, paramVal);
}
public static ParamDescriptor forString (String paramVal) {
return new ParamDescriptor (Types.VARCHAR, paramVal);
}
public static ParamDescriptor forDate (Date paramVal) {
return new ParamDescriptor (Types.DATE, paramVal);
}
// Add more here to support more data types . . . .
public int getDataType() {
return _dataType;
}
public Object getValue() {
return _value;
}
private int _dataType;
private Object _value;
}
接下来是executeInsertStmt()
的新版本。我们已将其减少到几行,无论将来是否支持参数类型,它都不需要再次更改:
public void executeInsertStmt(String strQuery, List<ParamDescriptor> parameters) throws SQLException {
PreparedStatement preparedStatement = cnx.prepareStatement(strQuery);
int counter = 1;
for (ParamDescriptor paramDescriptor : parameters) {
preparedStatement.setObject(counter,
paramDescriptor.getValue(),
paramDescriptor.getDataType());
counter++;
}
}
最后,代码将调用新的executeInsertStmt()
:
String strQuery = "insert into toto values (?,?)";
ParamDescriptor paramToPass1 = ParamDescriptor.forString("TheValueForTheString");
ParamDescriptor paramToPass2 = ParamDescriptor.forString("TheValueForTheString2");
List<ParamDescriptor> parameters = new ArrayList<ParamDescriptor>();
parameters.add(paramToPass1);
parameters.add(paramToPass2);
executeInsertStmt(strQuery, parameters);
请注意,如果您计划处理小数,则还有另一个版本的PreparedStatement.setObject()
支持指定小数。您可能需要在executeInsertStmt()
。
答案 1 :(得分:0)
嗯,你的想法不错......只是一些指示。
不要传递ArrayList的ArrayList ...而是使用instanceof或DataHolder类。
方法1:instanceof
简单地添加类型Integer,String,Double等然后在你的方法中:
public void executeInsertStmt(String strQuery, ArrayList<Object> parameters) {
PreparedStatement preparedStatement = cnx.prepareStatement(stringRequest);
int counter=1;
for (final Object eachParam : parameters) {
if (eachParam instanceof String) {
preparedStatement.setString(counter, (String)eachParam);
} else if (eachParam instanceof Integer) {
preparedStatement.setInt(counter, (Integer)eachParam);
} else ...
counter++;
}
}
DataHolder的想法是,一个字段将保留类型,另一个字段保留实际数据。你甚至可以使用泛型来使它更好。但是,我会在这种情况下使用。