Issue
I have an issue with this error, I want to delete the specific data from join table role_access, but delete random data inside the table. I applied many to many mapping which consist of role, access and linked table role_access. i have tried remove() using iterator but doesn't worked.Anyone please help me, thank you.
Here I share my code:
Role.java
@ManyToMany(fetch = FetchType.EAGER, cascade = { CascadeType.REFRESH, CascadeType.MERGE, CascadeType.REMOVE,
CascadeType.PERSIST })
@JoinTable(name = "role_access", joinColumns = {
@JoinColumn(name = "roleId", referencedColumnName = "rid") }, inverseJoinColumns = {
@JoinColumn(name = "accessId", referencedColumnName = "id") })
private List<Access> access = new ArrayList<>();
RoleController.java
@PostMapping("/delete/access/{roleName}")
public ResponseEntity<Object> deleteRoleAccess(@PathVariable String roleName) {
return roleService.deleteRoleToAccess(roleName);
}
RoleRepository.java
@Repository
public interface RoleRepository extends JpaRepository<Role, Long> {
Optional<Role> findByRoleName(String roleName);
Optional<Role> findByRid(Long rid); }
RoleService.java
public ResponseEntity<Object> deleteRoleToAccess(String roleName) {
if (roleRepository.findByRoleName(roleName).isPresent()) {
Role r = roleRepository.findByRoleName(roleName).get();
for (int i = 0; i < r.getAccess().size(); i++) {
if (accessRepository.findByAccName(r.getAccess().get(i).getAccName()).isPresent()) {
Access access = r.getAccess().get(i);
delAccess(r, access.getAccName());
} else
return ResponseEntity.unprocessableEntity().body("Role name not found");
}
roleRepository.save(r);
}
return ResponseEntity.ok("access is successfully delete");
}
public void delAccess(Role role, String accName) {
Optional<Access> aOpt = accessRepository.findByAccName(accName);
if (!aOpt.isPresent()) {
throw new CustEmailNotFoundexception("Access name cannot be null");
}
if (aOpt.isPresent() && aOpt.equals(aOpt)) {
role.getAccess().remove(aOpt.get());
}}
Solution
I think you are over complicating things a bit with your service which can be simplified to something like this
@Transactional
public ResponseEntity<Object> deleteRoleToAccess(String roleName) {
Optional<Role> optionalRole = roleRepository.findByRoleName(roleName);
if (!optionalRole.isPresent()) {
return ResponseEntity.unprocessableEntity().body("Role name not found");
}
Role role = optionalRole.get();
List<Access> removeList = new ArrayList<>(role.getAccesses());
for (Access access : removeList) {
role.removeAccess(access);
}
return ResponseEntity.ok("access is successfully delete");
}
But to do so you need to make changes to your entities
// Role
@Entity
public class Role {
@Id
@Column(name = "rid")
private Long rid;
private String roleName;
@ManyToMany(
fetch = FetchType.EAGER,
cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
}
)
@JoinTable(name = "role_access",
joinColumns = @JoinColumn(name = "roleId"),
inverseJoinColumns = @JoinColumn(name = "rid")
)
private List<Access> accesses = new ArrayList<>();
public Long getRid() {
return rid;
}
public void setRid(Long rid) {
this.rid = rid;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public List<Access> getAccesses() {
return accesses;
}
public void addAccess(Access access) {
accesses.add(access);
access.getRoles().add(this);
}
public void removeAccess(Access access) {
accesses.remove(access);
access.getRoles().remove(this);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Role role = (Role) o;
return getRid().equals(role.getRid());
}
@Override
public int hashCode() {
return Objects.hash(getRid());
}
}
// Access
@Entity
public class Access {
@Id
@Column(name = "id")
private Long accessId;
private String accName;
@ManyToMany(mappedBy = "accesses")
private List<Role> roles = new ArrayList<>();
public Long getAccessId() {
return accessId;
}
public void setAccessId(Long accessId) {
this.accessId = accessId;
}
public String getAccName() {
return accName;
}
public void setAccName(String accName) {
this.accName = accName;
}
public List<Role> getRoles() {
return roles;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Access access = (Access) o;
return getAccessId().equals(access.getAccessId());
}
@Override
public int hashCode() {
return Objects.hash(getAccessId());
}
}
Answered By - johnnyutts
Answer Checked By - Willingham (JavaFixing Volunteer)