所以我有一个简单的函数来从数据库中返回一些东西。然后,我可以通过在 WHERE 子句中添加不同的参数来修改此查询。处理这个问题最优雅有效的方法是什么?
示例:
public static getUsers(int id, string username, string email) {
Connection conn = null;
PreparedStatement stmt = null;
String sql = "";
sql = "SELECT * FROM users " .........
这就是我对where子句感到困惑的地方。如果我做了像
这样的事情"WHERE id = ? AND username = ? AND email = ?";
如果我只使用ID调用方法,没有用户名或电子邮件,会发生什么?它会破裂,我不能发生这种情况。
另外,管理我的索引变得很难,因为如果我会做stmt.setInt(1, id)
这样的事情,但是如果我只想用用户名调用该方法,并且该id将以null形式出现,那么该怎么办?投掷NPE?
我对Java不熟悉,抱歉......但我想我应该使用覆盖?我应该在条件语句中构建我的where子句吗?任何帮助,将不胜感激。
谢谢
答案 0 :(得分:2)
我将创建一个实现Builder Pattern的SqlQuery类。 This是一篇很好的文章,解释了模式的用法。
示例:
public class SqlQuery {
private StringBuilder tableQuery = new StringBuilder();
private StringBuilder whereQuery = new StringBuilder();
public SqlQuery(String selection, String table) {
tableQuery.append("SELECT ").append(selection).append(" FROM ").append(table);
}
public SqlQuery addWhereClause(String parameter, String value) {
if (whereQuery.length() == 0) {
whereQuery.append(" WHERE ");
}
else {
whereQuery.append(" AND ");
}
whereQuery.append(parameter).append(" = ").append(value);
return this;
}
public String toString() {
return tableQuery.toString() + whereQuery.toString();
}
}
SqlQuery sqlQ = new SqlQuery("*", "users")
.addWhereClause("id", "2")
.addWhereClause("email", "test");
System.out.println(sqlQ);
打印:
SELECT * FROM users WHERE id = 2 AND email = test
答案 1 :(得分:0)
写if else语句,即
if(username!=null)
query=query+"username=?";
和
if(username!=null)
stmt.setInt(2, username)
答案 2 :(得分:0)
我会做这样的事情,创建一个接受List<ColumnNames>
的方法,并在该方法中通过将占位符附加到列名称来循环遍历所有列名。
public List<Something> method(List<Something> list){
String sql = "SELECT * FROM users WHERE "+ this.processPlaceHolders(list);
}
public String processPlaceHolders(List<Something> list) {
StringBuilder finalStr=new StringBuilder("");
for(int i=0;i<list.size(); i++){
if(i==list.size()-1){
finalStr.append(list.get(i)+"=" +"?");
}
else {
finalStr.append(list.get(i)+"=" +"?,");
}
}
return finalStr.toString();
}
答案 3 :(得分:0)
您需要动态构建SQL查询才能实现此目的。
public static getUsers(int id, string username, string email) {
Connection conn = null;
PreparedStatement stmt = null;
String sql = "";
sql = "SELECT * FROM users where id=? ";
if (username != null)
sql += " AND username=? ";
if (email !=null)
sql += " AND email=?";
stmt = conn.prepareStatement(sql);
stmt.setInt(1,id);
if (username != null && email !=null)
{
stmt.setString(2,username);
stmt.setString(3,email);
}
else if (username != null)
stmt.setString(2,username);
else if (email != null)
stmt.setString(2,email);
答案 4 :(得分:0)
您的问题的解决方案是这样的:
public void getRecord(String id, String username, String email)
{
String sql = " select * from users ";
boolean isID , isUserName, isEmail;
boolean isFirst = true;
if (id!=null)
{
if ( isFirst)
{
sql = sql + " where";
isFirst = false;
}
sql = sql + " id = ?";
isID = true;
}
if (username != null)
{
if ( isFirst)
{
sql = sql + " where";
sql = sql + " username = ?";
isFirst = false;
}
else
sql = sql + " and username = ?";
isUserName = true;
}
if (email != null)
{
if ( isFirst)
{
sql = sql + " where";
sql = sql + " email = ?";
isFirst = false;
}
else
sql = sql + " and email = ?";
isEmail = true;
}
PreparedStatement pst = con.prepareStatement(sql);
int counter = 1;
if (isID)
pst.setString(counter++,id);
if (isUserName)
pst.setString(counter++,username);
if (isEmail)
pst.setString(counter++,email);
//Then execute the query
ResultSet rs = pst.executeQuery();
.......
}
答案 5 :(得分:0)
试试这个:
public static getUsers(int id, String username, String email) {
Connection conn = null;
PreparedStatement stmt = null;
String sql = "SELECT * FROM users WHERE id=? ";
if (username != null && username.trim().length() != 0) sql = sql + " AND username=? ";
if (email != null && email.trim().length() != 0) sql = sql + " AND username=? ";
stmt = conn.prepareStatement(sql);
stmt.setInt(1, id);
if (username != null && username.trim().length() != 0) stmt.setString(2, username);
if (email != null && email.trim().length() != 0) stmt.setString(3, email);
//.....
}
答案 6 :(得分:0)
您应该考虑为每个有效的输入组合编写一个单独的方法,而不是编写一个非常复杂的方法来动态构造PreparedStatement。然后每个人都可以轻松验证其输入,并始终使用特定的PreparedStatement。这不仅会在将来更容易理解和维护,而且更容易测试。
如果您需要与现有API向后兼容,则可以编写一个getUsers(int id, string username, string email)
方法,根据需要委派给更简单的方法。
答案 7 :(得分:0)
来自@ghdalum的好主意实际上并不涉及PreparedStatement。以下是我对他的建造者想法的改编,以制作PreparedStatement:
public class UserQueryBuilder {
private Connection conn;
private StringBuilder query = new StringBuilder("SELECT * FROM users");
private List<ValueSetter> valueSetters = new ArrayList<ValueSetter>();
// callback interface for setting the column values
private interface ValueSetter {
void setValue(PreparedStatement ps);
}
// the caller is responsible for closing the connection afterwards
public QueryBuilder(Connection conn) {
this.conn = conn;
}
public QueryBuilder byId(final Integer id) {
appendSeparator();
query.append("id = ?");
valueSetters.add(new ValueSetter() {
public void setValue(PreparedStatement ps) {
ps.setInt(id);
}
});
return this;
}
public QueryBuilder byEmail(String email) {
appendSeparator();
query.append("email = ?");
valueSetters.add(new ValueSetter() {
public void setValue(PreparedStatement ps) {
ps.setString(email);
}
});
return this;
}
public QueryBuilder byUsername(String username) {
appendSeparator();
query.append("username= ?");
valueSetters.add(new ValueSetter() {
public void setValue(PreparedStatement ps) {
ps.setString(username);
}
});
return this;
}
private void appendSeparator() {
if (filterValues.size() == 0) {
query.append(" WHERE ")
}
else {
query.append(" AND ")
}
}
public PreparedStatment build() {
PreparedStatement ps = conn.prepareStatement(query.toString());
for(ValueSetter valueSetter : valueSetters) {
valueSetter.setValue(ps);
}
return ps;
}
}
用法:
PreparedStatement userQuery = new UserQueryBuilder(conn)
.byId("2")
.byEmail("test")
.build();
userQuery.execute();
(顺便说一句,我没有测试这段代码所以可能会出现拼写错误)