Java Swing调用SQLite多条件搜索结果异常问题求助
问题分析与解决方案
你的核心问题出在三个地方:LIKE操作符未使用通配符、空输入未做处理、SQL语句拼接逻辑不合理,同时还存在SQL注入风险,逐个解决就能修复多条件搜索的问题:
1. 缺失LIKE通配符导致匹配逻辑错误
你当前的LIKE语句是v.make LIKE '" + make + "',这种写法只会匹配完全等于输入内容的记录,而非模糊搜索。比如输入"Ford",只会找到make字段完全是"Ford"的记录,而不是包含"Ford"的。单条件搜索时可能刚好输入了完全匹配的值,所以看似正常,但组合条件时就会出现偏差。
正确的模糊搜索需要在匹配值前后加上%通配符,比如v.make LIKE '%Ford%',表示匹配包含"Ford"的任意字符串。
2. 空输入未处理导致AND/OR逻辑失效
当你只填写一个条件,另一个输入框为空时:
- 用AND的话,空输入会生成
v.make LIKE '' AND t.test_result LIKE 'Pass',LIKE ''只会匹配字段为空的记录,自然无结果返回; - 用OR的话,空输入会生成
v.make LIKE '' OR t.test_result LIKE 'Pass',会把所有make字段为空的记录也查出来,导致结果偏差。
解决方法是动态构建WHERE子句:只有当输入框内容不为空时,才将该条件加入查询。
3. 使用Statement拼接SQL存在注入风险
直接拼接字符串生成SQL语句,不仅容易出错,还存在SQL注入漏洞,应该改用PreparedStatement预编译语句,既安全又能避免字符串拼接的语法错误。
修正后的代码示例
重点修改按钮点击事件中的查询逻辑:
bMake.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { String make = tf1.getText().trim(); String testResult = tf4.getText().trim(); // 动态构建SQL和参数列表 StringBuilder sqlBuilder = new StringBuilder("SELECT DISTINCT * FROM Vehicle v JOIN Test t ON v.vehicle_id = t.vehicle_id WHERE 1=1"); List<String> params = new ArrayList<>(); if (!make.isEmpty()) { sqlBuilder.append(" AND v.make LIKE ?"); params.add("%" + make + "%"); // 添加通配符实现模糊搜索 } if (!testResult.isEmpty()) { sqlBuilder.append(" AND t.test_result LIKE ?"); params.add("%" + testResult + "%"); } try (Connection c = DriverManager.getConnection("jdbc:sqlite:./data/Tables.db"); PreparedStatement pstmt = c.prepareStatement(sqlBuilder.toString())) { // 设置参数 for (int i = 0; i < params.size(); i++) { pstmt.setString(i + 1, params.get(i)); } ResultSet rs = pstmt.executeQuery(); dtm.setRowCount(0); while (rs.next()) { int ID = rs.getInt("vehicle_ID"); String make_ = rs.getString("make"); String model_ = rs.getString("model"); String colour = rs.getString("colour"); String fuel = rs.getString("fuel_type"); String cylinder = rs.getString("cylinder_capacity"); String use = rs.getString("first_use"); int test_id = rs.getInt("test_id"); String test_type = rs.getString("test_type"); String test_class = rs.getString("test_class"); String test_date = rs.getString("test_date"); String test_result = rs.getString("test_result"); String test_mileage = rs.getString("test_mileage"); // 注意这里要用结果集的make_,而不是用户输入的make dtm.addRow(new Object[]{ID, make_, model_, colour, fuel, cylinder, use, test_id, test_type, test_class, test_date, test_result, test_mileage}); } } catch (SQLException e1) { e1.printStackTrace(); } } });
额外注意点
- 代码中你原本在
addRow时用了用户输入的make,而不是从结果集获取的make_,这会导致显示错误(比如模糊搜索时,显示的是输入的关键词而非数据库实际值),已经在修正代码中改过来了; 1=1是动态构建WHERE子句的常用技巧,保证即使没有任何条件,SQL语法依然合法;- 使用try-with-resources语句自动关闭Connection和PreparedStatement,避免资源泄漏。
内容的提问来源于stack exchange,提问作者FlorenceBully
相关产品推荐
相关产品推荐

