Spring Like clause - java

I am trying to use a MapSqlParameterSource to create a query using a Like clause.
The code is something like this. The function containing it receives nameParam:
String namecount = "SELECT count(*) FROM People WHERE LOWER(NAME) LIKE :pname ";
String finalName= "'%" +nameParam.toLowerCase().trim() + "%'";
MapSqlParameterSource namedParams= new MapSqlParameterSource();
namedParams.addValue("pname", finalName);
int count= this.namedParamJdbcTemplate.queryForInt(namecount, namedParams);
This does not work correctly, giving me somewhere between 0-10 results when I should be receiving thousands. I essentially want the final query to look like:
SELECT count(*) FROM People WHERE LOWER(NAME) LIKE '%name%'
but this is evidently not happening. Any help would be appreciated.
Edit:
I have also tried putting the '%'s in the SQL, like
String finalName= nameParam.toLowerCase().trim();
String namecount = "SELECT count(*) FROM People WHERE LOWER(NAME) LIKE '%:pname%' "
;
but this does not work either.

You don't want the quotes around your finalName string. with the named parameters you don't need to specify them. This should work:
String namecount = "SELECT count(*) FROM People WHERE LOWER(NAME) LIKE :pname ";
String finalName= "%" + nameParam.toLowerCase().trim() + "%";
MapSqlParameterSource namedParams= new MapSqlParameterSource();
namedParams.addValue("pname", finalName);
int count= this.namedParamJdbcTemplate.queryForInt(namecount, namedParams);

This solution worked for me. I put the "%" on the Object[] parameters list:
String sqlCommand = "SELECT customer_id, customer_identifier_short, CONCAT(RTRIM(customer_identifier_a),' ', RTRIM(customer_identifier_b)) customerFullName "
+ " FROM Customer "
+ " WHERE customer_identifier_short LIKE ? OR customer_identifier_a LIKE ? "
+ " LIMIT 10";
List<Customer> customers = getJdbcTemplate().query(sqlCommand, new Object[] { query + "%", query + "%"}, new RowMapper<Customer>() {
public Customer mapRow(ResultSet rs, int i) throws SQLException {
Customer customer = new Customer();
customer.setCustomerFullName(rs.getString("customerFullName"));
customer.setCustomerIdentifier(rs.getString("customer_identifier_short"));
customer.setCustomerID(rs.getInt("customer_id"));
return customer;
}
});
return customers;

Have you tried placing the % wild cards in your sql string (not the bind variable value itself):
String finalName= nameParam.toLowerCase().trim();
String namecount = "SELECT count(*) FROM People WHERE LOWER(NAME) LIKE '%:finalName%'";

We can use simple JdbcTemplate instead of NamedParamJdbcTemplate
String namecount = "SELECT count(*) FROM People WHERE LOWER(NAME) LIKE ? ";
String finalName= "%" +nameParam.toLowerCase().trim() + "%"; //Notes: no quote
getJdbcTemplate().queryForInt(namecount, new Object[] {finalName});
Hope it helpful for someone using JdbcTemplate

Related

Recommended method to Keyword Search in whole MySQL DB via JavaWeb

I am trying to achieve a keyword search from my whole MySQL DB via JSP, I am confused if the method I chose is inefficient :(
I've read about the information_schema and found all column labels are there.
I've tried the SQL statement below to generate all the possible queries:
SELECT CONCAT('SELECT * FROM ',table_schema,'.',table_name,
' WHERE ',column_name,' LIKE ','searchString',';')
FROM information_schema.columns
WHERE table_schema NOT IN ('information_schema','mysql','performance_schema')
AND (column_type LIKE 'char(%'
OR column_type LIKE 'varchar(%'
OR column_type LIKE '%text')
and tried JSP code to get all the data match possible.
<%
String searchString = "malayalam";
searchString = "''%"+searchString+"%'' ";
ArrayList<String> queries = new ArrayList<String>();
String sql="SELECT CONCAT('SELECT * FROM ',table_schema,'.',table_name,"
+ "' WHERE ',column_name,' LIKE ','"+searchString+"',';')"
+ "FROM information_schema.columns "
+ "WHERE table_schema NOT IN ('information_schema','mysql','performance_schema')"
+ "AND (column_type LIKE 'char(%'"
+ "OR column_type LIKE 'varchar(%'"
+ "OR column_type LIKE '%text')";
try{
DBConInfoSchema db = new DBConInfoSchema();
ResultSet rs = db.getData(sql);
while(rs.next()){
queries.add(rs.getString(1));
}
for(int i=0;i<queries.size();i++){
DBConInfoSchema dCon = new DBConInfoSchema();
ResultSet rsDemo = dCon.getData(queries.get(i));
if(rsDemo.next()){
out.print("<br/>Data found n query-"+i+" -> "+queries.get(i));
}
dCon.DBClose();
}
}catch(Exception w){
out.print("excep<br/>"+w);
}
%>
Now I got huge list of Queries.
I am confused if its Good or Bad?!
Is this bad method when considering efficiency?
In the query building section
SELECT CONCAT('SELECT * FROM ',table_schema,'.',table_name,
' WHERE ',column_name,' LIKE ','searchString',';')
FROM information_schema.columns
WHERE table_schema NOT IN ('information_schema','mysql','performance_schema')
AND (column_type LIKE 'char(%'
OR column_type LIKE 'varchar(%'
OR column_type LIKE '%text')
I have updated line
WHERE table_schema NOT IN ('information_schema','mysql','performance_schema')
to
WHERE table_schema IN ('<my_table_name>')
to generate all the search results in my_table_name and saved to ArrayList and executed them
ArrayList<String> queries = new ArrayList<String>();
DBConInfoSchema db = new DBConInfoSchema();
ResultSet rs = db.getData(sql_statement);
while(rs.next()){
queries.add(rs.getString(1));
}
from there I sorted out the required data.
-Hope this may help some one.
NB: Even though it worked for me I still believe its Naive
Correct me If there's a better way yo achieve this

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);.

LIKE COALESCE in Spring JPA does not work

So my problem is the following:
I have a table I want a filter to apply to. This filter should call a query which finds based on the given information the reports.
This is how my query looks:
#Query("SELECT r FROM Report r WHERE r.importanceLevel = COALESCE(importance,'%')" +
"AND r.source = COALESCE(source,'%')" +
"AND r.resolvedStatus = COALESCE(resolvedStatus,'%')" +
"AND r.header LIKE + '%' COALESCE(query,'%') + '%'")
List<Report> getReportsByAppliedFilter(#Param("importance") int importance, #Param("source") String source,
#Param("resolvedStatus") int resolvedStatus, #Param("query") String query);
Problem is: IntelliJ does not like the following:
LIKE + '%' COALESCE(query,'%') + '%'
Error: expected, got +
Do you have any idea how to solve this otherwise?
Yeah, time to go to bed. You dont use + for concat , you use concat():
#Query(value = "SELECT r FROM Report r WHERE r.importanceLevel = COALESCE(importance,'%')" +
"AND r.source = COALESCE(source,'%')" +
"AND r.resolvedStatus = COALESCE(resolvedStatus,'%')" +
"AND r.header LIKE CONCAT('%', COALESCE(query,'%'), '%')")
If your column name is request_status and table name is connections then use COALESCE like
#Query(value = "SELECT connections.id, COALESCE(connections.request_status,'') as request_status.... ", nativeQuery = true)
List<ZXYType> xysfunction();
Here if request_status is null then it will be replaced by an empty string.

How to add limit to Hibernate query annotation?

I have this in Java Hibernate
#Query("SELECT dirPar FROM DirectiveParagraph dirPar, Directive dir "
+ "WHERE dirPar.directive = dir "
+ "AND dir.txtDirCode = :txtDirCode ");
List<DirectiveParagraph> getByName(#Param("txtDirCode") String name, #Param("page") int page ,#Param("size") int size);
I want to retrieve with limit and size, same way like this
SELECT * FROM tblDirectiveParagraph where intDirectiveID = 1 limit 10,10;
How do I add limit to above #Query annotation
You can try adding a Pageable parameter to your getByName method
#Query("SELECT dirPar FROM DirectiveParagraph dirPar, Directive dir "
+ "WHERE dirPar.directive = dir "
+ "AND dir.txtDirCode = :txtDirCode ");
Page<DirectiveParagraph> getByName(#Param("txtDirCode") String name, Pageable page);
And here's a sample method call:
public void someMethod(){
PageRequest pageR = new PageRequest(10,10);
Page<DirectiveParagraph> result = directiveParagraphRepository.getByName("txtDirCode",pageR);
List<DirectiveParagraph> resultList = result.getContent();
}
Limit is not supported in HQL. To set the size, you would use setMaxResults. To set start point, you use setFirstResult.
Query q = session.createQuery("...");
q.setFirstResult(10);
q.setMaxResults(10);
If you don't want to do it that way, you would have to use createSQLQuery to write a native sql query instead of hql.

Update with Join hibernate (HQL)

I'm on trouble with an hql problem.
I would like to write a query, that updates an attribut, and that's based on a value on another table.
This is my example, I have those two tables : Client and Widhdrawal.
Client : idClient, name ...
Widhdrawal : idWidh, cost, and the idClient (foreign key)
Now if i would update the client, under the condition of (idClient = 5 for example), i can't.
I tried this, but in vain :
String hql = "UPDATE Widhdrawal W set W.cost = :salary " +
"where W.Client.id_client = :employee_id)";
Query query = session.createQuery(hql);
query.setParameter("salary", 1000);
query.setParameter("employee_id", 5);
int result = query.executeUpdate();
I hope that someone can have some advices, thank you.
Try this:
String hql = "UPDATE Widhdrawal W set W.cost = :salary " +
"where W.idClient = :employee_id)";
Thank you, i found the solution.
I hope that this can help other people ...
This problem is du to lowerCase.
String hql = "UPDATE Widhdrawal W set W.cost= :newCost " +
"where W.client.id_client = :id_cl";
Query query = session.createQuery(hql);
Try this way --
String hql = "UPDATE Widhdrawal W set W.cost = :salary " +
"where W.id_client =(select id_client from client where id_client = :employee_id)";
Widhdrawal and client is POJO class name.

Categories

Resources