jdbcTemplate query prepared statement with multiple parameters - java

I am building my sql string like this:
String sql = "SELECT * FROM horse WHERE 1=1 ";
if (horse.getName() != null) {
sql += "AND UPPER(name) LIKE ? ";
}
if (horse.getDescription() != null) {
sql += "AND UPPER(description) LIKE ? ";
}
if (horse.getRating() != null) {
sql += "AND rating=? ";
}
I want to find a match for entity depending on which parameters are passed. So if only name and rating are passed I would get something like: SELECT * FROM horse WHERE 1=1 AND UPPER(name) LIKE ? AND rating=?
Now I pass the sql string to query like this:
List<Horse> matchingHorses = jdbcTemplate.query(sql, new Object[]{horse.getName()}, mapHorse());
This returns a correct result but I have to pass to new Object[] {} only the parameters that I know that user is gonna pass or else I do not get anything. For example if user passes something like this:
{
"description":"desc"
}
I won't get any results even if there is a description with "desc". If I do this:
List<Horse> matchingHorses = jdbcTemplate.query(sql, new Object[]{horse.getName(), horse.getDescription(), horse.getRating()}, mapHorse());
and pass only name I get:
org.springframework.dao.DataIntegrityViolationException: PreparedStatementCallback; SQL [SELECT * FROM horse WHERE 1=1 AND UPPER(name) LIKE ? ];
Invalid value "2" for parameter "parameterIndex" [90008-200]; nested exception is org.h2.jdbc.JdbcSQLDataException: Invalid value "2" for parameter "parameterIndex" [90008-200]
Here is my mapHorse() row mapper:
private RowMapper<Horse> mapHorse() {
return (resultSet, i) -> {
Long horseId = resultSet.getLong("id");
String horseName = resultSet.getString("name");
String horseDesc = resultSet.getString("description");
int horseRating = resultSet.getInt("rating");
return new Horse(
horseId,
horseName,
horseDesc,
horseRating,
);
};
}
How do I implement this correctly?

You can use NamedParameterJdbcTemplate.
MapSqlParameterSource params = new MapSqlParameterSource();
if (horse.getName() != null) {
sql += "AND UPPER(name) LIKE :name ";
params.addValue("name", horse.getName());
}
if (horse.getDescription() != null) {
sql += "AND UPPER(description) LIKE :description ";
params.addValue("description", horse.getDescription());
}
if (horse.getRating() != null) {
sql += "AND rating=:rating ";
params.addValue("rating ", horse.getRating());
}
namedParameterJdbcTemplate.query(sql, params, mapHorse());
suggestion- better if you you use string builder.

Related

How to execute Pre-build Query in Java Spring

I need to execute pre-build SQL query in java spring, I created query as follows,
String query = "select * from device where";
if (status != null) {
query += " status = "+status;
}
if (cinema != "") {
query += " and cinema_code = \'"+cinema+"\'";
}
if (content_profile != "") {
query += " and content_profile = \'"+content_profile+"\'";
}
if (mac != "") {
query += " and mac = \'"+mac+"\'";
}
Build query:
select *
from device
where status = 2
and cinema_code = 'AL10'
and content_profile = 'signage'
You can use Spring Data JPA Specifications for dynamic queries.
Give a look here:
https://www.baeldung.com/rest-api-search-language-spring-data-specifications
If you don't want JPA you can use Spring JDBC
Execute query:
String query = "select * from device where status = 2 and cinema_code = 'AL10' and content_profile = 'signage'";
List<Device> devices = jdbcTemplate.queryForObject(
query, new Object[] { }, new DeviceRowMapper());
Mapper can look like this:
public class DeviceRowMapper implements RowMapper<Device> {
#Override
public Employee mapRow(ResultSet rs, int rowNum) throws SQLException {
Device device = new Device();
device.setId(rs.getInt("ID"));
...
return device;
}
}
How to config the connection in providing url
However as it was mentioned in comments. It is better not to concatenate string parameters.
Your query building can be done in that way.
String query = "select * from device where";
List parameters = new ArrayList();
boolean wasParameter = false;
if(status != null) {
query += " status = ? ";
parameters.add(status);
wasParameter = true;
}
if(cinema != "") {
query += (wasParameter ? " and ": "") +" cinema_code = ? ";
parameters.add(cinema);
wasParameter = true;
}
if(content_profile != "") {
query += (wasParameter ? " and ": "") +" content_profile = ? ";
parameters.add(content_profile);
wasParameter = true;
}
if(mac != "") {
query += (wasParameter ? " and ": "") +" mac = ? ";
parameters.add(mac);
}
Object[] array = parameters.toArray(new Object[0]);
And execute query:
List<Device> devices = jdbcTemplate.queryForObject(
query, array, new DeviceRowMapper());
Assuming that you have configured the Spring datasource you can execute a Spring native query using:
EntityManager em = emf.createEntityManager();
List<Object> results = em.createNativeQuery(query);
You should also update your query, because you can easily get a SQLException when status is null. If it happens you will have an invalid query:
select *
from device
where and cinema_code = 'AL10' and content_profile = 'signage'
Try to use this initial query:
"select * from device where 1=1 "
Using the above, the query will be correct no matter if the first if is executed or no ifs executed at all.

VertX SQL queryWithParams Howto use LIKE ? with wildards

I'm working on a simple VertX Application. I have a hsqlDB and I'm trying to execute a query where I want to get all IDs from the Table where the Name contains a search parameter
String sql = "SELECT ID FROM MYTABLE WHERE NAME LIKE ?";
So this works when the Name is the same as the ?
When I try to use wildcards:
String sql = "SELECT ID FROM MYTABLE WHERE NAME LIKE %?%";
or
String sql = "SELECT ID FROM MYTABLE WHERE NAME LIKE '%?%'";
it doesn't work.
My Code:
private void getIDsBySearchString(String search, SQLConnection conn, Handler<AsyncResult<Vector<Integer>>> resultHandler) {
String sql = "SELECT ID FROM MYTABLE WHERE NAME LIKE ?";
conn.queryWithParams(sql, new JsonArray().add(search), asyncResult -> {
if(asyncResult.failed()) {
resultHandler.handle(Future.failedFuture("No Names Found"));
} else {
int numRows = asyncResult.result().getNumRows();
if(numRows >= 1) {
Vector<Integer> IDVector = new Vector<>();
for(int i = 0; i < numRows; i++) {
int id = asyncResult.result().getRows().get(i).getInteger("ID");
IDVector.add(id);
}
resultHandler.handle(Future.succeededFuture(IDVector));
} else {
resultHandler.handle(Future.failedFuture("No Names found"));
}
}
});
}
How do I need to edit my query String so the ? will be replaced by the search String and I will be able to use wildcards?
A parameter cannot be inside a quoted string. It can be part of a concat expression involving other strings.
String sql = "SELECT ID FROM MYTABLE WHERE NAME LIKE '%' || ? || '%'";
The part that should be changed is your search parameter, not the sql part:
String sql = "SELECT ID FROM MYTABLE WHERE NAME LIKE ?";
conn.queryWithParams(sql, new JsonArray().add("%"+search+"%"), asyncResult -> { ... }

JDBC dynamic query, only put value to string if not -1

I have a problem with JDBC and java.
I have a Query like this:
String updateSql = "UPDATE league SET season=?, playedMatches=?, percentHomeWins=?, percentDraws=?, percentAwayWins=?, averageGoalsPerGame=?, averageGoalsHomePerGame=?, averageGoalsAwayPerGame=?, percentOverOne=?, percentOverTwo=?, percentOverThree=?, percentBothTeamsScored=?, scoredGoalsTotal=? " + whereClause + " and country='" + l.getCountry() + "'";
all values after "season" can either be a number >= 0 or -1. -1 means, that there is no value. the values come from a class that holds data (like an object model).
I want only the values in my query, which are >= 0. The other one should not be in the query, because they replace data in the database, which they should not.
Can anyone help me archiving this?
Use a StringBuilder to dynamically build the SQL statement, e.g.
StringBuilder sql = new StringBuilder("UPDATE league SET season=?");
List<Integer> numValues = new ArrayList<>();
if (l.getPlayedMatches() != -1) {
sql.append(", playedMatches=?");
numValues.add(l.getPlayedMatches());
}
if (l.getPercentHomeWins() != -1) {
sql.append(", percentHomeWins=?");
numValues.add(l.getPercentHomeWins());
}
// ... more code ...
sql.append(whereClause)
.append(" and country=?");
try (PreparedStatement stmt = conn.prepareStatement(sql.toString())) {
int paramIdx = 0;
stmt.setInt(++paramIdx, l.getSeason());
for (Integer numValue : numValues)
stmt.setInt(++paramIdx, numValue);
stmt.setString(++paramIdx, l.getCountry());
stmt.executeUpdate();
}

MYSQL+Hibernate, Query cannot be created

Can someone help me to have a look at what is wrong with my query?
Java code :
public boolean fValidLogin(String fUsername, String fPassword) {
SessionFactory sf = new Configuration().configure().buildSessionFactory();
Session session = sf.openSession();
String query = "SELECT fusername,fpassword FROM flogin WHERE fusername=" + fUsername + " AND fpassword=" + fPassword + "";
Query DBquery = session.createQuery(query);
for (Iterator it = DBquery.iterate(); it.hasNext();) {
it.next();
count++;
}
System.out.println("Total rows: " + count);
if (count == 1) {
return true;
} else {
return false;
}
}
MYSQL Code:
SELECT fusername,fpassword FROM flogin WHERE fusername="SAS" AND fpassword="Sas123"
Try this first:
"SELECT fusername,fpassword FROM flogin WHERE fusername=\"" + fUsername + "\" AND fpassword=\"" +fPassword +"\""
By the way you are tring to use a native query. Maybe you should consider to use "createNativeQuery" instead of "createQuery"
Your query is a victim of an SQL Injection, it can also cause syntax error, instead you have to use setParameter with a JPQL query :
String query = "SELECT f FROM flogin f WHERE f.fusername = ? AND f.fpassword = ?";
Query dBquery = session.createQuery(query);
dBquery.setParameter(0, fUsername);//set username variable
dBquery.setParameter(1, fPassword);//set password variable
To get the nbr of result you can just call Query::list()
int count = dBquery.list().size();
Or just :
return dBquery.list().size() == 1;
The real problem in your query is that the String should be between two quotes (but i don't advice with solution)
fusername='" + fUsername + "'
//--------^_________________^
Note: Your query is not a JPQL Query, it seems a native query, if that you have to use session.createNativeQuery(query);.

How to select names in oracle10g database?

i want to search the name who having skills in java and oracle
and i know the coding like
select name from table_name where skills like '%java%' or skills like '%oracle%';
but my problem is,In servlet How can i do this?
String skills=request.getParameter("skill");
my select query
select name from table_name where skill like '"++"';
Here i am confused ,
i tried like this
select name from table_name where skill like '"+%skills%+"';
but not working.
I am a webdeveloper very new to oracle ,please help me
I am using oracle10g
You may try REGEXP_LIKE
SELECT name from TABLENAME where
WHERE REGEXP_LIKE (skills, '(Java|Oracle)');
String query = "select name from table_name";
String skills = request.getParameter("skill");
StringBuilder likePart = new StringBuilder("");
boolean appendOrClause = false;
String skillsArray[] = skills == null ? null : skills.split(",");
if(skillsArray != null && skillsArray.length > 0 ){
for(String skill : skillsArray){
if(skill.trim().length() > 0){
if(appendOrClause){
likePart.append(" OR skills like '%" + skill.trim() + "%'");
} else {
likePart.append(" where skills like '%" + skill.trim() + "%'");
}
appendOrClause = true;
}
}
if(likePart.toString().trim().length() > 0){
query += likePart.toString();
}
}
if(query.indexOf("like") > 0 ){
// User have skills
// Fire query to get User Name
} else {
// User doesn't have any skills
// don't Fire any query
}

Categories

Resources