Nuñito Calzada
Nuñito Calzada

Reputation: 2096

Multiple representations of the same entity in SpringBoot 2.0.4

I have a basic SpringBoot 2.0.4.RELEASE app. using Spring Initializer, JPA, embedded Tomcat, Thymeleaf template engine, and package as an executable JAR file.

I have a User object with roles:

@Entity
@Table(name="t_user")
public class User implements Serializable, UserDetails {


 @ManyToMany(cascade = CascadeType.MERGE, fetch = FetchType.EAGER)
    @JoinTable(
        name="t_user_role",
        joinColumns=@JoinColumn(name="user_id", referencedColumnName="id"),
        inverseJoinColumns=@JoinColumn(name="role_id", referencedColumnName="id"))
    private Set<Role> roles = new HashSet<>();
..
}

When I init the app. I create all the roles:

roleService.save(new Role(RolesEnum.USER.getRoleName()));
roleService.save(new Role(RolesEnum.ADMIN.getRoleName()));

Then I create a User with the USER role:

User user1 = new User();


         Role role = roleService.findByName(RolesEnum.USER.getRoleName());

         user.getRoles().add(role);
          userService.save(user);

but When I create another user with the same role:

User user2 = new User();


         Role role = roleService.findByName(RolesEnum.USER.getRoleName());

         user2.getRoles().add(role);
          user2Service.save(user);

I got this error:

Multiple representations of the same entity [com.tdk.backend.persistence.domain.backend.Role#1] are being merged. Detached: [com.tdk.backend.persistence.domain.backend.Role@5295d3de]; Detached: [com.tdk.backend.persistence.domain.backend.Role@2b3d9d32]

In the Role entity I don't have the field users declared since I will not get all the users based on a role

Upvotes: 5

Views: 8250

Answers (2)

abhinav kumar
abhinav kumar

Reputation: 1803

you are facing this issue because you are adding the object to the list/set which is already available.while performing save operation with oneToMany mapping

Now removing CascadeType.MERGE from cascade is one solution but not a best solution because after removing MERGE from Cascade you won't be able to update the mapped object ever

If you want to perform update operation also along with save for the mapped objects then before adding mapped object to list/collection just check/search within the list for the object and if the mapped object is available within the list then perform operation on that particular object.

keep cascade = CascadeType.ALL

Role role = roleService.findByName(RolesEnum.USER.getRoleName());
Note- make sure you have overridden hashcode/equals properly
boolean b = user2.getRoles().contains(role);
if (b!=true){
user2.getRoles().add(role);
}
 user2Service.save(user);

or using stream

Role r= user2.getRoles().stream().filter(oldRole->oldRole.equals(role)).findAny().orElse(null);
        
        if(r==null) {
 user2.getRoles().add(role);
    }
     user2Service.save(user);

Upvotes: 3

Pallav Kabra
Pallav Kabra

Reputation: 458

According to me, you have used cascade = CascadeType.MERGE on the Role entity. Please remove and it will solve the issue.

Upvotes: 2

Related Questions