JDBC template giving error for Query using "like" - java

I am not getting how to use %?% in the query below. It's giving me error:
PreparedStatementCallback; uncategorized SQLException for SQL [select
* from names where name like '%?%']
Problem:
String sql = "select * from names where name like ?";
List<NamesModel> names = jdbcTemplate.query(sql, new Object[]{searchName}, new NamesRowMapper());

Your exception tells you that you can't bind into quoted value. Below won't work:
String sql = "select * from names where name like '%?%'";
List<NamesModel> names = jdbcTemplate.query(sql,
new Object[]{ searchName }, new NamesRowMapper());
The correct way is to add % around searchName parameter value:
String sql = "select * from names where name like ?";
List<NamesModel> names = jdbcTemplate.query(sql,
new Object[]{ "%" + searchName + "%"}, new NamesRowMapper());

Related

use jpa nativequery multiple columns in object list array

Use jpa nativequery multiple columns in object list array
List<Object []> queryList = new ArrayList<>();
String[] arr = {"val1", "val2"};
queryList.add(arr);
String sql = SELECT * FROM TABLE A WHERE (A.COL1, A.COL2) IN (:queryList)
Query query = entityManager.createNativeQuery(sql);
query.setParameter("queryList", queryList);
In postgresql like this
SELECT * FROM TABLE A WHERE (A.COL1, A.COL2) IN (('val1', 'val2'), ('val3', 'val4'));
Here is the Exception
Caused by: org.postgresql.util.PSQLException: ERROR: operator does not exist: record = bytea
建議:No operator matches the given name and argument types. You might need to add explicit type
Is this possible?
I would try to restructure the query as follows:
SELECT * FROM TABLE A
WHERE (A.COL1 = 'val1' and A.COL2 = 'val2')
OR (A.COL1 = 'val3' and A.COL2 = 'val4')
This would allow the query to be constructed as follows:
List<String[]> queryList = new ArrayList<>();
String[] arr = {"val1", "val2"};
String[] arr = {"val3", "val4"};
queryList.add(arr);
String sql = "SELECT * FROM TABLE A "; //dont forget space at end
if (!queryList.isEmpty()){
sql = sql + "WHERE "; //dont forget space at end
for (String[] queryParam : queryList ){
sql = sql + " (A.COL1 = '"+ queryParam[0] + "' and A.COL2 = '" + queryParam[1] + "') OR "; //dont forget space at end and simple colons for param
}
//finally remove the last OR.
Integer indexLastOR = sql.lastIndexOf("OR");
sql = sql.substring(0, indexLastOR);
}
Query query = entityManager.createNativeQuery(sql);
This will also allow the query to be implemented without being native, which is advisable to maintain the JPA philosophy.

Set list parameter to native query

I would like to set parameter to a native query,
javax.persistence.EntityManager.createNativeQuery
Something like that
Query query = em.createNativeQuery("SELECT * FROM TABLE_A a WHERE a.name IN ?");
List<String> paramList = new ArrayList<String>();
paramList.add("firstValue");
paramList.add("secondValue");
query.setParameter(1, paramList);
Trying this query result in Exception:
Caused by: org.eclipse.persistence.exceptions.DatabaseException:
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server
version for the right syntax to use near
'_binary'??\0♣sr\0‼java.util.ArrayListx??↔??a?♥\0☺I\0♦sizexp\0\0\0☻w♦\0\0\0t\0
f' at line 1
Error Code: 1064
Call: SELECT * FROM Client a WHERE a.name IN ?
bind => [[firstValue, secondValue]]
Query: ReadAllQuery(referenceClass=TABLE_A sql="SELECT * FROM TABLE_A a WHERE a.name IN ?")
Is it any way to set list parameter for native query, without cast to string and append it to sql query?
P.S. I'm use EclipseLink 2.5.0 and MySQL server 5.6.13
Thanks
I believe you can only set list parameters to JPQL queries, not native queries.
Either use JPQL, or construct the SQL dynamically with the list.
It works if you name the parameter:
Query query = em.createNativeQuery("SELECT * FROM TABLE_A a WHERE a.name IN (:names)");
List<String> paramList = new ArrayList<String>();
paramList.add("firstValue");
paramList.add("secondValue");
query.setParameter("names", paramList);
Not a solution but more of a workaround.
Query query = em.createNativeQuery("SELECT * FROM TABLE_A a WHERE a.name IN ?");
List<String> paramList = new ArrayList<String>();
String queryParams = null;
paramList.add("firstValue");
paramList.add("secondValue");
query.setParameter(1, paramList);
Iterator<String> iter = paramList.iterator();
int i =0;
while(iter.hasNext(){
if(i != paramList.size()){
queryParams = queryParams+ iter.next() + ",";
}else{
queryParams = queryParams+ iter.next();
}
i++;
}
query.setParameter(1, queryParams );
You can add multiple values like this example:
TypedQuery<Employee> query = entityManager.createQuery(
"SELECT e FROM Employee e WHERE e.empNumber IN (?1)" , Employee.class);
List<String> empNumbers = Arrays.asList("A123", "A124");
List<Employee> employees = query.setParameter(1, empNumbers).getResultList();
Source: PRAGT E., 2020. JPA Query Parameters Usage. Retrieved from: https://www.baeldung.com/jpa-query-parameters

Passing a mysql query to the database using a java program

I am new to mysql and I am trying to connect to the database using a Java Program and I am passing a mysql query.
public class dbconnect {
public static void main(String[] args) throws SQLException,ClassNotFoundException {
Class.forName("com.mysql.jdbc.Driver");
Connection conn =DriverManager.getConnection("jdbc:mysql://localhost:3306/mydatabase?user=root&password=root");
Statement st = conn.createStatement();
int custid= 0;
String myname = null;
String query = "select name from groups where customer_id = 2;";
//This query has a problem can anyone help me fix it.
System.out.println(query);
ResultSet rs1 = st.executeQuery(query);
System.out.println("after query");
while (rs1.next()){
custid = rs1.getInt("customer_id");
myname = rs1.getString("name");
System.out.println(myname);
System.out.println(custid);
}
}
}
I am passing a query "select name from groups where customer_id = 2" .
Here "name" is a coloumn,"groups" is a table and "customer_id" is another column. In the program when I give this query(no typos) I get the following error
Exception in thread "main" java.sql.SQLException: Column 'customer_id' not found.
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1073)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:987)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:982)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:927)
at com.mysql.jdbc.ResultSetImpl.findColumn(ResultSetImpl.java:1144)
at com.mysql.jdbc.ResultSetImpl.getInt(ResultSetImpl.java:2815)
at com.memoir.client.widgets.memogen.dbconnect.main(dbconnect.java:61)
I have checked with the table , customer_id is present in the table . They are no spelling mistakes also .Even then it says that customer_id column is not found .
Can anyone help me fix it.
The query needs to be:
String query = "select name, customer_id from groups where customer_id = 2;";
Honestly it doesn't make any sense, your query is
String query = "select name from groups where customer_id = 2;";
and you expect to get customer_id ??
as you are already passing customer_id in where clause you don't need to get it back again from db.
String query = "select customer_id,name from groups where customer_id = 2;";
The above would work with your current code .
You are accessing only name column in query and you are try to get "customer_id" in while loop from result set
while (rs1.next()){
custid = rs1.getInt("customer_id"); // **error is here - remove this line or change your query**
myname = rs1.getString("name");
System.out.println(myname);
System.out.println(custid);
}
Your problem is that you are trying to get an invalid column ("cutomer_id") from the result set which contains only the "name" column.
To resolve this you have to select also the "customer_id" in your query:
"select name, customer_id from groups where customer_id = 2";
custid = rs1.getInt("customer_id");
you result set does not have customer_id
Include that too in your query
try this
String mysqlquery = "select name, customer_id from groups where customer_id=2";

JdbcTemplate does not support Parameterized Query 'IN' case? Must by NamedParameterJdbcTemplate?

Aimed at preventing SQL injection attacks, all the SQL Statement code in my project should transformed to Parameterized Query. But I got a problem when the query condition includes a 'IN' case. Like this (Using DB2 database):
String employeeId = 'D2309';
String name = "%brady%";
List<Integer> userRights = new ArrayList<Integer>();
userRights.add(1);
userRights.add(2);
userRights.add(3);
String sql = "SELECT * FROM T_EMPLOYEE WHERE EMPLOYEE_ID = ? AND NAME LIKE ?
AND RIGHT IN (?)";
jdbcTemplate.query(sql, new Object[] {employeeId, name, userRights}, new
EmployeeRowMapper());
The above code runs failed with the exception:
org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad
SQL grammar [SELECT * FROM T_EMPLOYEE WHERE EMPLOYEE_ID = ? AND NAME LIKE ? AND
RIGHT IN (?)]; nested exception is com.ibm.db2.jcc.am.io: [jcc][1091][10824]
[3.57.82] .... ERRORCODE=-4461, SQLSTATE=42815
The question here is that does not JdbcTemplate support Parameterized Query for IN case? and I know this work can be done by NamedParameterJdbcTemplate, and whether only NamedParameterJdbcTemplate can do IN case query?
Thanks a lot.
As I already mentioned in the comments, I'm not happy with this solution as it dynamically generates a number of SQL statements. Given the number of userRights is between 1 and n, it requires up to n prepared statements in the cache.
The below should work (I did not try it).
String employeeId = 'D2309';
String name = "%brady%";
List<Integer> userRights = new ArrayList<Integer>();
userRights.add(1);
userRights.add(2);
userRights.add(3);
// build the input string
StringBuilder sb = new StringBuilder();
for (int i = 0; i < userRights.size; i++) {
sb.append("?");
if (i < userRights.size() - 1) {
sb.append(", ");
}
}
// build the SQL
String sql = "SELECT * FROM T_EMPLOYEE WHERE EMPLOYEE_ID = ?" +
" AND NAME LIKE ?" +
" AND RIGHT IN (" + sb.toString() + ")";
// init the object array
// size is employeeId + name + right
Object[] param = new Object[2 + userRights.size()];
// fill it
param[0] = employeeId;
param[1] = name;
for (int i = 0; i < userRights.size(); i++) {
param[i + 2] = userRights.get(i);
}
jdbcTemplate.query(sql, param, new EmployeeRowMapper());

How to handle 'IN' case in SQL Statement with the way of Parameterized Query?

To avoid SQL injection attacks in my project, I'm attempting access database with Parameterized Query way. Right now I know how to handle equal case like below (With Spring JdbcTemplate):
String sql = "SELECT * FROM T_USER WHERE USERNAME = ? AND PASSWORD = ?"
jdbcTemplate.query(sql,
new UserRowMapper(),
new Object[]{"%admin%", "%password%"});
Above code runs no problem, but I had no idea how to handle the 'IN' case, following is my case, and it works failed:
String sql =
"SELECT * FROM T_USER WHERE USERNAME = ? AND PASSWORD = ? AND CLASS_ID IN (?)"
jdbcTemplate.query(sql,
new UserRowMapper(),
new Object[]{"%admin%", "%password%", "1,2,3"});
Anybody give me guidance? Thanks a lot.
I think you can create a List and pass it as 3rd parameter. Also You need to use LIKE in place of = in first two column filters.
List<Integer> classIds = new ArrayList<Integer>();
classIds.add(1);
classIds.add(2);
classIds.add(3);
String sql = "SELECT * FROM T_USER WHERE "+
"USERNAME LIKE ? AND PASSWORD LIKE ? AND CLASS_ID IN (?)";
jdbcTemplate.query(sql, new Object[]{"%admin%", "%password%", classIds},
new UserRowMapper());
Please note: Here is the syntax:
public List query(String sql, Object[] args, RowMapper rowMapper)
throws DataAccessException
EDIT: Please try namedParameterJdbcTemplate as bwlow:
String sql = "SELECT * FROM T_USER WHERE "+
"USERNAME LIKE :uname AND PASSWORD LIKE :passwd AND CLASS_ID IN (:ids)";
Map<String, Object> namedParameters = new HashMap<String, Object>();
namedParameters.put("uname", "%admin%);
namedParameters.put("passwd", "%password%");
namedParameters.put("ids", classIds);
List result = namedParameterJdbcTemplate.query(sql, namedParameters,
new UserRowMapper());
Three options:
Generate different JDBC queries for each length of the IN LIST, and parameterize each INDIVIDUAL item, e.g. this answer
For small tables, you can cheat and use a LIKE statement, e.g. this answer
Use a SPLIT function (anti-LISTAGG) to turn the delimited list into individual rows of one column each, and JOIN against it. Example SPLIT function
You'll parameterize the argument to the function as a single string

Categories

Resources