How to use inner join to get 'next column' value? - java

I've been researching for quite some time and it seems I may be misunderstanding how inner-joins work in MySQL.
I have 3 tables:
UserTable:
UserID UserName Hash UserUni UserHousing
1 John #123eq.. FK FK
2 Bob !S91ka.. FK FK
...
The foreign keys relate to the following two tables' PKs (UniID and HousingID, respectively):
UniversitiesList:
UniID UniName
1 Yale
2 Penn
...
HousingList:
HousingID HousingName UniID
1 Dorm_1 FK
2 Dorm_2 FK
...
Where, of course, these FKs are PKs (UniID) in Universities list
What I'm trying to do is query the id, hash, UserUni, and UserHousing values, i.e not the keys. This is what I'm playing around with now:
"SELECT UserTable.Hash, UserTable.UserID, UserTable.UserUni, UserTable.UserHousing "
+ "FROM UserTable "
+ "INNER JOIN UniversitiesList "
+ "ON UserTable.UserUni = UniversitiesList.UniID "
+ "INNER JOIN HousingList "
+ "ON UserTable.UserHousing = HousingList.HousingID "
+ "WHERE UserTable.UserName = John"
What I would like to retrieve is something like 1, #123eq, Yale, Dorm_1, but instead I keep getting 1, #123eq, 1, 1.
I'm working with Java so this is how I'm getting the results:
if (result.next()) {
hash = result.getString(1);
id = result.getInt(2);
uni = result.getString(3);
housing = result.getString(4);
}
Any idea one what I'm doing wrong?

Try changing your query to this:
"SELECT UserTable.Hash, UserTable.UserID, UniversitiesList.UniName, HousingList.HousingName "
+ "FROM UserTable "
+ "INNER JOIN UniversitiesList "
+ "ON UserTable.UserUni = UniversitiesList.UniID "
+ "INNER JOIN HousingList "
+ "ON UserTable.UserHousing = HousingList.HousingID "
+ "WHERE UserTable.UserName = John"
As written, you're only asking for the columns in your UserTable, not the other tables. The joins look ok from what I can tell...

Related

incorrect #query in spring boot

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

join fetch not working in Hibernate Query Language

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.

Mistake in HQL query while creating reports through hibernate projection

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.

SQLite fails to find existing column in SELECT via JDBC and jOOQ

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\"";

Formatting hql query

#My doubt is the partId in Product table can be null ,so if the partId is null I’m not able to see the product. If my Product Table has 11 entries and 2 entries have partId as null , Iam able to see only 9 entries
String hql = "from " + Product.class.getName() + " bs, "
+ Part.class.getName() + " dm, "
+ Manufacturer.class.getName() + " m where "
+ " m.id = bs.manufacturerId and dm.id = bs.partId ";
========================================
The ouput has to be like this
productName | PartName | Manufactuer Name
You need to do left joins instead of inner joins. But this is only possible if your entities are associated together instead of containing each other's IDs.
As is, it's plain impossible with HQL.
Given your query, you probably should have a ManyToOne between Product and Manufacturer, and a ManyToOne between Product and Part.
Also, your query would be much more readable if you didn't concatenate class names and if you used proper alias names:
String hql = "from Product product, Part part, Manufacturer manufacturer"
+ " where manufacturer.id = product.manufacturerId"
+ " and part.id = product.partId";
Once the associations exist, the query should just be
String hql = "select product.name, part.name, manufacturer.name"
+ " from Product product"
+ " left join product.part part"
+ " left join product.manufacturer manufacturer";

Categories

Resources