SPring data JPA JPQL multi join entities - spring-data-jpa

I want to join multiple tables by using JPQL query(#Query) with one-to-many mapping in model entities .
Eg: total 8 tables are there to join !! But I am getting error for OneToMany model mapping .
Below Query Works only for #OneToOne mapping
#Query("select new com.infinite.springframework.dto.WPOrderResponse(c.logo ,p.name,c.name ,ks.days)
FROM WPorder w , Project p ,Assignee a ,Customer c ,Domains d ,User u ,wp_kpi wk ,Kpi_Status ks
where w.project=p and p.assignee=a and w.customer=c and w.domains=d and w.wpKpi=wk and wk.kpiStatus=ks and u.id=:userID
group by p.id ,wk.id")

In my opinion, for those complex queries in RDBMS, create a view in the database side firstly.
Then in your project create a read-only(in concept, most of the views in database does not support modifications) Entity for the view for queries, it is more effective.

Related

SQL Tables with no direct relation

I have a PostgreSQL DB and I need to build a query to retrieve the information from a table that has no direct link with the main one.
The client is linked to the client_identity_document through its UUID and client_identity_document to the identity_document through the uuid_identity_document. I know I have to make an inner join, but I just started with relational databases and I don't know exactly the syntax to join tables that don't have direct relation.
try this
select *
from client c
inner join client_identity_document cid on c.UUID = cid.UUID_Client
inner join identity_document id on cid.uuid_identity_document = id.UUID

What's the difference between "JOIN FETCH" and "JOIN"?

Supposing I have a Person entity that has #OneToMany relationship with Phone entity. If I want to eagerly fetch Phone entities associated with a Person, I got 2 options:
SELECT p FROM Person p JOIN p.phones
or
SELECT p FROM person p JOIN FETCH p.phones
So what is the difference between them?
Remember that, in the end, JOIN FETCH is always a JOIN.
By default #OneToMany relationships are lazy loaded.
Using JOIN FETCH you load the related entities in advance.
You can find more info reading FETCH JOIN is still a JOIN by Piotr Nowicki

JPQL inner join and left join

I know what joins are and how to use them in plain SQL but i can't find any explanation of internet to query object with relations. I use entity,getList.size() to query objects that has oneToMany or ManyToMany associations with my entity. I'm wondering is there any way to query object with all his relations.
public Person
#OneToMany
List<Cat>
#ManyToMany
List<DormRoom>
what is do to get all object is;
Person p=PersonDAO.getWithId(1L);
p.getCats.size();
p.getsDormRooms.size();
Now i'm wondering the get fully evulated object with JPQL, CriteriaBuilder and maybe with QueryDSL.
It's called a fetch join:
select distinct p from Person p left join fetch p.cats left join fetch p.dormRooms
where p.id = :id
Beware though:
in Hibernate at least, that will only work if at most 1 of the collections is a bag (i.e. a list without any specified order column).
that will create a query returning the cartesian product of cats * dormRooms. So if a person has 100 cats and 100 dormRooms, 10,000 rows will be retrieved.

how to query a many to many for the absence of records using EF5

Assuming a pure many to many where the primary key is the composite of two foreign keys. For example "Employee Privileges" in Northwind has EmployeeID and PrivilegeID. This m2m obviously relates the Employees table to the Privilege table.
I need to write a query with EF that returns all Employees that are NOT associated with a specified PrivilegeID, regardless of whether or not it is related to other PrivilegeIDs.
I have an EF query that works for Sql Server using Except() but it doesn't work for Oracle.
If I were writing the query in t-sql, I would write a query that filters Employee Privileges with the required Privileges "see EmpPrivQuery below". I would then RIGHT join EmpPrivQuery to Employee as seen in EmployeesMissingPrivileges to complete the filter.
We currently have Employee and Privilege models with relationship properties to create the many to many table. The project uses EF code first to create the schema.
Can this be done with EF join syntax? Can it be done without creating an Entity model for the EmployeePrivilege table?
EmpPrivQuery:
SELECT [Employee Privileges].[Employee ID], [Employee Privileges].[Privilege ID]
FROM [Privileges] INNER JOIN [Employee Privileges] ON Privileges.[Privilege ID] = [Employee Privileges].[Privilege ID]
WHERE (((Privileges.[Privilege Name])="P3"));
EmployeesMissingPrivileges:
SELECT EmpPrivQuery.[Employee ID], Employees.*
FROM Employees LEFT JOIN EmpPrivQuery ON Employees.ID = EmpPrivQuery.[Employee ID]
WHERE (((EmpPrivQuery.[Employee ID]) Is Null));
This block was in original post but clouds the question. Retained for comment context.
I'm using Devart dotConnect as as the Oracle data provider.
The error that Oracle is throwing is ORA-00904: "Extent1"."EmployeeID": invalid identifier. In adapting the code base that was written for sql server to work against oracle, this is a common error that I've needed to resolve. In most cases I have been able to resolve it by re-writing the query to move relationships to other tables out of the WHERE predicate (where it is very easy to be dynamic) up into the main body of the query using SelectMany(). This tends to flatten the query being sent to the database server and Oracle appears to require that.
You can use EF to create basically the same queries posted in the question. I started by creating a poco model EmployeePrivilege with properties: int PrivilegeID & int EmployeeID. I did not add this to the DbContext.
var EmpPrivQuery = ctx.Privileges
.Where(p => p.PrivilegeName == "P3")
.SelectMany(p => p.Employees, (p, e) => new EmployeePrivilege{EmployeeID = e.EmployeeID, PrivilegeID = p.PrivilegeID}
.Distinct();
var employeesMissingPrivilege = from e in Employees
join epq in EmpPrivQuery
on e.EmployeeID equals epq.EmployeeID
into jointable
where jointable.Count()==0
select e;
I just realized you can also get the same result without creating the poco EmployeePrivilege as follows:
var EmpPrivQuery = ctx.Privileges
.Where(p => p.PrivilegeName == "P3")
.SelectMany(p => p.Employees.Select(e => e.EmployeeID)
.Distinct();
var employeesMissingPrivilege = from e in Employees
join epq in EmpPrivQuery
on e.EmployeeID equals epq
into jointable
where jointable.Count()==0
select e;
Both of these EF queries return Employees missing specified privileges against both Sql Server and Oracle (using Devart's dotConnect for Oracle).
Many posts that I read referred to using DefaultIfEmpty() to achieve a left outer join. The queries above work, however, please post if there is a better way to this result using DefaultIfEmpty().

Can I get Entity Framework to create code for my many-to-many relationship tables?

Say I have the MSSQL tables A, AB and B, where AB is a simple ManyToMany mapping table containing two columns: Primary key for A and Primary key for B. Entity Framework does not generate a class for AB, only a collection of B in A and of A in B. Sometimes I want to list the contents of AB as is.
Is there any way I can get EF to generate code for the AB ManyToMany-table?
PS I'm using Rob Halletts Mocking Context Object Generator for code generation. Don't know if this is relevant.
No, you can't. The join table is never represented as an entity in your model. But you can list the content of the AB join table also without that entity:
var joinTableList = (from a in context.As
from b in a.Bs
select new
{
AId = a.Id,
BId = b.Id
})
.ToList();
You get a list of of anonymous objects. Every object has the AId and BId as properties. This LINQ query is translated into a very simple SQL query over table AB without any joins:
SELECT
[Extent1].[AId] AS [AId],
[Extent1].[BId] AS [BId]
FROM [dbo].[ABs] AS [Extent1]