JPA JPQL: select entities with List attribute - jpa

I have an entity which have a collection of tags
#ManyToMany
private Set<Tag> listeTag;
I want to write a query which returns a list of my entity which contains all tags passed in parameters and not just one like this.
select distinct entity from Entity entity where and entity.listeTag in :listeTag
if there are two tags in listeTag I want only entities which have at least the two tags.

select e from SomeEntity e where :numberOfTagsInSet =
(select count(tag.id) from SomeEntity e2
join e2.listeTag tag
where e.id = e2.id
and tag.id in :setOfTagIds)
That should do the trick.

Related

QueryDSL Left Join not mapping properly with JPA entity

QueryDSL is not working properly with JPA for left join.
I am using queryDSL version 4.2.1 and mapping the response directly to javax.persistence entity.
For Left join/Right join, the joining condition it's not working. It fetches every entity disregarding the joining condition(here it's name = "testName") when entity1.getEntity2() is being called.
Is there any other way applicable for this case to map the result after JOIN tables ?
JPAQuery<Entity1> query = new JPAQuery<>(entityManager);
query.from(table1);
query.leftJoin(table2).on(table2.id.eq(table1.id).and(table2.name.eq("testName"));
List<Entity1> list = query.fetch();
#Entity
public class Entity1{
private Integer id;
#OneToMany(mappedBy = "entity1", fetch = FetchType.LAZY)
private List<Entity2> entity2;
}
An left or right join is an outer join.
So if you use left join all records from the left (in your case table1) will be selected.
If you only want records from table1 if there are corresponding records on table2 you have to use innerJoin.
JPAQuery<Entity1> query = new JPAQuery<>(entityManager);
query.from(table1);
query.innerJoin(table2).on(table2.id.eq(table1.id).and(table2.name.eq("testName"));
List<Entity1> list = query.fetch();
Read more about the join types here:
https://www.diffen.com/difference/Inner_Join_vs_Outer_Join

OrderBy Expression When Using An Association Table

I have two tables: CommentCategories and Comments. It is a many-to-many relationship. There is a CommentCategory_Comment association table. But that table contains a orderOfCommentInCategory field, so EF represents the association by creating a seperate entity rather than navigation properties.
I am trying to get the comments under a certain category and orer them by the orderOfCommentInCategory field. How should be the OrderBy expression that needs to be added to the query below?
List<Comment> comments = category.CommentCategory_Comment
.Select(ccc=>ccc.Comment)
.OrderBy(???)
.ToList();
As #GertArnold recommends the only you need to do is order first before select:
var comments = category.CommentCategory_Comment
.OrderBy(c=>c.orderOfCommentInCategory )
.Select(ccc=>ccc.Comment)
.ToList();
Using query syntax:
var query= from cc in category.CommentCategory_Comment
orderby cc.orderOfCommentInCategory
select cc.Comment;
var comments=query.ToList();

How can I write an EXISTS predicate on a collection attribute in Criteria API?

I have these classes:
#Entity
public class Customer {
#Id long id;
String name;
#OneToMany List<Customer> related;
}
and I'm using this JPQL query:
select c from Customer c where c.name = 'ACME'
or exists( select 1 from c.related r where r.name = 'ACME' )
How can I write the same query with the Criteria API? I need to use exists with a subquery, like the JPQL, but I don't know how to create a subquery from a collection attribute in the Criteria API.
Something like this would give EXISTS (subquery)
Subquery<Long> sq = cq.subquery(Long.class);
Root<Customer> customerSub = sq.correlate(customer);
Join<Customer,Customer> related = customerSub.join(Customer_.related);
... extra config of subquery
Predicate existsCustomer = cb.exists(sq);
where cq is the CriteriaQuery, and cb is CriteriaBuilder. This comes from an example in the JPA 2.1 spec p323 Example 4

Finding an inherited entity over a jointable with NamedQuery

How can I use a NamedQuery to find an entity over a jointable?
I have an abstract parent class/entity with #Inheritance(strategy=InheritanceType.JOINED) and two subclasses/subentities.
Hence, in the database I have a parent table (sdrs) and two subtables (xSdrs and ySdrs).
There is another table reservations which shall have a Many-to-Many relationship to table sdrs. That's why I created a jointable between reservations and sdrs.
I intend to have a NamedQuery in the parent entity Sdr to be able to find the key for a record/entity of XSdr or YSdr respectively over the jointable.
In class Sdr I have:
#NamedQuery(name="Sdr.findBySdrId", query="SELECT s FROM Sdr s "
+ "INNER JOIN s.reservations res WHERE res.sdrs = :transactionId")
and
#ManyToMany(fetch=FetchType.EAGER, cascade=CascadeType.ALL)
#JoinTable(name="sdrs_has_reservations",
joinColumns = {
#JoinColumn(name="sdrs_id", referencedColumnName="sdrId", nullable=false)
}, inverseJoinColumns={
#JoinColumn(name="reservations_id", referencedColumnName="reservationId", nullable=false)
})
private List<Reservation<T>> reservations;
But, of course, this sets the transactionId to reservationId which consequentially fails.
On the inverse side I have:
#ManyToMany(mappedBy="reservations", fetch=FetchType.EAGER)
private List<Sdr<T>> sdrs;
So, how do I have to implement the named query in class/entity Sdr to be able to get the proper Sdr (and its related reservations) with an Sdr ID to be set as query parameter?
SELECT sdr FROM Reservation r JOIN r.sdrs sdr WHERE sdr.id=:id

JPA OneToMany relations and performace

I have two entities: parent Customer and child Order.
Each Customer has 1,000,000 Orders for example, so it is not needed in any given time to load a Customer with all Orders but I want to have this ability to make join query on these two entities in JPA.
So because of this, I must create #OneToMany relationship for making join queries.
My question is: how to get query without making joinColumn because even in Lazy mode it is possible to load 1,000,000 objects!
I just want to get query on these object with where restrictions like native join.
If you don't want the #OneToMany relationship implicitly set in your Customer class than you don't have to. You can execute JPQL queries (in very precise manner) without the marked relationship.
Assume you have:
#Entity
public class Customer {
// all Customer-related fields WITHOUT #OneToMany relationship with Order
}
#Entity
public class Order {
#ManyToOne
private Customer owner;
}
Then if you want to get all Orders for particular Customer you can execute a simple JPQL query like that:
// Customer customer = ...
// EntityManager em = ...
String jpql = "SELECT o FROM Order o WHERE o.owner = :customer";
TypedQuery<Order> query = em.createQuery(jpql, Order.class);
query.setParameter("customer", customer);
List<Order> orders = query.getResultList();
In this way you can execute the code only when you're really sure you want to fetch Customer's orders.
I hope I've understood your problem correctly.
EclipseLink has support for QueryKeys, that allow you to define fields or relationships for querying that are not mapped. Currently there in no annotation support for query keys, but you can define them using the API and a DescriptorCustomizer.
Also you do not need the OneToMany to query on it, just use the inverse ManyToOne to query,
i.e.
Select distinct c from Customer c, Order o where o.customer = c and o.item = :item
Or,
Select distinct o.customer from Order o join o.customer c where o.customer = c and o.item = :item