My question is about how to retrieve association data in DAO.
I have 3 tables: user, role and user_role. user_role is the association table of user and role.
create table user (user_id varchar(50) not null primary key, password varchar(50) not null)
create table role (role_id int not null primary key, role_name varchar(50) not null)
create table user_role (user_role_id int not null primary key, user_id varchar(50) not null, role_id int not null)
I have 2 classes: User and Role. User has a roles property which is List of objects of Role type.
public class User {
private String userId;
private String password;
private List<Role> roles;
public String getUserId() { return this.userId; }
public void setUserId(String userId) { this.userId = userId; }
public String getPassword() { return this.password; }
public void setPassword(String password) { this.password = password; }
public List<Role> getRoles() { return this.roles; }
public void setRoles(List<Role> roles) { this.roles = roles; }
}
public class Role {
private int roleId;
private String roleName;
public int getRoleId() { return this.roleId; }
public void setRoleId(int roleId) { this.roleId = roleId; }
public String getRoleName() { return this.roleName; }
public void setRoleName(String roleName) { this.roleName = roleName; }
}
Now I am trying to build DAOs and getting confused on how to populate roles property of User class.
I think I need these DAO methods for User class:
1) User getUserMethod1(String userId) - retrieve a row from user table for a specific user_id. Dont populate roles property of User class.
2) User getUserMethod2(String userId) - retrieve a row from user table for a specific user_id. Also populate roles property of User class.
3) void updateUser(String userId) - update a row in user table for a specific user_id.
4) void deleteUser(String userId) - delete a row in user table for a specific user_id.
I think I need these DAO methods for Role class:
1) Role getRole(int roleId) - retrieve a row from role table for a specific role_id.
2) List<Role> getAllRoles() - retrieve all rows from role table.
3) void updateRole(int roleId) - update a row in role table for a specific role_id.
4) void deleteRole(int roleId) - delete a row in role table for a specific role_id.
Out of the above 8 DAO methods I am having issue with User getUserMethod2(String userId) method.
I can retrieve 1 row from user table for the specific user_id; then retrieve all role_id associated to that specific user_id from user_role table.
But then do I have to loop through them and call Role getRole(int roleId) method of Role class for each role_id?
If yes then how can I get a hold of that method? If not then what is the solution?
Is there a better way to solve this issue then calling Role getRole(int roleId) method of Role class for each role_id?
Thank you for reading this question.
If you have set your hibernate.cfg properly, you must have that one-to-many associations to associate your set in the user class.
<set name="role" table="role" inverse="true" lazy="true" fetch="select">
<key>
<column name="role_id" />
</key>
<one-to-many class="com.model.Role" />
</set>
Anyways, if this has been done correctly, you can enable lazy loading to not bring sets and only bring them when you try and access them. Note that you will have to keep the session open for lazy loading to work.
For question 2: you can use "fetch" in your hibernate query to specify eager loading of your set.
You can use criteria API or HQL to handle cases like to bring users who have no roles associated with them.
Related
I have following tables:
user
- id BIGINT
- name VARCHAR
user_roles
- id BIGINT
- user_id BIGINT - FK TO USER
- name VARCHAR (name of the role)
so by using this we can assign multiple roles to user. In Java there is UserRole enum. How can I load in Hibernate user records with assigned roles?
I have following code
private Set<UserRole> userRoles;
#ElementCollection(targetClass=UserRole.class)
#Enumerated(EnumType.STRING)
#CollectionTable(name="user_role")
#Column(name="name")
public Set<UserRole> getUserRoles() {
return userRoles;
}
public void setUserRoles(Set<UserRole> userRoles) {
this.userRoles= userRoles;
}
and I make the query like this:
CriteriaBuilder criteriaBuilder = sessionFactory.getCurrentSession().getCriteriaBuilder();
CriteriaQuery<User> criteriaQuery = criteriaBuilder.createQuery(User.class);
Root<User> queryRoot = criteriaQuery.from(User.class);
queryRoot.join("userRoles", JoinType.LEFT);
TypedQuery<User> query = sessionFactory.getCurrentSession().createQuery(criteriaQuery);
return query.getResultList();
Query runs but when I try to access the roles Set it says
com.sun.jdi.InvocationException occurred invoking method.
What am I doing wrong?
I am creating a web application only using Java and not any framework.
I am at this point where I have to get data from the Database. I am doing this using DAO pattern but I have a problem to understand some logic about relationships (one-to-one, one-to-many, and many-to-many).
To understand my problem better I will explain by taking an exact example.
I have two entities (tables) in the database User and Role. The entity User has attributes id, name, lastname, username, and password, and the table Role has attributes id, role, description.
From this I have the relation that one User can have more than one Role (so a user can be both a simple user and an admin of the web app), and one Role can be in many User. From this point I creat another table tha represents many-to-many relationship named UserRoles that has attributes user_id, role_id.
Now in Java I have a class named `User:
public class User
{
private int id; (with getters and setters)
private String name; (with getters and setters)
private String lastname; (with getters and setters)
private String username; (with getters and setters)
private String password; (with getters and setters)
// and two constructors with and without parameters together with toString method
}
and the interface named UserDAO:
public interface UserDAO
{
public User find(intid);
public User find(String email, String password);
public List<User> users();
public void create(User user);
public void update(User user);
public void delete(User user);
public boolean existEmail(String email);
public void changePassword(User user);
}
I have the class for manipulation with MySQL queries named UserDAOJDBC:
public class UserDAOJDBC implements UserDAO
{
private static final String FIND_BY_ID = "SELECT * FROM user WHERE id=?";
#Override
public User find(int id) {
return find(FIND_BY_ID, id);
}
private User find(String sql, Object... values){
User user = null;
try {
ResultSet resultSet = DBConnectionPool.executeQuery(sql, values);
if(resultSet.next()){
user = new User();
user.setId(Integer.parseInt(resultSet.getString("id")));
user.setName(resultSet.getString("name"));
user.setLastname(resultSet.getString("lastname"));
user.setUsername(resultSet.getString("username"));
user.setPassword(resultSet.getString("password"));
}
DBConnectionPool.getConnection().close();
} catch (Exception e) {
System.out.println(e);
}
return user;
}
}
Now when I want to get Role for one User what is a better practice?
So far I have this solution:
1) I have to include Role in the User class:
public class User
{
private int id; (with getters and setters)
private String name; (with getters and setters)
private String lastname; (with getters and setters)
private String username; (with getters and setters)
private String password; (with getters and setters)
private List<Role> roles; (with getters and setters)
// and two constructors with and without parameters together with toString method
}
and create in class UserDAOJDBC a method named findWithRoles that makes the join with the tables as:
SELECT * FROM user AS u INNER JOIN userroles as ur ON u.id = ur.user_id
and then the second query that goes through results of the previous one:
SELECT * FROM role AS r INNER JOIN userroles as ur ON r.id = ur.role_id
and from the ResultsSet of this query to populate the array List<Role> roles.
You don't need to include Role into the User class (even though you can). It is enough to create the UserRoles table and read the data from it. You should probably create UserRolesDAO class that will implement all the methods for you to find all the roles of a specific user, and all the users to specific role, as well as save new user, role combination and read it back.
I have an example on github where I combined Students and Courses in exactly same way using JDBC and DAO pattern so feel free to take a look.
Blog post about dao
I am developing an app where the user can have one or more roles, for this I decided to created a mapping (intermediate) table, so I ended with User, Role and UserRole like this:
In this app the role(s) a user has determines wheneaver he can access certain views or actions in the frontend. The only thing I need is to retrive the roles a user has and add/delete them. JPA Tools created he following EJB for me (simplified):
USER
/**
* The persistent class for the usuario database table.
*
*/
#Entity
#NamedQuery(name="Usuario.findAll", query="SELECT u FROM Usuario u")
public class Usuario implements Serializable {
private static final long serialVersionUID = 1L;
private int idUsuario;
private List<RolUsuario> rolUsuarios;
public Usuario() {
}
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
public int getIdUsuario() {
return this.idUsuario;
}
public void setIdUsuario(int idUsuario) {
this.idUsuario = idUsuario;
}
//bi-directional many-to-one association to RolUsuario
#OneToMany(mappedBy="usuario")
public List<RolUsuario> getRolUsuarios() {
return this.rolUsuarios;
}
public void setRolUsuarios(List<RolUsuario> rolUsuarios) {
this.rolUsuarios = rolUsuarios;
}
public RolUsuario addRolUsuario(RolUsuario rolUsuario) {
getRolUsuarios().add(rolUsuario);
rolUsuario.setUsuario(this);
return rolUsuario;
}
public RolUsuario removeRolUsuario(RolUsuario rolUsuario) {
getRolUsuarios().remove(rolUsuario);
rolUsuario.setUsuario(null);
return rolUsuario;
}
}
USER_ROLE
/**
* The persistent class for the rol_usuario database table.
*
*/
#Entity
#Table(name="rol_usuario")
#NamedQuery(name="RolUsuario.findAll", query="SELECT r FROM RolUsuario r")
public class RolUsuario implements Serializable {
private static final long serialVersionUID = 1L;
private int idRol_Usuario;
private Usuario usuario;
private Rol rol;
public RolUsuario() {
}
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
public int getIdRol_Usuario() {
return this.idRol_Usuario;
}
public void setIdRol_Usuario(int idRol_Usuario) {
this.idRol_Usuario = idRol_Usuario;
}
//bi-directional many-to-one association to Usuario
#ManyToOne(fetch=FetchType.LAZY)
public Usuario getUsuario() {
return this.usuario;
}
public void setUsuario(Usuario usuario) {
this.usuario = usuario;
}
//bi-directional many-to-one association to Rol
#ManyToOne(fetch=FetchType.LAZY)
public Rol getRol() {
return this.rol;
}
public void setRol(Rol rol) {
this.rol = rol;
}
}
In my project I am using the EJB to create POJO for the frontend. When I ask for the full list of roles for a given user how should I go about doing this:
Create a UserRole repository using CrudRepository with a metod like
List<RolUsuario> findByUsuario(Usuario user);
Return the list of UserRole to my User Service and go over the
the list extracting each Role into a UserPOJO
Send to frontend.
Or is there any way to just get right off the bat a list of Roles in table UserRole where User(Id?) = something?
This is hard to describe for me. My app only cares for the roles of a user, not the mapping table entity, so the botton line is that somehow I have to get them but I don't know where to start.
Any pointers would be extremely useful.
Edit:
Or I could...
Create UserRole for new role addition to a user.
Adding UserRole to the List inside User.
To get the roles of a user get the UserRolelist instead.
Your schema for User and Role is not commonly used. I advice to you make a #ManyToMany association from a user to roles. If you will need to map a join table to the entity (unlikely) you can do it later. And, please, use English identifiers and Java naming convention (idRol_Usuario). It will help you and others.
#Entity
#Table
public class User {
#Id
#GeneratedValue
private Long pid;
#ManyToMany(fetch = FetchType.LAZY)
private List<Role> roles;
}
#Entity
#Table
public class Role {
#Id
private Long pid;
#Column
private String name;
}
You can use Set<Role> too
#ManyToMany(fetch = FetchType.LAZY)
private Set<Role> roles;
The roles of a User and in the rolUsuarios list. In your User service, look up a user, often with the id. If you have the idUsuario, then user EntityManger.find(Usuario.class, idUsuario) and you can read the user roles by getRolUsuarios, or at least that would be the typical way to do it.
In your table design you have a id for the user_role table (iduserrole), which is not typical for a join table. Typically, you just create your entity with a OneToMany annotation and the join table is created for you:
#Entity
public class User {
#Id #GeneratedValue private Long id;
#ManyToMany
Set<Role> roles;
}
and
#Entity
public class Role {
#Id #GeneratedValue private Long id;
}
These two classes would create three tables, the User table, the Role table, and the User_Role Join Table. The join table would have the each id from the user and the role tables in it, and nothing more.
EDIT: The roles is changed to ManyToMany because otherwise a constraint will be added to the database that will prevent the a Role from being added to more than one user. Typically the role table has only unique roles in it, e.g., USER, ADMIN, etc., and so you want to be able to assign them to more than one user.
Is this what you are looking for?
How to decide if a separate entity and DAO is needed for an association table?
Suppose I have 3 tables: user, role and user_role. user_role is the association table.
create table user (user_id int not null primary key, login varchar(50) not null unique key, password varchar(100))
create table role (role_id int not null primary key, description varchar(100))
create table user_role (user_role_id int not null identity(1,1) primary key, user_id int not null foreign key references user(user_id), role_id int not null foreign key references role(role_id))
Now I will have separate entities and DAOs for user and role tables.
public class User {
private int userId;
private String login;
private String password;
// getters and setters
}
public interface UserDAO {
User getUserById(int userId);
void insertUser(User user);
void updateUserById(User user);
void deleteUserById(User user);
}
public class Role {
private int roleId;
private String description;
// getters and setters
}
public interface RoleDAO {
User getRoleById(int roleId);
void insertRole(Role role);
void updateRoleById(Role role);
void deleteRoleById(Role role);
}
I will have 3 screens:
Screen 1: I will have a screen to maintain CRUD operations on user table.
Screen 2: I will have a screen to maintain CRUD operations on role table.
Screen 3: I will have a screen where users will be assigned to roles.
But I am confused about how to tackle the user_role table.
a) Should User entity have a list of associated Role. And thats enough?
public class User {
private int userId;
private String login;
private String password;
private Set<Role> roles;
// getters and setters
}
b) Should Role entity have a list of associated User. And thats enough?
public class Role {
private int roleId;
private String description;
private Set<User> users;
// getters and setters
}
c) Should I have a separate entity and DAO for user_role table like this:
public class UserRole {
private int userRoleId;
private User user;
private Role role;
}
public interface UserRoleDAO {
User getUserRoleById(int userRoleId);
void insertUserRole(UserRole userRole);
void updateUserRoleById(UserRole userRole);
void deleteUserRoleById(UserRole userRole);
}
I guess as it a bidirectional relationship between user and roles you should have to have set of roles in User.java and set of users in Roles.java. An separate entity user_roles is definitely required. If you have dao for user you can have below methods in userdao
User getUserRoleById(int userRoleId);
void insertUserRole(UserRole userRole);
void updateUserRoleById(UserRole userRole);
void deleteUserRoleById(UserRole userRole);
I have a user class, users should have a list of friends. Friends are also users so every user should have many friends and obviously each of those friends(users) also have many friends(users).
So a many-to-many relationship of users is what I've assumed so far. This is currently the code I have been using (with hibernation JPA annotations)
Here is my MyUser code:
#Entity
public class MyUser {
#Id
private String username;
private String userPassword;
#ManyToMany
#JoinTable(
name="USR_USR",
joinColumns={#JoinColumn(name="USR1_ID", referencedColumnName="USERNAME")},
inverseJoinColumns={#JoinColumn(name="USR2_ID", referencedColumnName="USERNAME")})
private List<MyUser> friends = new ArrayList<MyUser>();
public void setUsername(String username) {
this.username = username;
public void setUserPassword(String userPassword) {
this.userPassword = userPassword;
}
public String getUsername() {
return username;
public String getUserPassword() {
return userPassword;
}
public void setFriends(List<MyUser> friends) {
this.friends = friends;
}
public List<MyUser> getFriends() {
return friends;
}
I'm trying to create a second table by joining the USERNAME column with itself (which doesn't really sound right to me I'll be honest.)
So I'm trying to create a relationship in my database where each MyUser can have many MyUser's.
I'm pretty stuck with this so some help would be appreciated.
Thanks a lot!
I would suggest changing your database schema to something like this:
MyUser(id, ....);
Friends(id1, id2);
Where MyUser.id is the primary key of MyUser, and Friends id1 and id2 are foreign keys to MyUser.id.
This is a pretty common pattern that will give you less problems in the future, and is a bit more maintainable. User A (w/ ID 1) is friends with User B (w/ ID 2) if there is a tuple in the Friends database (1, 2).
Hope that helps,