I am using spring-data jpa. When querying parent object with child object property,I was expecting parent with aggregated child objects.I have OneToMany relation between User and Phone. Just typing some part of code.
#Query(select u from User u inner join u.phone ph where ph.active=:active)
Page<User> getAllUsers(#Param("active") int active);
#Entity
User{
#OneToMany(fetch=FetchType.LAZY)
List<Phone> phone;
}
#Entity
Phone{
#ManyToOne
User user;
}
My query returns multiple User object based on active phone quantity. I was expecting one User object and all aggregated phone object in the list as part of User object. Is my assumption is wrong or am I doing something wrong?
Try:
#Query(select distinct u from User u inner join u.phone ph where ph.active=:active)
Page<User> getAllUsers(#Param("active") int active);
Related
I am using spring data jpa:
What is the best way to filter child object on the parent.
on my below example
I want Parent objects which has active childs, also wanted only active childs as list with parent
#Query(select distinct p from Parent p inner join p.child c where c.active=:active)
Page<Parent> getAllPArents(#Param("active") int active);
#Entity
Parent{
#OneToMany(fetch=FetchType.LAZY)
List<Child> child;
}
#Entity
Child{
#ManyToOne
Parent parent;
}
I had exactly the same problem and it took me a while to find out how this works. The child list will be filtered when you add FETCH after your JOIN like this:
SELECT p FROM Parent p JOIN FETCH p.child c WHERE c.active=:active
After spending lot of time, I could not find any solution to filter the child while querying the parent.
I decided to change the database structure so that I will be able to query child that I wanted. Added another filed/property that can put child into different categories. When querying child using unique criteria that will give me only the child I needed, also gave me the parent which I needed too.
I found the way to do this:
You can use the #Where annotation to filter the childs of a one to many or a many to many relationship.
public class Parent {
#OneToMany(mappedBy="Parent")
#Where(clause = "active = 1") //In case of a boolean but it can be a LIKE, a comparator...
private Set<Child> childs; //This gets filled with pets with a name starting with N
//getters & setters
}
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
I am struggling with the JPA Criteria API for formulating a query for my data structure. Ok, my entities are as follows. I have users and groups (both share a common base class OrgEntity). Logically, users can be members in multiple groups of course. Finally, I have an entity representing a task, which has a list of potential owners (that can be either single users or whole groups). The domain model is summarized below and is given, so I cannot change it.
#Entity
#Inheritance(strategy=InheritanceType.JOINED)
abstract public class OrgEntity {
#Id
public String name;
...
}
#Entity
public class User extends OrgEntity {
public String displayName;
#ManyToMany(mappedBy="members")
public List<Group> groups;
...
}
#Entity
public class Group extends OrgEntity {
#ManyToMany
public List<User> members;
...
}
#Entity
public class Task {
#Id
public String uuid;
#ManyToMany
public List<OrgEntity> potentialOwners;
...
}
The starting point for my query is a single instance of User. I want to know all the tasks where the user is a potential owner (regardless if the user is directly contained in the potentialOwners collection or member of a group that is contained in potentialOwners).
My first attempt using a named query was as follows
SELECT DISTINCT t FROM Task AS t JOIN t.potentialOwners po
WHERE (po IN (SELECT g FROM User u JOIN u.groups g WHERE u = :user)
OR po IN (SELECT u FROM User u WHERE u = :user))
It works, but I don't know if this is the most efficient way to do this. Any suggestions?
However, I have no idea how to implement this using the criteria API. Can somebody please help me with that.
Thanks
Ok, I finally figured out how to do it. If you are interested in my solution, here it is. u is the User object, basically the query parameter and em is the EntityManager instance.
CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
// specifies the result value of the query
CriteriaQuery<Task> cq = criteriaBuilder.createQuery(Task.class);
// start with the navigation at the task entity
Root<Task> from = cq.from(Task.class);
// join the potential owner organizational entities
Join<Task,OrgEntity> potentialOwners = from.join("potentialOwners");
// select the tasks but remove duplicates
CriteriaQuery<Task> select = cq.select(from).distinct(true);
// definition for subquery1: fetch the user instance
Subquery<User> subquery1 = cq.subquery(User.class);
// start at the User entities
Root<User> from1 = subquery1.from(User.class);
// select the whole user
subquery1.select(from1);
// based on the specified user
subquery1.where(criteriaBuilder.equal(from1, u));
// definition for subquery2: fetch all groups for given user
Subquery<Group> subquery2 = cq.subquery(Group.class);
// we start at the User entity
Root<User> from2 = subquery2.from(User.class);
// join to Group entities via the groups collection
Join<User, Group> groups = from2.join("groups");
// select the group entities only
subquery2.select(groups).distinct(true);
// and finally restrict to all groups of the specified user
subquery2.where(criteriaBuilder.equal(from2, u));
// order in descending order based on the unique task id
select.orderBy(criteriaBuilder.desc(from.get("uuid")));
// here we restrict to those tasks that have the potential
// owners either in the result set of subquery2 or subquery1
// additionally I've tried to filter for another restriction
// in the task (based on a like statement of the uuid)
select.where(criteriaBuilder.and(
criteriaBuilder.or(
criteriaBuilder.in(potentialOwners).value(subquery2),
criteriaBuilder.in(potentialOwners).value(subquery1)),
criteriaBuilder.like(from.<String>get("uuid"), "1%")));
TypedQuery<Task> typedQuery = em.createQuery(select);
List<Task> resultList = typedQuery.getResultList();
I am trying to design my ENTITY CLASSES using JPA annotations.
What I am trying to do is as follows :
A USER table with
id,
***email,
password,
activation_key,
active,
role***
and many TYPES OF USER table with for eg.
STUDENT_TABLE
USER_ID
FirstName
LastName
Company
Address
etc
MENTOR
USER_ID
FirstName
LastNAme
DOB
Department
etc
When USER will register depending o their ROLE they will be sotred in two tables (USER,MENTOR/STUDENT)
When they will log in , the ManagedBean will look into the UESR table to verify the authentication.
I tired to use #OneToOne but It just works with two tables.
I would really appreciate if any1 can help!!
Thanks
If I understand correctly, what you want is an inheritance relationship:
#Entity
#Inheritance(strategy = JOINED)
public abstract class User { ... }
#Entity
public class Student extends User { ... }
#Entity
public class Mentor extends User { ... }
The JOINED strategy tells JPA that the fields in the User class are stored in a table (USER), and that each subclass persists its own field in its own table (STUDENT and MENTOR), with a join column used to refer to the USER table ID.
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