HQL Select New doesn't return row when a foreign key is null - spring

I have the following named query
#NamedQuery(name = "UserFlight.getUserFlightDetails",
query = "SELECT new com.foobar.UserFlightDetails(uf.flight.divertedAirport, uf.flight.number) " +
"FROM UserFlight uf WHERE uf.user.id=?1 AND uf.flight.id=?2")
The UserFlightDetails constructor is as follows
public UserFlightDetails(Airport airport, String flightNumber) {
this.setDivertedAirport(airport);
this.setFlightNumber(flightNumber);
}
divertedAirport is a foreign key in the flight table, path=(uf.flight.divertedAirport)
My problem is when divertedAirport is null (it's a nullable foreign key), my HQL query returns null as the result (The code doesn't even trigger the constructor above), so I don't get the flightNumber which is never null.
If the divertedAirport isn't null, I get both the airport and the flight number fine (and the above constructor gets executed just fine).
What could be causing this and how could I resolve it? I tried some null functions like nullif and coalesce but nothing helped.
I'm using spring boot 1.2.7, hibernate-core 4.3.11.Final

Probably, the problem is the uf.flight.divertedAirport. This expression do a JOIN between flight and divertedAirport but, as you say, divertedAirport is a fk and can be null.
So, you need to use the LEFT JOIN.
I would rewrite your query like this:
#NamedQuery(name = "UserFlight.getUserFlightDetails",
query =
"SELECT new com.foobar.UserFlightDetails(divertedAirport, flight.number)
FROM UserFlight uf
JOIN uf.flight flight
LEFT JOIN flight.divertedAirport divertedAirport
JOIN uf.user user
WHERE user.id = ?1 AND flight.id = ?2 ")
I remove the references like uf.user.id for a explicit JOIN (JOIN uf.user user plus user.id), because is more legible and this kind of problem that generated your question is more easy to find using this way to write JPQL queries.

Related

Spring MVC, Select Special Columns in Native SELECT Query

this is my native SELECT Query in Repository
#Modifying
#Query(value = "SELECT * FROM tasks WHERE title LIKE '%Java%' ORDER BY id DESC ", nativeQuery = true)
List<Task> listAllTasks();
this works ok, but when I use custom column name instead of *, like this
#Modifying
#Query(value = "SELECT title FROM tasks WHERE title LIKE '%Java%' ORDER BY id DESC ", nativeQuery = true)
List<Task> listAllTasks();
I have this error :
org.postgresql.util.PSQLException: The column name id was not found in this ResultSet.
any Help?
The resultset doesn't have the "id" in it, you have to provide it.
You should change the way you are declaring your SQL:
SELECT t.title, t.id FROM tasks t WHERE t.title LIKE '%Java%' ORDER BY t.id DESC
Check out this sort example:Native Queries
Select * from Entity -> returns a List of Entity
Example:
#Query(select * from tasks)
List<Task> findAllTasks();
Select column from Entity -> returns a List of Types of the entity.
Example:
#Query(select t.title from tasks t)
List<String> findTitle_AllTasks();
title is of the type String
Select multiple columns from Entity -> returns an Object[] holding the data
Example:
#Query(select t.id, t.title from tasks t)
List<Object[]> findIdTitle_AllTasks();
So, you are retrieving String type data - title and asking to return a List of Task type. This is causing the problem. You can actually check the hibernate docs under HQL and JPQL to understand this.
Plus, you are doing a SELECT (DQL operation). #Modifying is rudimentary here as it is used for DML operations using Data JPA - UPDATE/DELETE.

Hibernate, Order by count of subquery on ManyToMany using Predicates

I have a query written using Predicates in Hibernate and I need to add a subquery on a join table to count the number of joins and order by the number of joins where they exist in an array of ids.
The join table is a ManyToMany relation.
I am using flyway to setup the table schema, so while the join table exists in the database, a join model is not needed in Hibernate to join the 2 related models therefore no join model exists.
I don't care about retrieving these related models, I just want the number of joins so that I can order by them.
The following is PostGreSQL, which works. I need to convert the following PSQL into a Predicate based query:
SELECT u.*, COUNT(jui.interest_id) AS juiCount
FROM "user" u
LEFT JOIN (
SELECT ui.user_id, ui.interest_id
FROM user_interest ui
WHERE ui.interest_id IN (?)
) AS jui ON u.id = jui.user_id
GROUP BY u.id
ORDER BY juiCount DESC
Where the ids provided for the IN condition are passed into the subquery. The above query is in PostGreSQL.
Working with what I have so far:
CriteriaBuilder b = em.getCriteriaBuilder();
CriteriaQuery<User> q = b.createQuery(User.class);
Root<User> u = q.from(User.class);
// This doesn't make sense because this is not a join table
// Subquery<Interest> sq = q.subquery(Interest.class)
// Root<Interest> squi = sq.from(Interest.class);
// sq.select(squi);
// sq.where(b.in("interest_id", new LiteralExpression<Long[]>((CriteriaBuilderImpl) b, interestIds)));
q.orderBy(
// b.desc(b.tuple(u, b.count(squi))),
b.asc(u.get(User_.id))
);
q.where(p);
return em
.createQuery(q)
.getResultList();
Everything I have managed to find doesn't quite seem to fit right given that they are not using ManyToMany in the use of q.subquery() in their example.
Anyone can help fill in the blanks on this please?

Laravel 4.2 Eloquent using lists() with a join query

I have a query that makes use of multiple joins:
public function scopePurchased($query, $userId)
{
return $query
->join('products','characters.id','=','products.productable_id')
->join('bundle_product','bundle_product.product_id','=','products.id')
->join('bundles','bundles.id','=','bundle_product.bundle_id')
->join('purchases','purchases.bundle_id','=','bundles.id')
->join('users','purchases.user_id','=','users.id')
->whereNull('purchases.deleted_at')
->where('purchases.refunded', false)
->where('products.productable_type', '=', get_class($this))
->where('users.id','=',$userId)
->groupBy('characters.id')
->orderBy('characters.title', 'ASC');
}
And I want to retrieve an array of ID's from this query to use in another scope so:
$query->purchased($userID)->lists('id')
My initial thought was to use lists('id') which complained about an ambiguous query on the ID.
Column 'id' in field list is ambiguous
(
SQL: select `id` from `characters`
inner join `products` on `characters`.`id` = `products`.`productable_id`
inner join `bundle_product` on `bundle_product`.`product_id` = `products`.`id`
inner join `bundles` on `bundles`.`id` = `bundle_product`.`bundle_id`
inner join `purchases` on `purchases`.`bundle_id` = `bundles`.`id`
inner join `users` on `purchases`.`user_id` = `users`.`id`
where `characters`.`deleted_at` is null
and `purchases`.`deleted_at` is null
and `purchases`.`refunded` = 0
and `products`.`productable_type` = Character and `users`.`id` = 1
group by `characters`.`id`
order by `characters`.`title` asc
)
Makes sense, fair enough so I changed the lists to
$query->purchased($userID)->lists('characters.id')
Thinking that naming the table and column should fix it but finding that the lists function drops the 'character.' part and so having the same error.
It appear that lists may not use a dot notation, bring me to my question... Can I escape the dot notation or is there another way to get the list of ID's as an array?
Many thanks
You can alias the column name before using lists:
$query->purchased($userID)->select('characters.id as _id')->lists('_id');
This will avoid any column name conflicts.

getting values from a table where value is not null

When doing an EF query in the code behind using LINQ, how does one go about retrieving only those items in a nullable column that actually have data?
for example;
Dim unit = (From d in ctx.Inventories
Where d.ProductId Is Not Null
Select d).ToList()
Where obviously that query doesnt work, how does one go about this?
Since ProductId is likely a nullable type, you should be able to do:
Dim unit = (From d in ctx.Inventories
Where d.ProductId.HasValue
Select d).ToList()

entity framework lazy loading null properties in child

Using entity framwork with lazy loading - Have the following question on loading related entities when the entities
are null.
Say I have two tables employee and employeedetails. Assume in the above case not all employee entries have an entry in the employeedetails table.
If I want to look up a list of Employees
(from e in objectcontext.employees
select new EmployeeEntity
{
EmpID= e.EmployeeID,
FirstName = e.FirstName,
Address = e.employeedetails.Address
}).ToList();
EmployeeEntity is the data class into which we stuff the results.
The above code breaks if even one employee in the returned list
does not have a entry in table employeedetails. This is obvious since e.employeedetails will be null for those customers who do not have a details entry
What is the best way to rewrite the above query?
Would something like this be acceptable ?
(from e in objectcontext.employees
select new EmployeeEntity
{
EmpID= e.EmployeeID,
FirstName = e.FirstName,
Address = e.employeedetails == null ? "" : e.employeedetails.Address,
}).ToList();
I am not clear on the efficiency of this above query - Would this statment do the null check at DB level?
Should I instead do an explicit include like
objectcontext.include("employeedetails")...
And then loop through the results to check for null?
Yes, this statement would indeed perform a null check in the SQL query that is generated. Most likely, it will simply be a NVL or COALESCE.
That's the way you should be doing it.

Resources