JPQL inner join and left join - jpa

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.

Related

SPring data JPA JPQL multi join entities

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.

Left Join an Element collection using JPQL

Suppose I have this classes, notice that entities are not related in anyway.
#Entity
class Laptop {
#Id
String userId;
#Column
String name;
...
}
#Entity
class Foo {
...
#Column
#ElementCollection
List<String> idsPointingToAnEntity;
...
}
Given that I have this Foo class which has an attribute of idsPointingToAnEntity, I could store there a list of Laptop ids or any ids of String. Let's say Foo has idsPointingToAnEntity=[1,2,3], this [1,2,3] has an equivalent Laptop entry in the database.
How can I left join/ join them with ordering in JPQL such given that the result is a list of Foo sorted by Laptop names.
In theory I think it is something like this.
Select f From Foo f LEFT JOIN Laptop l ON l.id IN f.idsPoitingToAnEntity ORDER by l.name
But this is having an error for me since f.idsPoitingToAnEntity is a Join table.
Note: idsPointingToAnEntity can also be another entity making List<Laptop> is not an option
If you are using JPA 2.1 or higher you use JOIN ON in JPQL on unrelated entities. Join the IDs table first, like this:
select f from Foo f
join f.idsPointingToAnEntity id
join Laptop l ON id=l.id
join AnotherEntity a ON id=a.id
You can use no Joins to obtain this result:
SELECT l FROM Laptop l, Foo f
WHERE l.id IN f.idsPointingToAnEntity ORDER BY l.name
Or use CROSS JOIN, a special kind of join that don't require any matching conditions:
SELECT l FROM Laptop l
CROSS JOIN Foo f
WHERE l.id IN f.idsPointingToAnEntity ORDER BY l.name
PS: the problem of using cross join in this scenario, is that it generates the Cartesian Product, not all the rows from left side.
Short answer here is simply don't do that. It is misusing the specific feature and likely to lead to troubles as your list grows. You have no good justification for doing this. If you think the list is small then the database load is minimal and there is no reason to put references into an ElementCollection. If the list gets large you definitely don't want an ElementCollection.
Reference Difference between #OneToMany and #ElementCollection?. An ElementCollection is for creating a OneToMany between, in your case, Foo and idsPointingToAnEntity. It's definitely not meant to be used as a One-To-Many Relationship with Join Table.

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

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]

Matching items with multiple foreign keys in RavenDB

I asked this question previously regarding SQL Server: Complicated SQL Query--finding items matching multiple different foreign keys
Basically, I need to be able to find products that match multiple criteria. I have a scenario where I need to find products that match each of multiple categories and are found in multiple invoices.
The solution was a rather complex set of unions, which amounts to counting the number times a product matched the criteria and filtering for items whose count matched the count of criteria.
; with data (ID, Count) as (
select pc.ProductID, count(*) from ProductCategories pc (nolock)
inner join #categoryIDs /*table valued param*/ c on c.ID = pc.CategoryID
union all
select ip.ProductID, count(*) from InvoiceProducts ip (nolock)
inner join #invoiceIDs i on i.ID = ip.InvoiceID
)
select d.ID from data d
group by d.ID
having sum(d.Count) = #matchcount
But now, I am considering a NoSQL provider. So my question is, how would I create an index function to match this kind of query in RavenDB (or some other NoSQL project)?
A mental shift is required to properly set this up with RavenDB (or any other document DB). The problem is with the hacks we all used to make when working with structured data against an SQL server.
Therefore, the question here is how your data is modeled. To be more exact - how are you going to use it most often; based on that there are certain guidelines on which entities to define and how to link them together.
For a simple Product object, with String[] of categories, you can query the DB like this:
// Query on nested collections - will return any product with category "C#"
products = from p in session.Query<Product>()
where p.Categories.Any(cat => cat == "C#")
select c;
You can add as many Where clauses as you want. An index will be automatically created for you - but it is recommended to use static indexes when you've settled on a Model.
More on this topic:
http://ayende.com/blog/4801/leaving-the-relational-mindset-ravendbs-trees
https://github.com/ravendb/docs