Java string format specifier collides with SOQL wildcard - java

I am trying to do a SalesForce query from Java, and I want to insert the current date and time into the query. However, I also want to add a wildcard for title, and the percent for the wildcard is being interpreted as a format specifier and giving an error.
String soqlQuery = new String.format("SELECT Id, Title, CreatedDate "
+ "FROM FeedItem "
+ "WHERE title like '%ven%' and createdDate %s ", timeOfLastQuery);
I was able to just use string concatenation to get around the problem, but I would like to know if there is a way to do create a query string that contains a wildcard specifically using formatted strings.

You can escape them with another % like
String soqlQuery = new String.format("SELECT Id, Title, CreatedDate "
+ "FROM FeedItem "
+ "WHERE title like '%%ven%%' and createdDate %s ", timeOfLastQuery);

Related

spring jdbc prepared statement with boolean fulltext search formatting issues

I have an sql query that uses boolean fulltext search:
SELECT
*,
MATCH (job_title) AGAINST ('"product manager"' in boolean mode) AS title_relevance_exact,
MATCH (job_description) AGAINST ('"product manager"' in boolean mode) AS description_relevance_exact,
MATCH (job_title) AGAINST ('product manager' in boolean mode) AS title_relevance_part,
MATCH (job_description) AGAINST ('product manager' in boolean mode) AS description_relevance_part
FROM
jobs
WHERE
MATCH(job_title, job_description) AGAINST ('product manager') AND
date_posted >= now() - INTERVAL 30 DAY
ORDER BY
job_title LIKE 'product manager' DESC,
title_relevance_exact DESC,
description_relevance_exact DESC,
title_relevance_part DESC,
description_relevance_part DESC
LIMIT 300;
i.e. the quotation and speech marks in '"product manager"' is important to the query.
When I run this query as a spring jdbc prepared statement, I have to do some work arounds to get the string formatted correctly since if I have '?', jdbc doesnt recognise this as a parameter:
String queryPrepared =
"SELECT\n" +
" *,\n" +
" MATCH (job_title) AGAINST (? in boolean mode) AS title_relevance_exact,\n" +
" MATCH (job_description) AGAINST (? in boolean mode) AS description_relevance_exact,\n" +
" MATCH (job_title) AGAINST (? in boolean mode) AS title_relevance_part,\n" +
" MATCH (job_description) AGAINST (? in boolean mode) AS description_relevance_part\n" +
"FROM\n" +
" jobs\n" +
"WHERE\n" +
" MATCH(job_title, job_description) AGAINST (?) AND\n" +
" date_posted >= now() - INTERVAL 30 DAY\n" +
"ORDER BY\n" +
" job_title LIKE ? DESC,\n" +
" title_relevance_exact DESC,\n" +
" description_relevance_exact DESC,\n" +
" title_relevance_part DESC,\n" +
" description_relevance_part DESC\n" +
"LIMIT 500;";
String param1 = String.format("'\"%1$s\"'", searchValue);
String param2 = String.format("'%1$s'", searchValue);
List<Map<String, Object>> resultPrepared = jdbcTemplate.queryForList(queryPrepared,
new Object[] {param1, param1, param2, param2, param2, param2});
But the correct result isnt produced from the query, the results are not in the expected order. I can only assume that this happens because of the formatting in the prepared statement parameters. But I can't see what the query looks like after adding the parameters, how can I debug this?
You need to remove the single quotes from your value. Single quotes in SQL delimit a string literal in the query string. When you set a parameter value, you only need to set the string value without the single quotes.
So, if you want to replace the literal '"product manager"' with a parameter, then you use ? in your query (so, without single quotes), and set the value "product manager" (again, without single quotes), which as a Java string literal is "\"product manager\"".
Using single quotes in the value passed as a parameter would be the equivalent of using the SQL String literal '''"product manager"'''.

NamedParameterJdbcTemplate not updating when using batchUpdate

I have a list of objects provided by another service which I use to update my own data. When I try to use NamedParameterJdbcTemplate.batchUpdate, all returned values are zero.
public void updateWeather(List<Weather> weatherList) {
String query = "UPDATE weather \n" +
"SET rain_probability = ROUND(:rainProbability, 4), \n" +
"wind_speed = :windSpeed \n" +
"WHERE city_id = :cityId AND date = :date;";
List<MapSqlParameterSource> batchList = new ArrayList<>();
for(Weather weather : weatherList) {
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("rainProbability", weather.getRainProbability());
params.addValue("windSpeed", weather.getWindSpeed());
params.addValue("cityId", weather.getCityId());
params.addValue("date", weather.getDate());
batchList.add(params);
}
this.namedParameterJdbcParameter
.batchUpdate(query, batchList.toArray(new MapSqlParameterSource[] {});
}
If I run this UPDATE directly in the database, it works fine. Futhermore, if I run it one by one, that is, replacing values (instead of adding the parameter source to batchList) it also works.
For example:
for (Weather weather : weatherList) {
String query = String.format("UPDATE weather \n" +
"SET rain_probability = ROUND('%d', 4), \n" +
" wind_speed = %d \n" +
" WHERE city_id = :cityId AND date = :date;",
weather.getRainProbability(),
weather.getWindSpeed(),
weather.getCityId(),
weather.getDate()
);
this.namedParameterJdbcTemplate.update(query, Collections.emptyMap());
}
Any suggestions of what I'm doing wrong?
Is it the use of "\n" or the ";" at the end of the statement within the String? (I'm surprised you don't get a SQL Syntax exception with the ; inside the actual query string)
Also dates are always a bit tricky and if that isn't converting properly then your WHERE clause isn't going to match and is possibly why 0 rows are returned. Could you temporarily try converting dates to Strings and see if the count is correct (e.g. for Oracle: AND date = TO_DATE(:dateStr, 'DD/MM/YYYY') )

Named parameter doesn't work with MySql LIKE statement

I'm trying to organize a search function on the site, using the Spring-jdbc NamedParameterJdbcTemplate.
public List<PhoneEntry> searchPhoneEntries(String search, String username) {
String SQL = "select * from entries, users where users.enabled=true " +
"and entries.username=:username " +
"and concat(secondName, firstName, patronymic, mobile, tel, " +
"address, entries.email) like ('%:search%')";
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("username", username);
params.addValue("search", search);
return jdbcTemplate.query(SQL, params, new PhoneEntryMapper());
}
But I get an empty list and have no any error.
When using a simple concatenation:
"...like '%" + search + "%'";
it working properly, but as I understand it is not safe.
I tried also add '%' symbols in parameter:
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("username", username);
params.addValue("search", "'%" + search + "%'");
return jdbcTemplate.query(SQL, params, new PhoneEntryMapper());
But it doesn't work too.
The solution is to add the parameter without quotes
params.addValue("search", "%" + search + "%");
and in the SQL string write
String sql = "... like :search";
Your first approach ('%:search%') did not work since named parameters are not recognized within string literals.
The second approach params.addValue("search", "'%" + search + "%'"); did not work since now the quotes were part of the like string, therefore asking Mysql to look for strings which start and end with a quote and contain the search term.

Obtaining selectedItem in JComboBox and inserting as one value in query Newbie

I can't find a way of putting all the selected items on 3 different combobox which I need to insert as query to Java DB(derby). Here's my code.
int response = JOptionPane.showConfirmDialog
(null, "Do you want to add the employee?","Confirm",JOptionPane.YES_NO_OPTION,JOptionPane.QUESTION_MESSAGE);
if(response == JOptionPane.YES_OPTION){
try{
String url="jdbc:derby://localhost:1527/EMPLOYEEINFO [ADMIN1 on ADMIN1]";
String username="ADMIN1";
String password="ADMIN1";
Connection con = DriverManager.getConnection(url, username, password);
Statement stat = con.createStatement();
String Query =
"INSERT INTO EMPLOYEE (EMPLOYEE_ID,EMP_LASTNAME,EMP_FIRSTNAME,EMP_MIDDLENAME,ADDRESS,POSITION ) "
+"VALUES "
+ "(' "+AddEmployee_EmployeeID_TxtField.getText()+" ',"
+ " ' "+AddEmployee_LastName_TxtField.getText()+" ',"
+ " ' "+AddEmployee_FirstName_TxtField.getText()+" ',"
+ " ' "+AddEmployee_MiddleName_TxtField.getText()+" ',"
+ " ' "+AddEmployee_Address_TxtField.getText()+" '"
+ " ' "+AddEmployee_Position_TxtField.getText()+" ',"
+ " ' "+AddEmployee_Gender_ComboBox.getSelectedItem()+"')"
;
stat.execute(Query);
JOptionPane.showMessageDialog(null,"Insert Success!");
And below is the screenshot. I'm thinking of getselectedObject but i have 3 combo boxes so I really don't know how. Please help.
I need to get the selected items of Month, Day and Year of the Birthday then insert it to my table in Derby. Thanks in advance.
You should create a separate method to get the fields and combine the values into a formatted date. Something like this:
private String getDateFromFields() {
String month = monthComboBox.getSelectedItem();
String day = dayComboBox.getSelectedItem();
String year = yearComboBox.getSelectedItem();
// Format this the way your database expects.
String formattedDate = month + "/" + day + "/" + year;
}
You just call this method and you will get back the formatted date string that you can use in your query. Change the variable names of the combo box fields to match your names and format the string into what your database expects and you should be good to go!
You can do something like this:
String bDay=dayCombo.getSelectedItem()+"-"+monthCombo.getSelectedItem()+"-"+yearCombo.getSelectedItem();
But I will recommend you to use JDatechooser in this case.
JDateChooser bDayChooser =new JDateChooser();
bDayChooser.setDateFormatString("dd-MM-yyyy");//format visible date of the date chooser as you need
String bDay=((JTextField) bDayChooser.getDateEditor().getUiComponent()).
getText();

How can i search for the year in a date via a query?

The records in the db look like this:
10//12/2013
10/13/2013
10/16/2013
10/20/2013
I want to search 2013 in the above records. Do i have to split first above values?
from CustomerRelations where DATE like'" + input + "'
Can I use like here?
Or how else can I do this?
Query q = session.createQuery("from CustomerPayment where DATE like '" + code + "'");
The Above code does not work.
Since you've saved the dates as VARCHAR do a wildcard String match
Query q = session.createQuery("from CustomerPayment where DATE like '%" + code + "'");
LIKE clause lets you use two wilcards:
_ = matches just one single character
% = matches any number of characters
Ideally, you should have created your table with a TIMESTAMP column. That would allow you to compare dates accurately and build queries like "fetch all customer payments in the last three months" etc.
you can use
datepart(year,datefield)
where datefield is your field from which you want to retrieve the year
Query q = session.createQuery("SELECT date FROM CustomerPayment WHERE datepart(year,"+Convert.ToDateTime(datefield)+")="+ input+";
Try changing your query to
Query q = session.createQuery("SELECT date FROM CustomerPayment WHERE date LIKE '%"+input+"'"
since your date field is a string, you must do the lookup via a string compare

Categories