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);
}
Related
I'm trying to write to a Query in JPA,and Query is working fine but result is not correct.
Mapping in User.java
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable( name = "user_roles",
joinColumns = #JoinColumn(name = "user_id"),
inverseJoinColumns = #JoinColumn(name = "role_id"))
private Set<Role> roles = new HashSet<>();
Entity Role.java
#Entity
#Table(name = "roles")
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Enumerated(EnumType.STRING)
#Column(length = 20)
private ERole name;
}
Enum file
public enum ERole {
USER,
GUEST,
ADMIN,
USER_HANDLER,
TOURNAMENT_HANDLER,
CHALLENGE_HANDLER,
CHAMPIONSHIP_HANDLER
}
and Join Query in UserRepository.java
#Query("select u.userId from User u LEFT JOIN Role r ON u.id = r.id AND r.name = 'ADMIN' OR r.name = 'USER_HANDLER'")
List<Long> findSubAdmins();
Result: I'm printing size of List in console
Expected - 5
Getting - 8 (8 is the total no. of record in join table)
#Query("select distinct(u.id) from User u INNER JOIN u.roles r ON r.name IN ('ADMIN', 'USER_HANDLER')")
List<Long> findSubAdmins();
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();
I have following entity:
public final class Stock implements Serializable {
#JsonIgnore
#ManyToMany(mappedBy = "stocks", fetch = FetchType.LAZY)
private Set<User> users = new HashSet<>();
[Other fileds]
[getters/setters]
}
And i would like write query in jpql to get top5 Stock entity based on size of set users. So far i write native query in sql and it looks like:
SELECT s.ticker, COUNT(s.ticker)
FROM t_stock s INNER JOIN t_user_stocks us ON s.id = us.stock_id
INNER JOIN t_user u on us.user_id = u.id GROUP BY s.ticker ORDER BY count DESC
And i want a jqpl query which return top 5 stocks entity. Could someone help me?
Assuming your entity is mapped as follows.
#Entity
public class Stock {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column
private String ticker;
#JsonIgnore
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinTable(name = "stock_user", joinColumns = { #JoinColumn(name = "STOCK_ID", nullable = false, updatable = false) }, inverseJoinColumns = { #JoinColumn(name = "USER_ID", nullable = false, updatable = false) })
private Set<User> users = new HashSet<User>();
}
I did the following using native SQL to get the result.If you insist on using JPQL, the answer here is your friend.
public interface StockRepository extends JpaRepository<Stock, Integer> {
#Query(value = "SELECT s.ticker, COUNT(s.ticker) FROM stock s INNER JOIN "
+ "stock_user us ON s.id = us.stock_id INNER JOIN user u on us.user_id = u.id GROUP BY s.ticker order by count(*) desc limit 1", nativeQuery = true)
public List<Object[]> findStock();
}
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).
My objects: user and credential - many to many relationship, however user has a param
I want to get all users with certain param for every credential in a loop
requirement: users have to be loaded in batch.
simple right?
so i have 3 tables:
#Table(name = "CRED")
public class Credential {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
#Column(name="CRED_ID")
Long credentialId;
#OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "credential")
#BatchSize(size = Search.DEFAULT_PAGE_SIZE)
private Set<UserCredentialMapping> userCredentialMappingSet;
}
#Table(name = "USER_CRED")
public class UserCredentialMapping {
#JoinColumn(name = "user_id", referencedColumnName = "user_id")
#ManyToOne
#Filter(name="paramFilter", condition="param = :param")
private User user;
#JoinColumn(name = "cred_id", referencedColumnName = "cred_id")
#ManyToOne
private Credential credential;
}
#Table(name = "USER")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
#Column(name="USER_ID")
Long userId;
#Column(name = "PARAM")
String param
}
i'm making a query in one place and return results:
String hqlQuery = "select c from UserCredentialMapping m " +
" inner join m.credential c" +
" inner join m.user u" +
" where u.param = :param" +
" and c.user_id in (:users)" ;
Session session = getSession();
//desparetly trying to set filter
session.enableFilter("paramFilter").setParameter("param", param);
Query query = session.createQuery(hqlQuery);
query.setParameterList("users", USERLIST);
query.setParameter("param", someparam);
List<Credential> credentialList = (List<Credential>)query.list();
return credentialList;
some processing on each credential in mean time and now i need to get list of users with given param:
for(Credential credential : credentialList){
//following line makes hibernate query for users
Iterator<CredentialMapping> mappingIterator = e.getUserCredentialMappingSet().iterator();
while (mappingIterator.hasNext()){
UserCredentialMapping userCred = mappingIterator.next();
User user = userCred.getUser();
DOEVILSTUFFTOINNOCENT(user);
}
My problem is that iterator generates SQL query that gets all users for credential and not all users with specified param for credential (in other words filter is not being applied)
Any advise how to make it work?
Thanks !
I've solved it by adding ManyToMany mapping to Credential class:
#ManyToMany(fetch = FetchType.LAZY)
#NotFound(action = NotFoundAction.IGNORE)
#JoinTable(name = "USER_CRED",
joinColumns = {
#JoinColumn(name = "CRED_ID") },
inverseJoinColumns = {
#JoinColumn(name = "USER_ID") })
#Filter(name="param", condition="PARAM = :param")
#BatchSize(size = Search.DEFAULT_PAGE_SIZE)
private Set<User> users;
i couldn't get it working through UserCredentialMapping...