I had the following query working fine but then i had to convert it to hibernate projection for performance issues.
NamedQuery = " SELECT o FROM OrderJob o "
was converted to:-
String hqlQuery = "select "
+ "new JobAuditListVO( o.jobDate, o.jobType, customer.name, job.street, payment.description, p.paid,o.invoice) "
+ " from OrderJob o "
+ " join o.order ordr "
+ " join ordr.customer customer "
+ " join o.jobAddress job "
+ " join o.payment p"
+ " join p.paymentReceivedMethod payment";
getEntityManager().createQuery(hqlQuery).getResultList();
But the list is returning 0 results. While the name query return 2 results.
I have got the answer. Both the queries are absolutely equivalent.
The problem was that i had to use Left Join instead of Simple Join. Because some entities were returning null.
Related
I am trying to use this query in springboot so I can display the results in a webpage. I know that this query works because I tested it in postgresql and it gave me the right results.
But JPA is telling me that the '(' after the first FROM is an unexpected token and the query was therefore viewed as invalid.
This is my query:
#Query(
"SELECT com.example.imse22.model.TrvlA_Cust_Dto(books_query.name, count(travelA_query.customer_id)) " +
"FROM (SELECT DISTINCT customer_servant.employee_id, books.customer_id FROM customer_servant " +
"INNER JOIN books ON customer_servant.employee_id = books.customer_servant_id) AS travelA_query " +
"INNER JOIN " +
"(SELECT travel_agency.id, travel_agency.name, employee.employee_id FROM travel_agency " +
"INNER JOIN employee ON travel_agency.id = employee.travel_agency_id) AS books_query " +
"ON travelA_query.employee_id = books_query.employee_id " +
"GROUOP BY travelA_query.name")
can somebody help me out how I could rewrite the query so that JPA approves it?
Your query is native so you should declare it in that way:
#Query(
value = "SELECT com.example.imse22.model.TrvlA_Cust_Dto(books_query.name, count(travelA_query.customer_id)) " +
"FROM (SELECT DISTINCT customer_servant.employee_id, books.customer_id FROM customer_servant " +
"INNER JOIN books ON customer_servant.employee_id = books.customer_servant_id) AS travelA_query " +
"INNER JOIN " +
"(SELECT travel_agency.id, travel_agency.name, employee.employee_id FROM travel_agency " +
"INNER JOIN employee ON travel_agency.id = employee.travel_agency_id) AS books_query " +
"ON travelA_query.employee_id = books_query.employee_id " +
"GROUOP BY travelA_query.name", nativeQuery = true)
link point 2.2: https://www.baeldung.com/spring-data-jpa-query
Ok so this is how I solved it:
I changed my query into a native one just like #notAPPP pointed out and then I only had to add an alias for the LEFT JOIN (also I changed INNER JOIN to LEFT JOIN).
here the code example:
#Query(value = "SELECT combined.name as name, count(combined.customer_id) as id " +
"FROM (" +
"(SELECT travel_agency.name, travel_agency.id, employee.employee_id " +
"FROM travel_agency INNER JOIN employee ON travel_agency.id = employee.travel_agency_id) as trvlEmp " +
"LEFT JOIN " +
"(SELECT books.customer_id, books.customer_servant_id, customer_servant.employee_id " +
"FROM books INNER JOIN customer_servant ON books.customer_servant_id = customer_servant.employee_id) as custBooks " +
"ON trvlEmp.employee_id = custBooks.employee_id) as combined " + // this "AS combined" got added
"GROUP BY combined.name", nativeQuery = true)
This makes sense, because after a FROM clause one should wirte the name of a table or a result table (e.g. from two joined queries like in my case). As I didnt specify an alias for the LEFT JOIN of my two subqueries, JPA obviously didnt know how to handle the result of those subqueries. Therefore always name your subqueries if they are not used in a WHERE clause, but rather with a FROM clause, like in my case. E.g. the name I gave my LEFT JOIN is "combined" as seen in the code example above.
Also I changed my INNER JOIN to a LEFT JOIN to get the value 0 of the elements that have 0 counts of what I wanted to count in the table.
If you want to know how to handle the result which such a query returns follow this link.thorben-janssen.com/spring-data-jpa-dto-native-queries
I'm running this PostgreSQL query on Java and it is throwing an error "ERROR: syntax error at or near ":".
But the query is working on Postgresql when I run directly.
I'm thinking Array[]::integer[] is causing the issue. Can someone has any idea?
String query = "WITH RECURSIVE tree AS ( SELECT id, ARRAY[]::integer[] AS ancestors \n" +
" FROM regions \n" +
" WHERE parent_id IS NULL\n" +
" UNION ALL \n" +
" SELECT soato.id, tree.ancestors || regions.parent_id \n" +
" FROM regions, tree \n" +
" WHERE regions.parent_id = tree.id \n" +
") \n" +
" SELECT d.id FROM department d \n" +
" WHERE d.region_id IN (select id from tree where 1703 = ANY(tree.ancestors))";
Query q = entityManager.createNativeQuery(query);
q.getResultList();
Use an explicit cast to avoid the implicit PostgreSQL option :: for casting.
ARRAY[CAST(NULL AS INTEGER)] AS ancestors
I'm working on a website in a Spring Bootwhich is connected to a MySQL db. In the db i have two tables: Player and Match and i created a query that should return me a list of players with count of matches they already played. The problem is that typed aggregate function count(M) doesn't and I don't know that I'm doing wrong. In db I have e.g. Player with id = 1 and two played Matches, another with one Match, and another with 0. What I get as a result is one Player with 3 played Matches. If i type M.id instead of count(M), I get two rows for Player 1 (one for Match id), and onw row for the second. What is wrong with my code?
#Query( "select new dto.PlayerDTO(" +
" P.id, " +
" P.nickname, " +
" count(M), " +
"from " +
" Player P left join Match M on P = M.player " +
"where " +
" P.games like %?1% ")
List<PlayerDTO> findPlayersForGame(String game);
When you count() on the joined table, you have to use group by statement:
#Query( "select new dto.PlayerDTO(" +
" P.id, " +
" P.nickname, " +
" count(M), " +
"from " +
" Player P left join Match M on P = M.player " +
"where " +
" P.games like %?1% " +
"group by P.id ")
List<PlayerDTO> findPlayersForGame(String game);
I want to retrieve all the records in One database hit and for that, I am using join fetch statements below is my Query
String q = "SELECT oneChat from " + Chat.class.getName() + " oneChat "
+ " join fetch oneChat.user1 "
+ " join fetch oneChat.user2 "
+ " join fetch oneChat.user3 "
+ " join fetch oneChat.groupData "
+ "where oneChat.dmlStatus != :dmlStatusValue"
+ " AND group_id = :groupIdValue" + " AND reference_id = 0"
+ " AND root_chat_id = oneChat.chatId";
There are total 4 foreign keys/Joins in my table so I added the join fetch statement but its not working i.e. not returning anything how ever if I remove the join fetch statements I get the result set. My Fetch on table joins is by default Eager ( didn't changed it to Lazy).
Also there's no sql syntax error in the Log file. Am I missing anything ?
Update:
It is because the second join i.e. user2 is returning null so I wasn't getting any data. Now if anyone could tell me how can I counter this, the query should be independent it shouldn't rely on data.
IF you want to return results regardless of data being present on the dependencies, then you should use left join instead of inner join (join fetch is equal to inner join fetch):
"SELECT oneChat from " + Chat.class.getName() + " oneChat "
+ " left join fetch oneChat.user1 "
+ " left join fetch oneChat.user2 "
+ " left join fetch oneChat.user3 "
+ " left join fetch oneChat.groupData "
+ "where oneChat.dmlStatus != :dmlStatusValue"
+ " AND group_id = :groupIdValue" + " AND reference_id = 0"
+ " AND root_chat_id = oneChat.chatId";
Now when the OneChat does not have any user2 dependency on the database, the query will still return results regardless of that.
Just on the side.. if you are using prefixed, then try to add prefixes to group_id and root_chat_id fields in the where clause for clarity.
I experience some strange results working with SQLite and JDBC (via JOOQ actually, but this problem can be reproduced by executing the query string manually via JDBC). My database consists of a three tables including a many-to-many and one-to-many relationship. I try to select all values of the 'main' table and join all needed values out of the relationship tables:
SELECT location.name,
world.world,
player.player
FROM location
JOIN world
ON location."world-id" = world."world-id"
LEFT OUTER JOIN (location2player
JOIN player
ON location2player."player-id" = player."player-id")
ON location."location-id" = location2player."location-id"
Within JDBC this query fails:
java.sql.SQLException: [SQLITE_ERROR] SQL error or missing database (no such column: player.player)
When I execute the query in an external SQLite editor such as SQLite Manager for Firefox it works as expected.
I work with sqlite-jdbc-3.7.2 which I cannot change. For reference, the JOOQ query is:
create.select(LOCATION.NAME,WORLD.WORLD_,PLAYER.PLAYER_)
.from(LOCATION
.join(WORLD)
.on(LOCATION.WORLD_ID.eq(WORLD.WORLD_ID)
)
.leftOuterJoin(LOCATION2PLAYER
.join(PLAYER)
.onKey()
)
.on(LOCATION.LOCATION_ID.eq(LOCATION2PLAYER.LOCATION_ID)
)
.fetch()
Why fails this query in JDBC and how am I supposed to fix it?
While I think that you wrote valid ANSI SQL, it may well be that SQLite interprets your statement slightly differently. But you don't really need to nest joins the way you do. Try this insted:
SELECT location.name,
world.world,
player.player
FROM location
JOIN world
ON location."world-id" = world."world-id"
LEFT OUTER JOIN location2player
ON location."location-id" = location2player."location-id"
LEFT OUTER JOIN player
ON location2player."player-id" = player."player-id"
I was able to recreate your issue under sqlite-jdbc-3.7.2 using
sql =
"SELECT location.name, " +
"world.world, " +
"player.player " +
"FROM " +
"location " +
"JOIN world " +
"ON location.\"world-id\" = world.\"world-id\" " +
"LEFT OUTER JOIN (location2player " +
"JOIN " +
"player " +
"ON location2player.\"player-id\" = player.\"player-id\") " +
"ON location.\"location-id\" = location2player.\"location-id\"";
The problem appears to be that the location2player and player tables are "hidden" inside the parentheses () of the sub-join and are unavailable to the initial column list and the final ON clause. The following statement avoids that problem by giving the subquery an alias and using the alias name in those two places:
sql =
"SELECT " +
"location.name, " +
"world.world, " +
"playerlocation.player " +
"FROM " +
"location " +
"JOIN " +
"world " +
"ON location.\"world-id\" = world.\"world-id\" " +
"LEFT OUTER JOIN " +
"( " +
"SELECT location2player.\"location-id\", player.player " +
"FROM " +
"location2player " +
"JOIN " +
"player " +
"ON location2player.\"player-id\" = player.\"player-id\"" +
") AS playerlocation " +
"ON location.\"location-id\" = playerlocation.\"location-id\"";