-
Notifications
You must be signed in to change notification settings - Fork 54
Inline optional with where is not optional #233
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
@molexx It looks like a bug to me. :) You can try use this query as workaround:
{
"data": {
"Humans": {
"select": [
{
"id": "1001",
"name": "Darth Vader",
"favoriteDroid": {
"name": "R2-D2"
}
},
{
"id": "1002",
"name": "Han Solo",
"favoriteDroid": null
},
{
"id": "1003",
"name": "Leia Organa",
"favoriteDroid": null
},
{
"id": "1004",
"name": "Wilhuff Tarkin",
"favoriteDroid": null
}
]
}
}
} |
Thanks! But the response doesn't include Luke, I expect him to be there but with |
I think the problem here is that in SQL an outer join will return no rows (as opposed to null) if the WHERE clause contains a predicate that doesn't match. So a possible fix for this is to move the predicates from the WHERE to each join's ON. Unfortunately the JPA spec disallows adding ON predicates to fetch joins, they are only allowed on joins that aren't fetch, and all of this project's joins are fetch joins. Is it possible to change that? |
@molexx Changing predicates to apply restrictions in JPA's JOIN ON for each join will not make a difference. The underlying SQL query will use either outer outer or inner join with restrictions on the join, i.e. GraphQL JPQL Fetch Query:
Is translated by Hibernate to:
but it is also equivalent to the following query with left outer join where name restriction:
In this plain query without name restriction all humans are returned with or without droid relation, which is optional by default:
Now, with name restriction, the SQL query applies it on the left outer join and correctly returns single Darth Vader:
After relaxing name restriction to include humans without favorite droids, i.e.
So, I think there the query and results are consistent. |
The last GraphQL response doesn't include Luke because his favoriteDroid is neither null nor begins with 'R'. But I'd like to be able to include Luke, with a null favoriteDroid. In the original query I'm expecting all 5 Humans to be listed because the Humans aren't restricted and the 'name begins with R' predicate on favoriteDroid is marked as I tried the two SQL queries in the H2 console and they produce different results: The first one, with But the second SQL, with |
@molexx I have been experimenting with fetch join on condition to try enabling collection filters using embedded where criteria expressions, i.e.
Each query produces different results:
The only caveat is I had to hack Hibernate to disable check for fetch join with on conditions: The relevant change in the code is here: |
Thanks for this @igdianov ! Is it okay to hack hibernate? Will we hit issues updating it and get stuck on a particular version? Would an alternative be to not use fetch joins but instead build a fetch graph as it goes along? |
@molexx I know it is not a good idea to hack Hibernate. There only reason they have the restriction on fetch join condition is to follow JPA spec, so it is not a option. The only viable option to implement collection fetch filter behavior is to create extra queries when resolving data for associated collections with inline where criteria, but it will have big impact on performance due to N+1 queries generated for each parent record. It might be possible to mitigate it with GraphQL batch loader, but I am not sure if this is going to work at all due to entity manager session binding to specific thread while batch loader execution will run on a different thread. |
… plural attributes (#251) * fix: add ON condition on the right side of collection join fetch criteria * fix: remove Hibernate HqlSqlWalker hack * fix: add GraphQLJpaOneToManyDataFetcher for inline query filter * fix: optimize OneToManyDataFetcher using query stream result * fix: update name to GraphQLJpaOneToManyDataFetcher * feat: add OneToMany batch DataLoader support * fix: refactor GraphQLJpaOneToManyMappedBatchLoader * feat: add GraphQLJpaToOneMappedBatchLoader support * fix: add batch query logging * fix: add support orderBy sort for collections * fix: unexpected NPE in getJPQLQueryString * fix: add support for inline optional to one assiciations * fix: add inline optional support for singular attributes * fix: add support for inline collections filter with alias * fix: remove hibernate-core dependency * fix: polish data loader data fetchers
I want to get all Humans, and include their favoriteDroid if their favoriteDroid's name begins with 'R'. I want Humans who don't have a favoriteDroid or who's favoriteDroid is C3PO to still be listed but have
favoriteDroid: null
.But for this:
the 'optional' appears to have no effect - most Humans are excluded.
If there is no where clause then it works as expected - Humans with no favoriteDroid are returned with a null favoriteDroid.
The text was updated successfully, but these errors were encountered: