Inner join using HQL - java

I am trying to inner join two tables on one column.
From DB side, there's no mapping as it's something I don't want to discuss.
I want to execute HQL query using INNER JOIN and retrieve ROLE objects/results.
Here's my hql so far
session.createQuery("from ROLE as role INNER JOIN INVOLVEMENT as involvement ON role.id = involvement.roleid WHERE involvement.id = X").list();
I see ON is not available on HQL. how do i explicitly tell Hibernate to JOIN on this column only.
I tried below one too
select roleSpec from ROLE as role, INVOLVEMENT as involvement WHERE role.ID = involvement.role_id and involvement.id =27251352
But I am getting ROLE not mapped in exception.

Please check that your ROLE is indeed a mapped entity.
In addition, you don't need to perform "ON" - hibernate knows what is the join column (I know how to define this at JPA ) - so no need to provide it at the statement.
It should be -
session.createQuery("from Role as role INNER JOIN Involvement as involvement WHERE involvement.id = X").list();
I assume you have Role class mapped to ROLE table, and Involvement class mapped to Involement table.
Maybe you used table names by mistake, and this is why you get the "not mapped" error.
Last time I wrote HQL (and not JPA-QL) I used the following link as reference, it provides all the info needed.

Related

QueryDSL, specify projection for join

I'm trying to use QueryDSL to fetch a collection of entities (table Category) where each entity has a #OneToMany association with an other type of entity (table User), and a join is used to get it all in one go.
Problem is that the second entity (the users) contains CLOB fields which should not be included. I don't want to include them in my query. Given the following QueryDSL query :
JPAQuery<CategoryEntity> baseQuery = new JPAQuery<>(entityManager)
.select(QCategoryEntity.categoryEntity)
.from(QCategoryEntity.categoryEntity)
.leftJoin(QCategoryEntity.categoryEntity.users, QUserEntity.userEntity)
.where(somePredicate);
QueryDSL will generate something like
SELECT categoryen0_.id, (...), useren0_.id, (...)
FROM category categoryen0
LEFT OUTER JOIN user useren0 ON ...
WHERE ...
How can a specific projection be applied to this query such that the CLOB data is excluded?
Notes :
I'm trying to avoid native queries and changing the domain model.
I have not found a way to use Projections on the join
itself.
Using subqueries inside joins is not supported by JPQL hence
it's not supported by QueryDSL either.
Turns out this was not working well due to my use of fetch joins, which prevented me from using projections. Solving it was a matter of using a basic join instead and manually reconstructing the relationship.
Collection<Tuple> tuples = new JPAQuery<>(entityManager)
.select(QCategoryEntity.categoryEntity, Projections.constructor(UserEntity.class, <constructor arguments>)
.from(QCategoryEntity.categoryEntity)
.join(QCategoryEntity.categoryEntity.users, QUserEntity.userEntity)
.where(somePredicate);

JPA ManyToMany retreive 2 lists in one query

I need your help.
I've 2 tables with a join table to get ManyToMany relationship as below :
Table schema
In JAVA with JPA, I'm able for one User to get List<Group>, or for a Group to get List<User>.
Is there a way to get one entity with List<User> AND List<Group> like you can do with SQL :
SELECT * FROM USER_GROUP
INNER JOIN USERS ON USERS.ID = USER_GROUP.USER_ID
INNER JOIN GROUPS ON GROUPS.ID = USER_GROUP.GROUP_ID
WHERE USERS.USER_NAME LIKE ....
Thx all for your help :)

When use a JoinType in Criteria ? Hibernate mapping

I'm a bit confused about when use a join with Criteria. Example of what I'm talking about:
.createAlias("cars", "c", JoinType.LEFT_OUTER_JOIN)
Here are the different JoinType:
LEFT_OUTER_JOIN
INNER_JOIN
LEFT_OUTER_JOIN
NONE
RIGHT_OUTER_JOIN
When we map entities with Hibernate there is already a "JoinType" automatically (is that an INNER_JOIN ?).
Simple example with user - car:
User class (table name USERS)
class User {
#Id
#Column(name="ID_USER")
private int idUser;
#Column(name="NAME")
private String name;
#OneToMany
#JoinColumn(name="ID_USER")
private Set<Car> cars;
}
And Car class (table name CARS):
class Car{
#Id
#Column(name="ID_CAR")
private int idCar;
#Column(name="MODEL)
private String model;
#Column(name="ID_USER")
private int idUser;
}
If I have a user u and i type u.getCars() which Join is it mapped by default ?
If I want for example results of:
SELECT * FROM Users u LEFT JOIN Cars c on u.id_user = c.id_user
Then is that correct to use that :
Criteria c = getSession().createCriteria(User.class);
c.createAlias("cars", "c", JoinType.LEFT_OUTER_JOIN);
return c.list();
(And then I loop on User and Car to search what I'm looking for).
And if I'm looking for that:
SELECT * FROM Users u INNER JOIN Cars c on u.id_user = c.id_user
Am I right saying I have no need to create a JoinType.INNER_JOIN ?
If I'm, JoinType.INNER_JOIN is useless when I already have map entites ?
I have to map a lot of complex tables using a lot of join and I'm a little muddled !
When we map entities with Hibernate there is already a "JoinType" automatically (is that an INNER_JOIN ?).
Assuming you have marked the oneToMany association as Fetch.EAGER. In that case when you load User object via hibernate criteria, it uses LEFT OUTER JOIN by default, unless you override it in Criteria. If you have not marked it as FetchType.EAGER, it will be lazy and so no join by default, again, unless you override it in Criteria.
If I have a user u and i type u.getCars() which Join is it mapped by default ?
For EAGER loading refer above. If lazy and it is within the same session you are calling u.getCars, it will fire a new SELECT to load cars based on the userId and so no join.
Am I right saying I have no need to create a JoinType.INNER_JOIN ? If I'm, JoinType.INNER_JOIN is useless when I already have map entites ?
Refer above, by default it is LEFT OUTER JOIN if it is EAGER and unless overidden in Criteria.
On suggestion, - It would be good idea to view the SQLs that hibernate is actually firing in the background via enable show_sql property with different FetchTypes and Criteria JOIN Types, because based on your entiy mappings the count/complexity of SQL queries might be different.

How to create a JPAQL to pull a tree of parent with multiple children collections and avoid Hibernate Illegal attempt to dereference collection

I am trying to mimic a eager fetch for a specific situation only.I use spring-data-jpa with hibernate 4.1 as implementation. i have User, Role and Right. Role and User have many-to-many with additional field thus mapped as an Entity RoleUser. Role and Right also are in many-to-many mapped as an Entity RoleRight.
I would like to load all right and role for a user into the Authorization mechanism of the application when needed. this query below is giving illegal attempt to dereference collection
List<Role> roles = (List<Role>)em.createQuery("select r from RoleImpl r JOIN FETCH r.roleRightMap rrm JOIN FETCH rrm.right ur WHERE r.userRoleMap.user.ID=:id ")
.setParameter("id", ID).getResultList();
How can it be rewritten to load the role and its mapping thanks.
Sorry, Never mind. it was an oversight.
The query should have been like this :
select r from RoleImpl r LEFT JOIN FETCH r.roleRightMap rrm LEFT JOIN FETCH r.userRoleMap urm WHERE urm.user.ID=:id

Querying many to many association where the entity doesn't have a certain value using Hibernate Criteria API

I got two classes User and Role which are mapped to each other using a many to many associations. Now I'm trying to query all users which doesn't have a certain role using the Hibernate Criteria API. But I'm a little bit stuck.
To query users with a certain role I use the following query, which works just fine.
Session session = getSessionFactory().getCurrentSession();
Criteria mainCrit = session.createCriteria(boClass);
return mainCrit.createAlias("roles", "r").add( Restrictions.eq("r.name", roleName)).list();
Now I'm a little bit confused how to reverse the query and get all user that don't have a certain role. If possible I want to explicit exclude a certain role and don't query for all roles chaining them with OR as there may be more roles added later dynamically.
UPDATE
To get a better understanding of my scenario you can see the association I'm trying to query in another question.
Furthermore I would also add that the name property of the Role class is an Enum, don't know if this is important or changes the way to query the database.
There's perhaps a more elegant way, but the only one I've found is to query for all the users for which there doesn't exist any role in the user's roles which has the given role name.
This is done like this:
Criteria c = session.createCriteria(User.class, "user");
DetachedCriteria roleOfUserWithName = DetachedCriteria.forClass(Role.class, "role");
roleOfUserWithName.createAlias("role.users", "userOfTheRole");
roleOfUserWithName.add(Restrictions.eqProperty("userOfTheRole.id", "user.id"));
roleOfUserWithName.add(Restrictions.eq("role.name", roleName);
roleOfUserWithName.setProjection(Projections.id());
c.add(Subqueries.notExists(roleOfUserWithName));
It's equivalent to the following HQL query:
select user from User user where not exists (
select role.id from Role role inner join role.users userOfTheRole
where userOfTheRole.id = user.id
and role.name = :roleName);

Categories