matiska
matiska

Reputation: 525

Saving entity with existing children with CRUD Repository fails because of duplicate key

A User can have multiple Authorities. By default, when I create a new User I want to add him ROLE_USER authority.

This is the User entity:

@Entity
@Table(name = "Users")
public class User
{
    @Id    
    private String username;
    private String password;
    private String email;
    @OneToMany
    @JoinTable(
      name = "UserAuthority",
      joinColumns = @JoinColumn(name = "username"),
      inverseJoinColumns = @JoinColumn(name = "authority"))
    private List<Authority> authorities = new ArrayList<>();

and Authority entity:

@Entity
public class Authority
{
    @Id
    private String authority;

I am using basic UserRepository and AuthorityReposiroty both extending CrudRepository.

This is method for registering new user:

public String register(User user)
{
    if (userRepository.findOne(user.getUsername()) != null)
    {
        return "User with given username already exists!";
    }
    user.setPassword(passwordEncoder.encode(user.getPassword()));
    user.getAuthorities().add(authRepository.findOne("ROLE_USER"));
    userRepository.save(user);
    return "User successfully registered!";
}

When I try to register new user it fails with this error:

org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "uk_c1gaghspdr9qx2yt45moye10y"
  Detail: Key (authority)=(ROLE_USER) already exists.

I can see in logs that Hibernate is trying to insert ROLE_USER authority which is not possible because it already exists, but I do not understand why. I haven't set cascade property on @OneToManyannotation.

How to I achieve what I want?

This is my configuration:

compile('org.springframework.boot:spring-boot-starter-data-jpa')
runtime('org.postgresql:postgresql:9.4-1206-jdbc42')

Thanks in advance!

Upvotes: 0

Views: 2151

Answers (1)

Victor1125
Victor1125

Reputation: 692

Problem is in relations. You have OneToMany - means that on other site is relation ManyToOne... If you used some Authority in one User you can't use this entity (object) for other user.

The solution of your issue is changing relation to @ManyToMany insted @OneToMany in User class. It's little streng, but in fact it is relation ManyToMany, because User can has many authorities and any athority can be used in many users.

Upvotes: 2

Related Questions