所以我有4个菜单选项(产品,位置,courseType和类别),所有这些都可以为null(使用JSF编程,但这应该与此问题无关,因为它是一个SQL问题).
菜单选择将向托管bean发送用户选择的变量,并使用准备好的语句使用用户选择的菜单中的信息(如果有)搜索数据库表.
如果用户将菜单项保留为null,则应搜索所有内容.
如果用户将1或2或3个菜单项留下信息,而另一个留空,则应相应地进行搜索.
我的问题是如何在没有附加到适当的sql语句的bean中的一堆if/then语句的情况下执行此操作?
或者是否有一个更好的sql语句我可以做到这一切吗?
我在Java中使用准备好的语句.
我试过这个:
if (product != null && location != null && courseType != null && category != null) {
pstmt = conn.prepareStatement("select * FROM Courses WHERE "
+ "product = ? "
+ "and location = ? "
+ "and courseType = ? "
+ "and category = ?");
pstmt.setString(1, product);
pstmt.setString(2, location);
pstmt.setString(3, courseType);
pstmt.setString(4, category);
} else if (product == null && location != null && courseType != null && category != null) {
pstmt = conn.prepareStatement("select * FROM Courses WHERE "
+ "location = ? "
+ "and courseType = ? "
+ "and category = ?");
pstmt.setString(1, location);
pstmt.setString(2, courseType);
pstmt.setString(3, category);
}
Run Code Online (Sandbox Code Playgroud)
等等,但我必须这样做16次,每个案例1为空而不是其他情况?必须有一个更聪明的方法(通过使用1个sql语句或只有几个java if/then语句?)
更新感谢Luiggi Mendoza!我的代码是这样的:
pstmt = conn.prepareStatement("select * FROM Courses WHERE "
+ "(product = ? or ? is null) "
+ "and (location = ? or ? is null) "
+ "and (courseType = ? or ? is null)"
+ "and (category = ? or ? is null)");
pstmt.setString(1, product);
pstmt.setString(2, product);
pstmt.setString(3, location);
pstmt.setString(4, location);
pstmt.setString(5, courseType);
pstmt.setString(6, courseType);
pstmt.setString(7, category);
pstmt.setString(8, category);
rset = pstmt.executeQuery();
Run Code Online (Sandbox Code Playgroud)
更新是的我不得不使用=""而不是为一个不同的mysql数据库是null(可能是不同的版本或东西)
我假设你有一个NULL所选值的默认值(因为我不知道使用它的另一种方法PreparedStatement)'0'(仅作为一个例子).
知道了这一点,我倾向于使用这种SQL:
SELECT *
FROM Courses
WHERE
(product = ? or ? = '0')
and (location = ? or ? = '0')
and (courseType = ? or ? = '0')
and (category = ? or ? = '0')
Run Code Online (Sandbox Code Playgroud)
使用此方法,您可以利用该IF用法并让数据库处理工作.唯一不好的一点是你应该将每个变量设置两次(这一生中没有任何东西是自由的= \).
编辑:我已根据您的要求进行了测试.首先是SQL表和内容:
create table pruebaMultiSelect
(id int primary key auto_increment,
nombre varchar(50),
tipo varchar(10),
categoria varchar(10));
insert into pruebaMultiSelect values
(null, 'Luiggi', 'A', 'X');
insert into pruebaMultiSelect values
(null, 'Thomas', 'A', 'Y');
insert into pruebaMultiSelect values
(null, 'Jose', 'B', 'X');
insert into pruebaMultiSelect values
(null, 'Trina', 'B', 'Y');
Run Code Online (Sandbox Code Playgroud)
现在,相关的Java代码:
public class DBTest {
public void testPreparedStatement(String p1, String p2) throws SQLException {
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = getConnection();
pstmt = con.prepareStatement("SELECT * FROM pruebaMultiSelect WHERE (tipo = ? OR ? = 'EMPTY') "
+ "AND (categoria = ? OR ? = 'EMPTY')");
pstmt.setString(1, p1);
pstmt.setString(2, p1);
pstmt.setString(3, p2);
pstmt.setString(4, p2);
rs = pstmt.executeQuery();
while (rs.next()) {
System.out.printf("%5d %15s\n", rs.getInt(1), rs.getString(2));
}
} catch(ClassNotFoundException e) {
e.printStackTrace();
} finally {
rs.close();
pstmt.close();
con.close();
}
}
public Connection getConnection() throws SQLException, ClassNotFoundException {
Class.forName("com.mysql.jdbc.Driver");
return DriverManager.getConnection("jdbc:mysql://localhost:3306/luiggi_test", "user", "password");
}
public static void main(String[] args) throws SQLException {
//this will return all the data
String p1 = "EMPTY";
String p2 = "EMPTY";
new DBTest().testPreparedStatement(p1, p2);
}
}
Run Code Online (Sandbox Code Playgroud)
使用MySQL 5.1.18测试.
我倾向于使用这样的辅助方法构建动态查询:
StringBuilder query = new StringBuidler();
query.append("SELECT foo, bar FROM baz");
query.append(buildProductClause(product));
query.append(buildLocationClause(location));
query.append(buildCourseTypeClause(courseType));
// etc...
Run Code Online (Sandbox Code Playgroud)
如果您仍想使用准备好的语句,则可以使用成员字段来构建参数数组。
| 归档时间: |
|
| 查看次数: |
21333 次 |
| 最近记录: |