Reputation: 33
I want to do a Search function with multiple Java Swing components, where a user can search by (name/nationality/specialty/experience) and results will be displayed in a Jtable.
I'm only struggling with the SQL Query, as if a user typed a 'name' only, no data will be retrieved because it goes to database like this (name, null, null, null) and I don't have any null values in my database.
So I want to retrieve all data with that name regardless of other columns, but at the same time, if they also chose a specific specialty for example, I want to retrieve all data with the selected name AND specialty, and so on.
I hope you understand my question.
My current SQL statement:
public ArrayList<Applications> getData(String name, String nationality, String specialty, String experience) {
ArrayList<Applications> list = new ArrayList<Applications>();
Connection con = getConnection();
Statement st;
ResultSet rows;
try {
st = con.createStatement();
rows = st.executeQuery("SELECT * FROM applications WHERE name LIKE '%" + name+"%'"
+ " AND (nationality LIKE '" + nationality+"')"
+ " AND (specialty LIKE '" + specialty+"')"
+ " AND (experience LIKE '" + experience+"')");
Applications applications;
while(rows.next()) {
applications = new Applications(
rows.getInt("id"),
rows.getString("name"),
rows.getString("nationality"),
rows.getString("Specialty"),
rows.getString("experience")
);
list.add(applications);
}
} catch (SQLException ex) {
Logger.getLogger(MyQuery.class.getName()).log(Level.SEVERE, null, ex);
}
return list;
}
Upvotes: 3
Views: 4434
Reputation: 76434
Let's see your query:
rows = st.executeQuery("SELECT * FROM applications WHERE name LIKE '%" + name+"%'"
+ " AND (nationality LIKE '" + nationality+"')"
+ " AND (specialty LIKE '" + specialty+"')"
+ " AND (experience LIKE '" + experience+"')");
Here, since only name
was given, the other values are null
. If you write this code for testing purpose:
String foo = null;
System.out.println(foo + "");
the output will be
"null"
so, since your values are null
, the generated query will be
SELECT * FROM applications WHERE name LIKE '%Rowan Atkinson%'
AND (nationality LIKE 'null')
AND (specialty LIKE 'null')
AND (experience LIKE 'null')
First of all, let's make sure that you get empty String
in case of null
:
rows = st.executeQuery("SELECT * FROM applications WHERE name LIKE '%" + ((name == null) ? "" : name)+"%'"
+ " AND (nationality LIKE '" + ((nationality == null) ? "" : nationality)+"')"
+ " AND (specialty LIKE '" + ((specialty == null) ? "" : specialty)+"')"
+ " AND (experience LIKE '" + ((experience == null) ? "" : experience)+"')");
The next problem is that you are only putting %
at the name
, which is also incorrect, so let's fix that:
rows = st.executeQuery("SELECT * FROM applications WHERE name LIKE '%" + ((name == null) ? "" : name)+"%'"
+ " AND (nationality LIKE '%" + ((nationality == null) ? "" : nationality)+"%')"
+ " AND (specialty LIKE '%" + ((specialty == null) ? "" : specialty)+"%')"
+ " AND (experience LIKE '%" + ((experience == null) ? "" : experience)+"%')");
and now read YCF_L's answer so you will use Named Parameters for PreparedStatement.
Upvotes: 2
Reputation: 59960
In this case You have two Solution :
I will gives you an example about the second one, you can use NamedParameterStatement
it is like PrepapredStatement
to avoid Syntax error and SQL Injection :
String query = "SELECT * FROM applications"
+ " WHERE (:name is null or name LIKE CONCAT('%', :name, '%')) "
+ " AND (:nationality is null or nationality LIKE :nationality)"
+ " AND (:specialty is null or specialty LIKE :specialty)"
+ " AND (:experience is null or experience LIKE :experience)";
NamedParameterStatement namedParametterStatement =
new NamedParameterStatement(connection, query);
namedParametterStatement.setString("name", name);
namedParametterStatement.setString("nationality", nationality);
namedParametterStatement.setString("specialty", specialty);
namedParametterStatement.setString("experience", experience);
Note the trick for example here :
(:nationality is null or nationality LIKE :nationality)
It will check if the nationality
is null or the nationality like the value you pass, like this you avoid the null.
Some good references :
Upvotes: 1
Reputation: 610
Below code may give you expected Result.
StringBuilder sql=new StringBuilder("SELECT * FROM applications WHERE 1=1 ");
if(!name.isEmpty()){
sql.append(" AND name LIKE '%" + name+"%'");
}
if(!nationality.isEmpty()){
sql.append(" AND (nationality LIKE '" + nationality+"')");
}
if(!specialty.isEmpty()){
sql.append(" AND (specialty LIKE '" + specialty+"')");
}
if(!experience.isEmpty()){
sql.append(" AND (experience LIKE '" + experience+"')");
}
rows = st.executeQuery(sql.toString());
Try this
Upvotes: 1