How do i form a query for jdbcTemplate - java

am trying to form a query based on parameters, if the parameters for WHERE clause is null or not. it seems to be a huge code if i do this on if and else. Is there any other smart way to this??
example :
String query = "SELECT CUSTOMER_NAME FROM CUSTOMER_TABLE WHERE ";
if(cust_id !=null && !(cust_id.trim().equalsIgnoreCase("")))
{
query = query + "cust_id='"+cust_id+"'";
}
else
{
}
checking all the columns like this, the code is looking like a mess, please let me know if there is an other way to do this
adding to the above question :
I also have the parameters for like operator
example
if(strCustName!=null)
{
String query = "SELECT * FROM CUSTOMER WHERE CUSTOMER_NAME LIKE '"+strCustName+"';
}

You can use NamedParameterJDBCTemplate
And your query could be
... WHERE (cust_id=:custIdParam OR :custIdParam is null)
AND (another_column=:another_param OR :another_param is null)
UPDATE:
String sqlstr = "select * from the_table where lastname like :lastname or :lastname is null"
NamedParameterJdbcTemplate jt = new NamedParameterJdbcTemplate(datasource);
Map namedParameters = new HashMap();
namedParameters.put("lastname", "%test%");
SqlRowSet result = jt.queryForRowSet( sqlstr ,namedParameters );
from the link

Related

NamedParameterJdbcTemplate substituing values with single quotes

#Autowired
NamedParameterJdbcTemplate namedParameterJdbcTemplate;
public List<Contact> findByPhoneWithNamedParameters(String phone) {
MapSqlParameterSource namedParameters = new
MapSqlParameterSource().addValue("phone", phone);
String sqlQ = getSqlQuery(namedParameters);
namedParameters.addValue("anotherCondition", sqlQ);
String sql = "select * from Contact c where c.phone=:phone
:anotherCondition";
return namedParameterJdbcTemplate.query(sql, namedParameters, new ContactRowMapper());
}
private String getSqlQuery(MapSqlParameterSource namedParameters) {
return " and c.name='Saman'";
}
The above one is generating the query like below:
select * from Contact c where c.phone='09137390432' ' and c.name=''Saman'''
getSqlQuery() return value is embeddigng within single quotes, with that query is not working as expected.
I tried to concatenate the value directyle instead of namedParams;
But in my case, I have to avoid the SQL Injection.
How to resolve this?
You should only use named parameters with the actual values you want to pass to the query, not with whole SQL sub-parts. Otherwise it will escape also the valid SQL quotes.
So you should change your code to something like this:
private String getAdditionalSqlConditions(MapSqlParameterSource namedParameters) {
namedParameters.add("name", "Saman");
return "c.name = :name";
}
public List<Contact> findByPhoneWithNamedParameters(String phone) {
MapSqlParameterSource namedParameters = new MapSqlParameterSource().addValue("phone", phone);
String conditions = getAdditionalSqlConditions(namedParameters);
String sql = "select * from Contact c where c.phone=:phone and " + conditions);
return namedParameterJdbcTemplate.query(sql, namedParameters, new ContactRowMapper());
}

Solve JPQL Query

I am trying to get details of Properties details from database using JPQL, Hear I am writing where condition like (properties.IsDeleted <> 'Y' or properties.IsDeleted IS NULL)
but, in JPQL query it is not getting 'Y', but, it is was showing like '?' symbol. this is the problem I am getting. please help me from this issue.
the below code is showing query like:-
select properties0_.property_id as col_0_0_,
properties0_.property_type as col_1_0_, properties0_.property_name as
col_2_0_, properties0_.property_area as col_3_0_,
properties0_.property_city as col_4_0_, properties0_.no_of_rooms as
col_5_0_ from iot_property properties0_ where
(properties0_.is_deleted<>? or properties0_.is_deleted is null) and
properties0_.property_id=6
In the above query in bold mark shows properties0_.is_deleted<>? ,but what I want is properties0_.is_deleted<>Y
why that "Y" is not assigned to that query. that I am not understanding.
will you please help me to solve this issue.
Thanks
CriteriaBuilder deviceBuilder = propertySession.getCriteriaBuilder();
CriteriaQuery<Object[]> userCriteriaQuery = deviceBuilder.createQuery(Object[].class);
Root<Properties> propertyRoot = userCriteriaQuery.from(Properties.class);
Path<Object> pathPropertyId = propertyRoot.get("propertyId");
Path<Object> pathpropertyType = propertyRoot.get("propertyType");
Path<Object> pathpropertyName = propertyRoot.get("propertyName");
Path<Object> pathpropertyArea = propertyRoot.get("propertyArea");
Path<Object> pathpropertyCity = propertyRoot.get("propertyCity");
Path<Object> pathnumberOfRooms = propertyRoot.get("numberOfRooms");
userCriteriaQuery.multiselect(pathPropertyId, pathpropertyType, pathpropertyName, pathpropertyArea,
pathpropertyCity, pathnumberOfRooms);
Predicate userRestriction = deviceBuilder.or(deviceBuilder.notEqual(propertyRoot.get("isDelete"), "Y"),
deviceBuilder.isNull(propertyRoot.get("isDelete")));
Predicate userRestriction2 = deviceBuilder
.and(deviceBuilder.equal(propertyRoot.get("propertyId"), propertyId));
userCriteriaQuery.where(deviceBuilder.and(userRestriction, userRestriction2));
Query<Object[]> deviceQuery = propertySession.createQuery(userCriteriaQuery);
List<Object[]> resultList =deviceQuery.getResultList();
for(Object[] objects : resultList) {
Integer dbPropertyId = (Integer) objects[0];
String dbPropertyType = (String) objects[1];
String dbpropertyName = (String) objects[2];
String dbpropertyArea = (String) objects[3];
String dbpropertyCity = (String) objects[4];
Integer dbNoOfRooms = (Integer) objects[5];
System.out.println(dbPropertyId);
System.out.println(dbPropertyType);
System.out.println(dbpropertyName);
System.out.println(dbpropertyArea);
System.out.println(dbpropertyCity);
System.out.println(dbNoOfRooms);
}
There is no such thing as "the final JPQL that ultimately gets translated to the final SQL with inserted paramerters". How a JPA implementation generates the SQL is down to it, and parameters, in general, will never be substituted into any String. SQL has generated from expression trees etc, not a String. This is a criteria query so for parameters it will show "?" on the console.
If you want param values inserting in then do it yourself since it only makes sense to you

Custom Query Join in JPA using Criteria Builder API

Currently I am doing it like this:
List<Table1Entity> findAllMatchingEntities(Table1Entity table1Entity) {
String queryString = "SELECT table1.* FROM table1 "
+ "JOIN table2 t2 ON table1.id=t2.table1_id";
if (table1Entity.getName() != null) {
queryString +=" where name like ?";
}
Query query = em.createNativeQuery(queryString, Table1Entity.class);
if (table1Entity.getName() != null) {
query.setParameter(1, table1Entity.getName())
}
return query.getResultedList();
}
If I want to check more parameters in this join this will quickly turn into a lot of if statements and it would be really complicated to set parameters correctly.
I know I can check parameters with criteria Builder API like this:
if(table1Entity.getName() != null) {
table1EntitySpecification = (root, query, criteriaBuilder)
-> criteriaBuilder.like(
criteriaBuilder.lower(root
.get("name")),
("%" + table1Entity.getName() + "%")
.toLowerCase());;
}
and after that get them all with:
findAll(table1EntitySpecification) with findAll from simpleJPARepository. Now I can chain them together with .or or .and etc. and avoid setting the parameter and checking for null second time.
But how do I do join with criteria APi?
I know I can have in my #Repository something like this:
#Query(value = "SELECT table1.* FROM table1 JOIN table2 t2 ON table1.id=t2.table1_id", nativeQuery = true)
List<Table1Entity> findAllMatchingEntities(Table1Entity table1Entity);
But since name is optional (can be null) I can't just leave it in #Query.
What is the best solution here to avoid using native query and in case of having to check many parameters to avoid using if statements?
I don't know if I fully get your question, but regarding the possibility of nulls, and using the CRUD repository, you can always do a null check before like:
#Query(value = "SELECT table1.* FROM table1 JOIN table2 t2 ON table1.id=t2.table1_id WHERE table1.id is not null", nativeQuery = true)
List<Table1Entity> findAllMatchingEntities(Table1Entity table1Entity);
Depending on what you are trying to achieve, you can always compose the query with similar checks like (not related to your code):
#Query("SELECT c FROM Certificate c WHERE (:id is null or upper(c.id) = :id) "
+ "and (:name is null or upper(c.name) = :name)")
List<Table1> findStuff(#Param("id") String id,
#Param("name") String name);

Java native SQL query to display all values when an input param is null

I have the following DAO method:
public String getSomeTable(final String param1) {
String sqlString = "select * from table where name ilike ?";
Query query = this.getEntityManager().createNativeQuery(sqlString);
query.setParameter(1, "%param1%");
}
If param1 is null or empty then I want to select all entries from the table. What is the correct way to do this? I am currently using the following:
public String getSomeTable(final String param1) {
String sqlString = "select * from table where name = ?";
Query query = this.getEntityManager().createNativeQuery(sqlString);
if(param1 == null)
query.setParameter(1, "%%");
else
query.setParameter(1, "%param1%");
}
But this is not scalable. I have datatypes like integer, date, etc. I want to know if there is a way to skip checking for that parameter if it is null.
I was planning to use COALESCE(?, CASE WHEN ? = '' THEN '%%' ELSE '%?%') but I think ? can be used only once for a particular parameter. The next one > I write is linked to second param.
On SQL Server, I use something like this, perhaps you can translate it to postgres:
DECLARE #variable INT = NULL;
SELECT *
FROM sysobjects
WHERE
(1 = CASE WHEN #variable IS NULL THEN 1 ELSE 2 END)
OR
(id LIKE #variable);

Query result with columns names

I'm using java, spring data jpa
Is there away to get as query result a map with column name and value?
something like: List<Map<String,object>> res = query.getResults();
EDIT:
I found this.
it uses JDBC statement.
String queryString = "Select auditTime From AuditPlayer ap Where ap.id = 1"
dbConnection = getDBConnection();
statement = dbConnection.createStatement();
// execute the SQL stetement
rs = statement.executeQuery(queryString);
rs.getString("auditTime")
this works, but is there a way to use * in the select:
Select * From AuditPlayer ap Where ap.id = 1
and now call a column name? `rs.getString("auditTime")
I keep getting error.
You can return a map of column-name: column-value pairs using JdbcTemplate. Example:
public List<Map<String, Object>> getCustomers() {
return this.jdbcTemplate.queryForList("SELECT customer_id, customer_name FROM customers");
}
This would return:
[{'customer_id': 4005, 'customer_name': 'John Smith'}, {...}, ... ]

Categories