JPQL for Entities with No Items in ManyToMany Relationship - java

Simple JPA/JPQL question. I have an entity with a ManyToMany relationship:
#Entity
public class Employee {
#ManyToMany
#JoinTablename="employee_project"
joinColumns={#JoinColumn(name="employee_id"}
inverseJoinColumns={#JoinColumn(name="project_id"})
private List<Project> projects;
What is the JPQL query to return all the Employees that do not have any projects?

from Employee e where not exists elements(e.projects)
or
from Employee e where size(e.projects) = 0

JQPL does have dedicated IS [NOT] EMPTY comparison operator for checking is collection empty:
SELECT e FROM Employee e WHERE e.projects IS EMPTY

Related

How to conditionally WHERE populated foreign keys with OneToMany Entity?

I am assuming a setup as described in: https://howtodoinjava.com/hibernate/hibernate-one-to-many-mapping-using-annotations/
Employee:
#JoinColumn(name="EMPLOYEE_ID")
private Set<AccountEntity> accounts;
Account:
#ManyToOne
private EmployeeEntity employee;
Using JPA/Hibernate, how can I fetch results using a WHERE condition that applies to Account. In other words, query something like Select all employees with accounts with sales > 0 or similar.
I'm assuming sales column as INT in account table.
you can write a query like following:
TypedQuery<Employee> query = em.createQuery("SELECT e FROM Employee e JOIN Account a ON e.id = a.accounts.employee_id WHERE a.sales > :sales", Employee.class);
query.setParameter("sales", salesInput);
List<Employee> items = query.getResultList();
I would recommend you to go through this tutorial to learn about CRUD operations in Hibernate Associations
https://www.dineshonjava.com/spring-crud-example-using-many-to-one/

Spring JPA intersect two list fields of an entity

I have a entity called A which has one property userGroups:
#entity
Public class A {
#OneToMany
#JoinTable(name = "a_user_groups", ...)
private Set<UserGroup> userGroups;
...
}
I need to find those A entities which their userGroups has no intersection with given Set<UserGroup> userGroups parameter.
This is my method:
#Query("SELECT a FROM A a WHERE :userGroups intersect a.userGroups is NULL")
List<A> getAWithNoIntersectionInGroups(#param("userGroups") Set<UserGroup> userGroups)
But there is no intersect keyword in jpa.
Not In keyword not works here:
Suppose there is an A entity with user groups ids {1,3} and my passed user group ids are {3,4}, Now {1,3} is not in {3,4} and it's true and entity will be selected, but it shouldn't selected, because there is a mutual item {3}
You can use NOT IN SQL clause instead intersect.
#Query("SELECT a FROM A a WHERE a.userGroups not in (:userGroups)")
List<A> getAWithNoIntersectionInGroups(#param("userGroups") Set<UserGroup> userGroups)

Hibernate DetachedQuery and Spring's HibernateTemplate with Restriction giving wrong results

My data structure is like this
Department
-> Employees
-> Gender
-> CityID -> Cities
->CityID
->CountryID -> Countries
-> CountryID
Department Class:
public class Department {
#OneToMany(mappedBy = "departmentid", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Set<Employee> employees = new HashSet<>();
}
I build Crteria like this:
DetachedCriteria criteria = DetachedCriteria.forClass(Department.class);
DetachedCriteria detlCrit = criteria.createCriteria("employees");
detlCrit.add(Restrictions.eq("gender", "MALE"));
detlCrit.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
I have 1 Department, 2 Employees in the Tables (1 male, 1 female).
When I excecute this criteria iam expecting Hibernate build one 'Department' object, one 'Employee' object, and city, country etc.,
But what iam getting is 1 Department, 2 Employees.
When I see the queries executed by Hibernate in logs, it shows two queries
First Query:
Select * from Department, Employee
Left outer join City on Employee.cityID = City.cityID
Left outer join Country on City.countryID = City.countryID
Where Employee.DeptID = Department.DeptID
AND Employee.Gender = 'MALE';
Second query:
Select * from Employee
Left outer join City on Employee.cityID = City.cityID
Left outer join Country on City.countryID = City.countryID
Where Employee.DeptID = Department.DeptID;
Second query is wrong there is no Restriction applied on Gender='MALE';
What iam doing wrong? any suggestions? how to solve this?
sorry queries may be not exactly correct, but you got the idea.
Any more details needed please ask, I can provide.
Thanks in advance..
Try this,using SessionFactory.
#Autowired
private SessionFactory sessionFactory;
Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Department.class);
criteria.add(Restrictions.eq("gender", "MALE"));
Hope I was useful.
The first query is selecting Department entities and the filtering is applied as you specified in your where clause.
But you cannot truncate associations, you always have to fetch them all eagerly or lazily. That's because Hibernate has to maintain consistency guarantees when flushing back the loaded Department entity and possibly cascading the employees state back to the database.
The second query is most likely because you use a FetchType.EAGER on your employees collection:
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "department", orphanRemoval = true)
private List<Employee> employees = new ArrayList<>();
Once the Department is fetched, the employee collection is fetched eagerly as well.
Try with an HQL query liken this one:
select distinct d
from Department d
left join fetch d.employees e
where e.gender = :gender

Hibernate: Populating UnMapped Component via HQL

Class A and Class B are entities mapped to their own database tables. Class C is NOT mapped and contains all the attributes of A and B. Is it possible to build a HQL to populate C?
Yes, you can. You can use Hibernates ResultTransformer for this:
List resultWithAliasedBean = s.createQuery(
"select e.student.name as studentName," +
" e.course.description as courseDescription" +
"from Enrolment as e")
.setResultTransformer( Transformers.aliasToBean(StudentDTO.class))
.list();
StudentDTO dto = (StudentDTO) resultWithAliasedBean.get(0);

How to select childs from a superclass?

I have a basic JPA mapping with a superclass containing a list.
How can I select all List row entries from the database for a specific person?
class Person {
#Id
int id;
#OneToMany
List<Payment> payments;
}
//SELECT <all payments> from Person p WHERE p.id = 1
You can simply do SELECT person.payments FROM Person person JOIN person.payments WHERE person.id = ?.
You would cast the return list() to a List<Payment>

Categories

Resources