How to perform left join in hql to fetch data - hql

I am using following query to get data data database
String hql = "from Parameters s "
+"left join fetch s.userValues as uv "
+ "where s.groupId=:gid "
+"and uv.user.id=:uid " ;
Above is my hql query here I am fetching data from Parameter and from userValues.
This query is working properly if user have any value in userValues.
This query is not fetching any value when there is no saved value for user in userValues.
My problem is Whether there should be data in userValues or not I want to fetch data from Parameters.
How to achieve this using hql?
I just want to do left join in hql to get first table values.

You probably want something like this. You need to left join the association to user also. Note that you should use the Hibernate mapping between Parameter and Group as below. But you will probably need to use grouping to remove duplicate results.
String hql = "from Parameters s "
+ "join s.group g "
+ "left join fetch s.userValues uv "
+ "left join uv.user u "
+ "where g.id=:gid "
+ "and (u.id=:uid or u is null) ";

Related

Is there a way to make these kind of query with multiple queries?

#Query("select user.id, language, profile " +
"from User user " +
"join user.language language " +
"left join user.profiles profile " +
"where user.id in :usersIds")
List<Object[]> findDataByUsersIds(#Param("usersIds") Collection<Integer> usersIds);
I would like a better way to write this query, by dividing it into multiple queries.

Spring JPA - Issue while sorting on non entity column

I have requirement where I need to get the records based in join of three table with pagination(addition requirement are also there). So I have written a nativeQuery to get the records. Below is the sample query
#Query(value = "SELECT "
+ "a.GROUP_REF_ID as refId "
+ "count(case when c.STAT_CD in :userStatus then (c.grp_user_id) end) as numberOfUsers, "
+ "count(case when b.STAT_CD in :itemStatus then (b.grp_item_id) end) as numberOfItems "
+ "from grp a left join grp_item b on a.grp_id=b.grp_id left join grp_user c on a.grp_id=c.grp_id "
+ "where a.stat_cd in :status and a.co_id in :cids "
+ "group by a.GROUP_REF_ID,a.grp_nam,a.GRP_DESC,a.co_id,a.co_nam,a.CRTE_BY, "
+ "a.CRTE_DT,a.UPDT_BY,a.UPDT_DT ", countQuery = "select count(*) from grp where stat_cd in :status and co_id in :cids ", nativeQuery = true)
public Page<Object> findByStatusAndCompanyIdIn(#Param("status") String status, #Param("cids") List<Long> companyIds,
#Param("userStatus") List<GroupUserStatus> userStatus,
#Param("itemStatus") List<GroupItemStatus> itemStatus, Pageable pageable);
Now the requirement is also that these records are to be sorted on any of the column in select part. So, if user passes numberOfItems, the records are to be sorted on it. But I am facing an issue here because if I pass Sort parameter as numberOfItems, spring prepends an a. before numberOfItems which results in error that not able to find a.numberOfItems.
Is there a way I can stop spring from prepending table alias while creating a query with Sort, or should I write my logic in a different approach
Making my comment an answer so the question can be marked as answered:
Wrap the whole select in another one: select * from (<your current select>) x
I have solved the issue by creating a projection. (Kotlin was used but you’ll get the gist.)
class ShowRepository : JpaRepository<Int, Show> {
#Query("SELECT s AS show, (CASE WHEN (s.status = 'scheduled') THEN s.scheduledStartTime ELSE s.startTime END) AS time FROM Show s")
fun findShows(pageable: Pageable): Page<ShowWithTime>
}
interface ShowWithTime {
val show: Show,
val time: Date?
}
This allows Spring-Data to work its full magic, and using Sort.by(Order.desc("time")) works like a charm.
I’ve written it up with a little bit more detail here: Sorting by a Non-Entity Field.

Spring Data JPA Repository returns Object[] instead of MyType while using Sum Function

Until today I was using this statement:
#Query(value = "select top 5 p.*, sum(po.quantity) as total_quantity from product p " +
"inner join productorder po " +
"on p.id = po.product_id " +
"group by p.id, p.name " +
"order by total_quantity desc", nativeQuery = true)
List<Product> findTopFiveBestSellerNative();
Here as i define the return type as a list of Products, i exactly get what i need. And the selected column total_quantity is simply ignored.
Lastly i needed to integrate pagination into this query. Since Spring does not support pagination handling with native queries, i wanted to first transform this query to JPQL (then i will add pagination). And now it looks like this:
#Query(value = "select p, sum(po.quantity) as total_quantity " +
"from Product p, ProductOrder po " +
"where p.id = po.pk.product " +
"group by p.id, p.name " +
"order by total_quantity desc")
List<Product> findTopFiveBestSeller();
The return type is now a list of object arrays, where the first element of array is Product, and second one is the total_quantity. (Although the method signature says List..)
How can i change my statement or somehow achieve this, so that i do not have to deal with array, and simply just get my Product objects?
EDIT: I had the idea to use this query as a subquery, and just select the products from the subquery. It turns out that the JPQL cannot do subqueries in the 'from' clause..
Fact is your query is not returning only the columns needed to build a Product object, so Spring JPA is mapping it to an object.
Create an aggregate entity that extends product and that contains the property totalQuantity and map your query to it (possibly in another repository)

Bind parameters for ORDER BY in NamedParameterJDBCTemplate

I am trying to use NamedParameterJdbTemplate in a Spring MVC application. The issue is that the bind parameters do not seem to work (no sorting happens) when I include one of ORDER BY clauses listed below. However, a hard coded order by column name in the sql works.
ORDER BY column1
ORDER BY column1
ORDER BY column1 asc
ORDER BY column1 desc
For example, the below listed query does not work.
private static final String SEARCH_ALL_BY_SORT_ORDER=
" select FIRST_NM, MIDDLE_NM, LAST_NM, CUSTOMER_IDENTIFIER, EMAIL_ADDRESS, ACCOUNT_ID" +
" from VIEW " +
" where CUSTOMER_IDENTIFIER= :customerIdentifier " +
" and ( REGEXP_LIKE(FIRST_NM, :firstName, 'i') " +
" or REGEXP_LIKE(LAST_NM, :lastName, 'i') " +
" or REGEXP_LIKE(EMAIL_ADDRESS, :emailAddress, 'i') )" +
" order by :sortColumns";
The same query with a hard coded order by column works:
private static final String SEARCH_ALL_BY_SORT_ORDER=
" select FIRST_NM, MIDDLE_NM, LAST_NM, CUSTOMER_IDENTIFIER, EMAIL_ADDRESS, ACCOUNT_ID" +
" from VIEW " +
" where CUSTOMER_IDENTIFIER= :customerIdentifier " +
" and ( REGEXP_LIKE(FIRST_NM, :firstName, 'i') " +
" or REGEXP_LIKE(LAST_NM, :lastName, 'i') " +
" or REGEXP_LIKE(EMAIL_ADDRESS, :emailAddress, 'i') )" +
" order by LAST_NM";
Here's the relevant jdbctemplate code
Map <String, Object> params = new HashMap <String, Object>();
params.put("customerIdentifier", customerIdentifier);
params.put("firstName", searchCriteria );
params.put("lastName", searchCriteria );
params.put("emailAddress",searchCriteria);
// sortBy is COLUMN name
// sortOrder is either 'asc' or 'desc'
params.put("sortColumns", sortBy + " " + sortOrder);
// Using just the column name does not work either
//params.put("sortColumns", sortBy);
namedParameterJdbcTemplate.query(SEARCH_ALL_BY_SORT_ORDER, params, new MemberMapper());
Only values can be bound as parameters. Not parts of the query itself.
In the end, a prepared statement is generated and the parameters are bound to the prepared statement. The principle of a prepared statement is to prepare the execution plan of the query (of which the order by clause is a part), and to execute the query one or several times after, with varying parameters.
If the query is not complete, the execution plan can't be prepared and reused. So, for this part of the query, you'll need to generate the query dynamically using string concatenation, and not parameters.
As JB Nizet has already explained that parts of query cannot be used as bind keys (orderby :age). Therefore we will need to use concatenation here instead.
" order by "+ sortBy + " " + sortOrder;

JDBC ResultSet get column from different tables

i wan to retrieve data from query involving many tables.
i have a query as follows
String sql = "SELECT "
+ "s.Food_ID AS 'Sales_FoodID', "
+ "f.Food_Name AS 'foodName' "
+ "FROM Ordering o, Sales s, Food f"
+ " WHERE o.Table_No = " + tableNo + ""
+ " AND o.Paid = '" + NOT_PAID + "'"
+ " AND s.Order_ID = o.Order_ID"
+ " AND f.Food_ID = s.Food_ID;";
resultSet = statement.executeQuery(sql);
no error were found when i run the program, but after i add this line to get a table's column data:
String orderID = resultSet.getString("foodName");
i'm given this error:
java.sql.SQLException: Column not found
anyone know why?
You have to use next() method.
You should know that ResultSet is implicitly positioned on position before first row so you need to call next to get current position and if is valid, it returns true, else returns false (cursor is positioned after the last row).
rs = statement.executeQuery(sql);
while (rs.next()) {
String orderID = rs.getString(2);
}
Note: You can use also rs.getString(<columnName>) but in case when you know how your statement looks i recommend to you use index instead of columnName.
After calling the resultSet.executeQuery() you need to call the next() to pulling the records from db
after that you can call setXxx() provided by Java API

Resources