how to write hql query for hibernate OneToMany relationship? - java

I have the following classes laid out like so:
class User {
#Id
private long id;
#OneToMany(fetch = FetchType.EAGER,cascade = CascadeType.ALL)
Set<UserRole> userRoles;
}
class UserRole {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", unique = true, nullable = false)
private int id;
#Column(name = "role", nullable = false, length = 45)
private String role;
}
I'm attempting to query for users that have a specific role (in this case, all users with the role ROLE_ADMIN), using the following query:
org.hibernate.query.Query<User> userQuery=session.createQuery("from User as mc where mc.userRoles in (from UserRole as ur where ur.role in (:uRoles))",User.class);
Set<String> roles = new HashSet<String>();
roles.add("ROLE_ADMIN");
userQuery.setParameterList("uRoles", roles);
List<User> admins = userQuery.getResultList();
However, the query is not returning any results.

session.createQuery(
"from User as user join user.userRoles as userRole where userRole.role in :roles")
.setParameter("roles", Arrays.asList("ROLE_ADMIN"))
.getResultList();

Related

How to join two entities with ManyToMany relationship in the jpa query

I have two entities User and Role. Each user can have multiple roles.
User class
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", updatable = false, nullable = false)
private Long id;
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinTable(
name = "user_role",
joinColumns = #JoinColumn(name = "user_id"),
inverseJoinColumns = #JoinColumn(name = "role_id")
)
private Set<Role> roles = new HashSet<>();
}
Role class:
#Entity
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", updatable = false, nullable = false)
private Long id;
private String name;
}
So a new joined table is being created called: user_role
I want to create a query for returning a list of users with role_id of 4, for example.
The query that I already tried:
#Override
public List<User> getArtists() {
return em.createQuery(
"from User u, Role r where u.roles='4'",
User.class
).getResultList();
}
How can I fix this query in order to retrieve a list of users with role_id of 4?
You can do something like this:
List<User> users = em.createQuery(
"select distinct u from User u join fetch u.roles rl where rl.id = :id",
User.class)
.setHint( QueryHints.HINT_PASS_DISTINCT_THROUGH, false )
.setParameter("id", 1L)
.getResultList();
The QueryHints.HINT_PASS_DISTINCT_THROUGH is added as an additional performance optimization. But please note that this optimization will work only with hibernate 5.2.2.Final ... 5.2.11.Final. It was broken in the 5.2.12.Final.
If I were you, I will get the benfit of using SpringdataJpa with hibernate and just use this statment :
If you don't want to use query :
List<User> findByRoles_Id(Long id);
In your User Repository :
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByRoles_Id(Long id);
}

Criteria from join two tables Hibernate

I have 2 entity
BlackList
public class BlackList {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id", unique = true, nullable = false)
private Integer id;
#ManyToOne
#JoinColumn(name = "applicant_id", unique = true)
private Applicant applicant;
and
public class Applicant {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id", unique = true, nullable = false)
private Integer id;
#Column(name = "number", nullable = false, unique = true)
private String number;
please help me. How create criteria for get me data for this query: select applicant.number from black_list inner join applicant on black_list.applicant_id = applicant.id
public List<BlackList> getAll(){
Session session =sessionFactory.getCurrentSession();
ProjectionList projectionList = Projections.projectionList();
Criteria criteria = session.createCriteria(BlackList.class);
projectionList.add(Projections.property("applicant"));
criteria.setProjection(projectionList);
List res = criteria.list();
return res;
}
this method returned me /id and number/ but i need only number
There are two ways to approach this, you could select the applicants from the black list using hql.Or you could add the inverse join in your applicant, allowing you to 'create alias' and add a 'not null' restriction.

hibernate path expected for join but path is set

I have an hql query:
"from User u inner join UserRole ur on ur.user_name = u.user_name and ur.user_role =ROLE_MANAGER "
And it shows an error though the path is set. I tried different variants of hql but error remains the same. I use those 2 entites for spring security login from db and it works fine. But when i'm trying to get user with specified role it doesn't work.
My entities:
#Entity
#Table(name = "USERS")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "user_id")
private int user_id;
#Column(name = "username", nullable = false, unique = true)
private String username;
#Column(name = "passwort", nullable = false)
private String password;
#Column(name = "email")
private String email = "hromnikforever#gmail.com";
#Column(name = "enabled", nullable = false)
private int enabled = 1;
#Autowired
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private Set<UserRole> userRoles = new HashSet<UserRole>(0);
UserRole entity:
#Entity
#Table(name = "USER_ROLES")
public class UserRole {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "user_id",unique = true, nullable = false)
private int user_role_id;
#Column(name = "username")
private String username;
#Column(name = "user_role")
private String user_role;
If i change my HQL query to:
from User u inner join u.userRole ur on ur.user_name = u.user_name
and ur.user_role =ROLE_MANAGER "
it shows an error that
could not resolve property: userRole of: com.webproject.User [from com.webproject.User u inner join u.userRole ur on ur.user_name = u.user_name and ur.user_role =ROLE_MANAGER ]
Instead explicit JOIN try with comma notation, and change the second JOIN table with UserRole, as follow:
from User u, UserRole ur
where ur.user_name = u.user_name
and ur.user_role = ROLE_MANAGER
If you want only User elements complete your query as follow:
select u from User u, UserRole ur
where ur.user_name = u.user_name
and ur.user_role = ROLE_MANAGER
You have a typo in your query, since your User entity doesn't have a userRole, but userRoles
from User u
inner join u.userRoles ur on ur.user_name = u.user_name
and ur.user_role = ROLE_MANAGER

How to get entities when oneToMany relation contains values using Hibernate Filters

I have User entity:
public class User implements IStandarizedEntity {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id")
private Long id;
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "web.user_role",
joinColumns = {
#JoinColumn(name = "user_id", referencedColumnName = "id")},
inverseJoinColumns = {
#JoinColumn(name = "role_id", referencedColumnName = "id")})
#Size(min = 1, max = 10)
private List<Role> roles = new ArrayList<>();
A a Role entity:
public class Role implements IStandarizedEntity {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id")
private Long id;
#Column(name = "type")
#Enumerated(EnumType.STRING)
private ERole type;
I am using hibernate like a jpa provider. I want to only get users with specific role. I wrote named query to retrieve all users and now I am trying to use #Filter to retrieve only users with specified role type.
What I achieved is that I can retrieve all users and next while loading roles I can load filtered roles list but it is not what I want to do.
You can just filter the role when querying.
For example:
Select u from User u join fetch u.roles r where r.type = :roleType;
Join fetch will return all users with roles matching your filter.

Delete ManyToMany link

I'm newbie in Hibernate and I've a question about it.
I've 3 tables: User, Role and UserRole.
User and Role have ManyToMany relationship mapped by UserRole.
I have 2 rows in Role: (1, ROLE_ADMIN) (2, ROLE_USER).
I have 1 row in User: (1, TESTUSER).
I have 2 rows in UserRole: (1,1)(1,2).
I have 2 Entities: UserEntity and RoleEntity.
I added 2 role to TESTUSER calling method .add( Role ) on UserEntity and after .save( User ) on Session.
I can add all role i want to TESTUSER and it's works!
When i call .remove( Role ) on UserEntity and after .save( User ) on my JPA repository. It doesn't work.
I mean that hibernate doesn't execute any query to delete elements by table UserRole. Why?
Can you help me?
RoleEntity
#Entity
#Table(name = "role" , uniqueConstraints= {
#UniqueConstraint(columnNames={ "role_id" }) ,
#UniqueConstraint(columnNames={ "name" })
})
#Indexed
public
class Role
implements Serializable
{
#ManyToMany( mappedBy="roleList", fetch = FetchType.LAZY )
#Fetch(FetchMode.SELECT)
#BatchSize(size = 100)
private List<User> userList = new ArrayList<>(0);
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "role_id", nullable = false)
private
Long roleId;
#Column(name = "name", nullable = false)
private
String name;
UserEntity
#Entity
#Table(name = "user" , uniqueConstraints= {
#UniqueConstraint(columnNames={ "user_id" }) ,
#UniqueConstraint(columnNames={ "name" })
})
#Indexed
public
class User
implements Serializable
{
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "user_role")
#Fetch(FetchMode.SELECT)
#BatchSize(size = 100)
private List<Role> roleList = new ArrayList<>(0);
#Column(name = "name", nullable = false)
private
String name;
My test code:
Role adminRole = new RuoloBuilder().setName("ROLE_ADMIN").build();
Role userRole = new RuoloBuilder().setName("ROLE_USER").build();
adminRole = roleService.saveOrUpdate(adminRole);
userRole = roleService.saveOrUpdate(userRole);
User user = new UtenteBuilder()
.setName("TESTUSER")
.setRoleList(Arrays.asList(adminRole, userRole))
.build();
user = userService.saveOrUpdate(user); // It works
user.getRoleList().remove(userRole);
userService.saveOrUpdate(user); // It doesn't work
#ManyToMany(fetch = FetchType.LAZY,cascade=CascadeType.ALL) // on the entity User
You have to cascade all the operations PERSIST, REMOVE, REFRESH, MERGE, DETACH to the linked entities (Roles).

Categories