I'm trying to link mysql tables (role, user, user_role).
UserModel entity contains a field 'roles'.
#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;
Role entity contains a field 'users'
#Transient
#ManyToMany(mappedBy = "roles")
private UserModel users;
When i save a user, new rows are automatically created in the table 'roles'. How to cancel duplicate roles?
You are cascading all operations from the UserModel over the roles attribute to entity Role. So whenever you persist a user, it persists its roles as well. Try removing the cascade = CascadeType.ALL or replace the cascading to something less "brute force".
Related
I currently have a problem with this Relationship, I have tried everything I saw on the internet. Still, I get this error: ERROR: column roles0_.user_id does not exist.
I have a boot app that has spring security, and I need to login using users from PostgreSQL database.
But I just can't get the relation between the user and the Role to work.
Here are Entity classes:
#Data
#Entity
#Table(name="user",schema = "public")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "user_id")
private Integer id;
#Column(unique = true)
private String username;
private String password;
private boolean enabled;
#OneToMany(mappedBy = "user", fetch = FetchType.EAGER)
private List<Role> roles;
}
#Data
#Entity
#Table(name="role",schema = "public")
public class Role {
#Id
#Column(name="role_id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
#ManyToOne()
#JoinColumn(name ="user_id")
private User user;
}
The database looks fine, I looked at the column names, etc. I don't know what to do to get rid of this error. I have the user table, and another table named roles, which include id and name, 2 inputs, USER and ADMIN...
It seems that the #JoinColumn annotation requires one additional column in the roles table the one with #ManytoOne relation, because when I add the column the error disappears, but when I'm trying to get the role from each user, I get an empty List. The foreign key is set as well, from the roles column to the role_id column from role table.
worked for me this way:
#Entity
#Data
#Table(name = "users")
public class User{
#ManyToMany(fetch = FetchType.EAGER)
#JoinTable(name = "user_roles", joinColumns = {#JoinColumn(name = "user_id", referencedColumnName = "id")},
inverseJoinColumns = {#JoinColumn(name = "role_id", referencedColumnName = "id")})
private List<Role> roles;
}
and then in roles just:
#Entity
#Table(name = "roles")
public class Role{
#ManyToMany(mappedBy = "roles", fetch = LAZY)
private List<User> users;
}
that's if you are ok with third table user_roles (user_id, role_id) which manages the many to many relation
User table :
#OneToMany(cascade = CascadeType.ALL, mappedBy = "user", fetch = FetchType.EAGER)
private List<Role> roles;
Role table :
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "user_id")
private User user;
So i have a MyUser entity which refers to a Role entity with a many to many relationship.
But when i try to delete the user, i always get the errror that the user_id is always referenced on the user_role jointable...
I have already tried every cascade type... but didn't get the solution
Please help
Thanks
#Table(name = "users")
public class MyUser {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
... Other properties ...
#ManyToMany
#JoinTable(
name = "users_roles",
joinColumns = #JoinColumn(
name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(
name = "role_id", referencedColumnName = "id"))
private Collection<Role> roles;
// getters setters
}
#Entity
#Table(name = "roles")
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String role;
// getters setters
}
As it stated in the documentation:
For #ManyToMany associations, the REMOVE entity state transition doesn’t make sense to be cascaded because it will propagate beyond the link table. Since the other side might be referenced by other entities on the parent-side, the automatic removal might end up in a ConstraintViolationException.
So, before removing Role entity you should be assured that there is no MyUser entity linked with this role.
I am new with Spring jpa and I am trying to perform the deletion operation on spring jpa many to many database. My database has user and drug. I can delete an user and deletes also the rows associated to it from user_drug table, I can delete a drug that has no linking to the user_drug table, but i cannot delete a drug that is also in the user_drug table.
I had a look on this page but the solutions from there do not work for me.. How to remove entity with ManyToMany relationship in JPA (and corresponding join table rows)?
Here is my code for User entity:
#ManyToMany(cascade = CascadeType.ALL, fetch=FetchType.EAGER)
#JoinTable(name = "user_drug",
joinColumns = #JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(name = "drug_id", referencedColumnName = "id"))
private Set<Drug> drugs = new HashSet<>();
Here is the code for Drug entity:
#ManyToMany(mappedBy = "drugs", fetch=FetchType.EAGER)
private Set<User> users = new HashSet<>();
And here is the delet method from DrugServiceImpl:
public void delete(Drug drug)
{
drug.getUsers().clear();
drugRepository.delete(drug);
}
I have also printed the size of drug.getUsers() after clear operation and it is 0. Why isn't it delete the drug from database?
I've tried in many ways.. Can someone please send some help?
that is how the cascade works it deletes from the relation table only and in the ManyToMany the relation table here is the user_drug table
and for this cases there are many solution one of them is deleting the drug in the same transaction of the deleting user
but another solution that will save the effort that you create the ManyToMany table as entity and put cascade on the drug object in the relation table
like this
But this in the User entity
#ManyToMany(cascade = CascadeType.ALL, fetch=FetchType.EAGER, mappedBy="user")
private Set<UserDrug> drugs = new HashSet<>();
the UserDrug entity
public class UserDrug {
#ManyToOne
#JoinColumn(name="user_id")
User user;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name="drug_id")
Drug drug;
}
When I am trying to delete Role from the roles table with the help of Hibernate using its id it occurs an exception:
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`ewp`.`permissions`, CONSTRAINT `FK_sq51ihfrapwdr98uufenhcocg` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`))
Class User
...
#NotNull
#ManyToMany(fetch = FetchType.EAGER, targetEntity = Role.class)
#JoinTable(name = "permissions",
joinColumns = {#JoinColumn(name = "user_id")},
inverseJoinColumns = {#JoinColumn(name = "role_id")})
private Set<Role> roles;
...
Class Role
...
#ManyToMany(fetch = FetchType.EAGER)
private List<User> users;
...
When I add to Role
#JoinTable(name = "permissions",
joinColumns = {#JoinColumn(name = "role_id")},
inverseJoinColumns = {#JoinColumn(name = "user_id")})
private List<User> users;
Roles deleted without exceptions.
But I think that it can work without mapping in Role.
You either need to determine which side of the Many-To-Many owns the relationship or make sure that you alter both sides prior to removing the associated Role objects.
As mentioned in the comments, you can imply ownership by adding a mappedBy attribute to either side of the relationship. By adding mappedBy="roles" to the Role entity, this will tell the persistence provider that the relationship is managed by the User object's roles property and thus to manipulate the relationship using its join-table mapping.
I am trying to setup and Many to Many relationship between users and roles. I am mostly using JPA Repositories but I also tried using and EntityManger.
I have the following in my main User object.
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "svcAuthUserRolev2", schema="dbo", joinColumns = {
#JoinColumn(name = "user_id", updatable=false,insertable=false, nullable = false) },
inverseJoinColumns = { #JoinColumn(name = "role_id",
updatable=false,insertable=false, nullable = false) })
private Set<AuthRoleEntity> roles;
And the following in my Roles object
#ManyToMany(fetch = FetchType.LAZY, mappedBy = "roles")
private Set<AuthUserEntity> users;
No matter what I do if I make changes to the roles on a user when saving they are persisted and this is not what I would like. I want roles on the user object to be read only.
I'm not sure why updateable and insertable are not working, I haven't used those attributes much. One possible solution is to make AuthRoleEntity the owning entity of the many-to-many relationship. Just move the #JoinTable annotation to the AuthRoleEntity and put the mappedBy on the AuthUserEntity.