[FIXED] How to delete specific data from join table(role_acces) in springboot jpa

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 – Pedro (Easybugfix Volunteer)

Leave a Reply

(*) Required, Your email will not be published