【发布时间】:2016-04-02 21:59:27
【问题描述】:
我正在我的 JAVA 应用程序和 PostgreSQL 数据库中进行过滤搜索。
我有以下用于选择航班数据的 PostgreSQL 查询:
String query = "SELECT flight.flight_id, route.from_location, route.to_location, flight.base_cost, flight.departure_date, flight.departure_time, flight.arrival_date, flight.arrival_time, aircraft.manufacturer, aircraft.seats " +
"FROM flight " +
"INNER JOIN route ON flight.route_id = route.route_id " +
"INNER JOIN aircraft ON flight.aircraft_id = aircraft.aircraft_id " +
"WHERE " +
"(from_location = CASE WHEN ? IS NULL THEN from_location ELSE ? END) AND " +
"(to_location = CASE WHEN ? IS NULL THEN to_location ELSE ? END) AND " +
"(base_cost = CASE WHEN ? IS NULL THEN base_cost ELSE ? END) AND " +
"(departure_date = CASE WHEN ? IS NULL THEN departure_date ELSE ? END) AND " +
"(departure_time = CASE WHEN ? IS NULL THEN departure_time ELSE ? END) AND " +
"(arrival_date = CASE WHEN ? IS NULL THEN arrival_date ELSE ? END) AND " +
"(arrival_time = CASE WHEN ? IS NULL THEN arrival_time ELSE ? END)";
然后我有一个这样的Java代码:
ResultSet rs = null;
PreparedStatement prepStatement = connection.prepareStatement(query);
try {
if (!showFromTxtField.getText().trim().isEmpty()) {
prepStatement.setString(1, showFromTxtField.getText());
prepStatement.setString(2, showFromTxtField.getText());
} else {
prepStatement.setNull(1, java.sql.Types.VARCHAR );
prepStatement.setNull(2, java.sql.Types.VARCHAR );
}
if (!showToTxtField.getText().trim().isEmpty()) {
prepStatement.setString(3, showToTxtField.getText());
prepStatement.setString(4, showToTxtField.getText());
} else {
prepStatement.setNull(3, java.sql.Types.VARCHAR );
prepStatement.setNull(4, java.sql.Types.VARCHAR );
}
if (!showCostTxtField.getText().trim().isEmpty()) {
prepStatement.setFloat(5, Float.parseFloat(showCostTxtField.getText()));
prepStatement.setFloat(6, Float.parseFloat(showCostTxtField.getText()));
} else {
prepStatement.setNull(5, java.sql.Types.FLOAT );
prepStatement.setNull(6, java.sql.Types.FLOAT);
}
LocalDate depDate = showDepDateDatePicker.getValue();
if (depDate != null) {
prepStatement.setDate(7, Date.valueOf(depDate));
prepStatement.setDate(8, Date.valueOf(depDate));
} else {
prepStatement.setNull(7, java.sql.Types.DATE );
prepStatement.setNull(8, java.sql.Types.DATE);
}
if (!showDepTimeTxtField.getText().trim().isEmpty()) {
DateFormat formatter = new SimpleDateFormat("HH:mm:ss");
try {
Time timeValue = new Time(formatter.parse(showDepTimeTxtField.getText()).getTime());
prepStatement.setTime(9, timeValue);
prepStatement.setTime(10, timeValue);
} catch (ParseException e) {
e.printStackTrace();
}
} else {
prepStatement.setNull(9, java.sql.Types.TIME );
prepStatement.setNull(10, java.sql.Types.TIME );
}
LocalDate arrDate = showArrDatePicker.getValue();
if (arrDate != null) {
prepStatement.setDate(11, Date.valueOf(arrDate));
prepStatement.setDate(12, Date.valueOf(arrDate));
} else {
prepStatement.setNull(11, java.sql.Types.DATE );
prepStatement.setNull(12, java.sql.Types.DATE);
}
if (!showArrTimeTxtField.getText().trim().isEmpty()) {
DateFormat formatter = new SimpleDateFormat("HH:mm:ss");
try {
Time timeValue = new Time(formatter.parse(showArrTimeTxtField.getText()).getTime());
prepStatement.setTime(13, timeValue);
prepStatement.setTime(14, timeValue);
} catch (ParseException e) {
e.printStackTrace();
}
} else {
prepStatement.setNull(13, java.sql.Types.TIME );
prepStatement.setNull(14, java.sql.Types.TIME );
}
rs = prepStatement.executeQuery();
} catch (SQLException e) {
e.printStackTrace();
}
因此,重点是仅返回符合文本字段条件的航班。如果任何文本字段留空,则查询应返回符合该特定条件的所有航班,但会使用其他非空条件进行过滤。
我在参数 $9 处出错。
当我将输入showDepTimeTxtField 的String(例如“18:00:00”)转换为java.sql.Time 对象时,我可以将其用作prepStatement 方法setTime() 的输入参数,我的查询应该只返回航班(已满足其他标准)departure_time 与在文本字段中输入的时间相同。如果文本字段为空且没有 String 输入,我的查询应该从我的数据库中返回带有 departure_time 的航班。
我的问题是,当我运行我的代码时,出现以下错误:
org.postgresql.util.PSQLException: ERROR: could not determine data type of parameter $9 无论我用字符串填充departureTimeTxtField 还是将其留空,所以参数departure_time 应该设置为NULL 并且我的查询应该返回所有 departure_time 的航班。
所以我假设我对 setTime() 方法参数 timeValue 以及从 String 到 java.sql.Time 的转换有问题。
如何进行正确的转换以消除该错误?
编辑:SQL 查询和 Java 源代码已更新。
【问题讨论】:
-
假设参数不为 null 并执行
SELECT * FROM flights WHERE departure_time = ?会发生什么?无论如何我都会这样做(如果您的参数为空,请使用select * from flights)。 -
您好,先生。当我只使用
SELECT * FROM flights WHERE departure_time = ?执行代码时,它已经工作了,但是我的查询要复杂得多。我做了修改,请看一下。 -
我将动态生成 SQL 查询,而不是使用处理所有可选参数的单个查询。例如,使用 QueryDSL。
-
您应该只对原始类型使用
setNull,对于所有非原始类型,您应该能够只使用setXXX(null)。检查您是否使用最新的 PostgreSQL 驱动程序,如果是,请提交错误报告,因为使用setTime(null)应该适用于兼容的 JDBC 驱动程序。
标签: java sql postgresql jdbc prepared-statement