Search code examples
javaspringspring-bootspring-data

Spring updating many to many reletionship Issue


I'm trying to update my entity many to many by this json: as you can see i have this relation: Utente-Ruoli, Ruoli-Privileggi

  • I sending a list of id for ruoli and an id for user in the json DTO

this is the method in my Utente JPA:

  @Modifying(flushAutomatically = true, clearAutomatically = true)
    @Transactional
    @Query("UPDATE Utente u SET u.roles = :roles WHERE u.id = :userId")
    int saveUserRoles(@Param("userId") Integer userId, @Param("roles") Set<Ruoli> roles);

and this is where i perfom the service:

 public Utente addRolesToUser(RuoliDTO ruoliDTO) {
    log.info("{}.addRolesToUser adding user: {} to list roles: {}", this.getClass().getName(), ruoliDTO.getUser().getUsername(), ruoliDTO.getRoles().size());
    Utente utente = ruoliDTO.getUser();
    Set<Ruoli> rolesToAdd = ruoliDTO.getRoles();
    utente.setRoles(ruoliDTO.getRoles());
     userRepository.saveUserRoles(utente.getId(), rolesToAdd);
     return utente;
}

And i get always this error:

Parameter value [Ruoli{id=2, roleName='ADMIN', description='admin', privileggi=[Privileggi{id=1, privName='UNICACON_MDJS_USER', description='basic user', active=false}, Privileggi{id=3, privName='UNICACON_MDJS_ADMIN', description='admin role', active=true}, Privileggi{id=4, privName='ARCHICON_MDJS_USER', description='archicon role', active=true}]}] did not match expected type [java.util.Set (n/a)]; nested exception is java.lang.IllegalArgumentException: Parameter value [Ruoli{id=2, roleName='ADMIN', description='admin', privileggi=[Privileggi{id=1, privName='UNICACON_MDJS_USER', description='basic user', active=false}, Privileggi{id=3, privName='UNICACON_MDJS_ADMIN', description='admin role', active=true}, Privileggi{id=4, privName='ARCHICON_MDJS_USER', description='archicon role', active=true}]}] did not match expected type [java.util.Set (n/a)]

These are my entities:

     @Entity
    @Table(name = "utente")
@Data
    public class Utente implements Serializable {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Integer id;
    
        @JsonIgnoreProperties("utenti")
        @ManyToMany(fetch = FetchType.EAGER, cascade = {CascadeType.MERGE, CascadeType.PERSIST})
        @JoinTable(
                name = "utente_ruolo",
                joinColumns = @JoinColumn(name = "utente_id", referencedColumnName = "id"),
                inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id")
        )
        private List<Ruoli> roles;
    }



 @Data
    @Entity
    @Table(name = "ruoli")
    public class Ruoli implements Serializable {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Integer id;
    
        @JsonIgnore
        @ManyToMany(cascade ={ CascadeType.MERGE, CascadeType.PERSIST})
        @JoinTable(
                name = "utente_ruolo",
                joinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"),
                inverseJoinColumns = @JoinColumn(name = "utente_id", referencedColumnName = "id")
        )
        private List<Utente> utenti;
    }

    @Entity
    @Data
    @Table(name = "privileggi")
    public class Privileggi implements Serializable {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Integer id;
    
        @Column(name = "priv_name")
        private String privName;
    
        @Column(name = "description")
        private String description;
    
        @Column(name = "active")
        private Boolean active;
    
        @JsonIgnore
        @ManyToMany( cascade ={ CascadeType.MERGE, CascadeType.PERSIST})
        @JoinTable(
                name = "ruolo_privileggi",
                joinColumns = @JoinColumn(name = "priv_id", referencedColumnName = "id"),
                inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id")
        )
        private List<Ruoli> ruoli;
    }

What Am I doing wrong?


Solution

  • Here is the answer shown below

    • First, you need to fetch the Utente entity from the database.

    • Then, you can update the Utente entity's roles with the roles from the RuoliDTO.

    • Finally, you can save the updated Utente entity back to the database.

       public Utente addRolesToUser(RuoliDTO ruoliDTO) {
           log.info("{}.addRolesToUser adding user: {} to list roles: {}", this.getClass().getName(), ruoliDTO.getUser().getUsername(), ruoliDTO.getRoles().size());
      
           // 1. Fetch the Utente entity from the database.
           Utente utente = userRepository.findById(ruoliDTO.getUser().getId()).orElse(null);
      
           if (utente != null) {
               // 2. Update the Utente entity's roles with the roles from RuoliDTO.
               utente.setRoles(ruoliDTO.getRoles());
      
               // 3. Save the updated Utente entity back to the database.
               utente = userRepository.save(utente);
           }
      
           return utente;
       }