Spring Data JPA native query parameters are omitted - debugging

How do I check that parameters are correctly passed into an Hibernate native query ?
This is my Spring Data repository:
public interface TasksRepository extends JpaRepository<Task, Long> {
#Query(value = "SELECT * FROM tasks_table WHERE jsonb_path_exists(task_tags, "
+ "'$[*] ? (#.entityCode == $code && #.entityId == $id)', "
+ "'{\"code\":\"?1\", \"id\":\"?2\"}')",
nativeQuery = true)
List<Task> findTasksByEntityCodeAndEntityId(String entityCode, UUID entityId);
}
And these are my logs:
Hibernate:
SELECT
*
FROM
tasks_table
WHERE
jsonb_path_exists(task_tags, '$[*] ? (#.entityCode == $code && #.entityId == $id)', '{"code":"?1", "id":"?2"}')
But I can see no means to check that the variables are replaced before the query is passed to PostgreSQL 13; which seems odd, but consistent with classical derived queries I also logged, ending up with traces like "where task0_.task_name=?" where the parameters values aren't shown either.
Does anyone know why my positional parameters are not interpreted with this native query, since I understood that they should be?
Thanks for any tip!

Related

How to add optional parameter in JPQL?

How to use/add optional parameter in JPQL?
#Query(value = "SELECT stud FROM Student stud where stud.name = :studentName AND stud.age IN :studentAgeList")
List<Student> getStudents(
#Param("studentName ") String studentName,
#Param("studentAgeList") List<Integer> studentAgeList
)
How to make studentAgeList parameter in above query ?
I tried below :
#Query(value = "SELECT stud FROM Student stud where stud.name = :studentName AND (:studentAgeList IS NULL OR stud.age IN :studentAgeList))
List<Student> getStudents(
#Param("studentName ") String studentName,
#Param("studentAgeList") List<Integer> studentAgeList
)
But getting error : unexpected AST node:
Tried above but getting error
JPQL does not support optional parameters, you can use overload methods with different queries or criteria API or JPA specifications.
may be get answer here: Set optional parameters in JPQL Query

Spring Data JPA: Parameterize #Query Annotation String, Refactor Two Similar #Query Methods

In Spring Data I have 2 very large queries which are essentially identical, but with small differences. I don't want to duplicate the methods for both queries. Suppose I have
Method 1
#Query(value = ".. " +
" .. " +
//... big query
"...")
public List<Bean> getResult(#Param("studyId") long studyId);
Method 2
#Query(value = ".. " +
" .. " +
//... big query, after WHERE:
" and (:startDate is null or :startDate = '' or r.recall_date >= to_date(cast(:startDate as TEXT) " +
"...")
public List<Bean> getResult(#Param("studyId") long studyId, #Param("startDate" String startDate);
My goal is:
1) Parameterize the #Query string so that it can either take or omit the optional additional WHERE as a sub-string.
2) Somehow refactor the methods so they don't call separate SQL. The only difference is the additional parameter in Method 2.
Is this possible?
Something like this should work
interface ReportTypeRepository extends PagingAndSortingRepository<ReportType,String> {
final String report = " select r from ReportType r ";
final String where = " where r.active=:active ";
final String sort = " order by r.id asc ";
#Query(report + sort) // <-- all with sort
List<ReportType> findByQuery();
#Query(report + where + sort) // <-- all with where and sort
List<ReportType> findByActiveQuery(#Param("active") boolean active);
}
Another (probably better) solution is to use Spring Data JPA with Querydsl or the JPA 2 Criteria API where you can define some Predicates and combine then to use multiple constraints.
You could also take a look on Specification if you plan to do dynamic queries.

Modify SQL based on DAO method param in Spring Data #Query

I have a Spring Data query method where the SQL/HQL can vary depending on a method param passed to the method, in this case the boolean methodParam. Is there a way to achieve the below?
#Query("select ... " +
".... " +
"...." +
(methodParam ? "variant1" : "variant2") +
"....")
public List<MyObject> findObjects(boolean methodParam);
It's better to create the query to use OR and two different conditions e.g.
select
...
where
...
AND (
(methodParam = 1 AND <variant1 conditions>)
OR
(methodParam = 0 AND <variant2 conditions>)
)
...
OR in case of boolean you can just declare two methods.

generic hql select function given field and param

is this valid HQL?
If not (i assume not since im getting wrong result back). How/can i achieve this generic slect transaction?
String hql = "SELECT * from users Where :searchCriteria = :searchString";
List q = session.createSQLQuery(hql).addEntity(Users.class)
.setParameter("searchField", searchCriteria)
.setParameter("searchString", searchString).list();
Try this hql,
Criteria cr= session.createCriteria(Users.class);
cr.add(Restrictions.eq("searchField", searchCriteria);
cr.add(Restrictions.eq("searchString", searchString);
List<Users> user_data=(List<Users>)cr.list();

Spring jdbcTemplate dynamic where clause

Is it possible to generate arbitrary where condtions SQL query through Jdbc template:
example:
If i pass value for 1 parameter (only name) : search by name
"select * from address where shopname = ?";
If i pass value for 2 parameter (name and city) - search by shopname and city:
"select * from address where shopname = ? and city = ?";
I have mupliple search fields. 7 fields. If user enters any combination. i have search only based on parameter. How to dynamically pass the parameters to the sql. Need snippet/Example how to achieve this.
What you want is some sort of criteria building api, which Hibernate has. Unfortunately, I don't think Spring's JdbcTemplate has any such facility. Others will correct me if I'm wrong...
Though as some guys already suggested that Hibernate is the best way of doing this, but still i think you can try this approach-
String sql = "select * from address where 1 = 1";
if(shopname != null)
sql += "and shopname = :shopname";
if(city!= null)
sql += "and city = :city";
and so on..and use NamedParameterJdbcTemplate
Spring Data and Hibernate have that kind of functionality. Though it might not be worth dragging in such big framework for your app.
You can try to check out SimpleJdbcInsert
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/jdbc.html
Edit:
Alternatively you can try to fix it in SQL with checking on empty, but if you have lots of data to go through, this technique will slow down your request.
"select * from address
where (shopname = ? or shopname = null)
and (city = ? or city = null)";
If Scala is an option to you, the query could be constructed with something like this:
case class Search(shopname:String, city:String = None) {
def sql = "select * from address where shopname = '"+shopname+"'" + city.map(" and city = '"+
_ +"'").getOrElse("")
}
Example usage:
Search("lloh").sql
Search("lloh", Some("Austin")).sql

Resources