Zapis encji z referencją do już istniejącej

0

Przy próbie zapisu encji z referencją do innej już istniejącej dostaje błąd "duplicate entry for key".
Wygląda to tak jakby entityManager chciał zapisać dodane do klasy Employee objekty UserPermission jeszcze raz w bazie danych zamiast po prostu ustanowić relację.
Jak można to naprawić?

@Entity
@Table(name = "employee")
public class Employee implements UserDetails {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer employee_id;
    @Column(unique = true)
    private String username;
    private String password;
    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.MERGE)
    private List<UserPermission> userPermissions;
    private String name;
    private String surname;
    private String position;
    private String phoneNumber;
    private Boolean enabled;

    public Employee() {
    }

    public Employee(String username, String password, List<UserPermission> userPermissions, String name, String surname, String position, String phoneNumber) {
        this.username = username;
        this.password = password;
        this.userPermissions = userPermissions;
        this.name = name;
        this.surname = surname;
        this.position = position;
        this.phoneNumber = phoneNumber;
        this.enabled = true;
    }
}

// getters && setters 
@Entity
@Table(name = "permission")
public class UserPermission implements GrantedAuthority {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    @Column(name = "permission")
    private String permission;

    public UserPermission() {
    }

    public UserPermission(String permission) {
        this.permission = Permission.valueOf(permission).getRoleName();
    }

    public void setAuthority(String permission) {
        this.permission = permission;
    }

    @Override
    public String getAuthority() {
        return permission;
    }
}
public void createNewUser(CreateUserRequest createUserRequest) {
        Employee employee = employeeWrapper.employeeRequestToEmployee(createUserRequest);
        employee.setPassword(passwordEncoder.encode(employee.getPassword()));
        try {
            employeeRepository.addUser(employee);
        } catch (Exception e) {
            System.out.println("exception " + e.getMessage() + " " + e.getCause());
        }
    }
public Employee employeeRequestToEmployee(CreateUserRequest createUserRequest) {
        List<UserPermission> allPermisions = userPermissionRepository.getAllPermisions();
        List<UserPermission> allMatchingPermissions = allPermisions.stream()
                .filter(ap -> createUserRequest.getUserPermissions().contains(ap.getAuthority()))
                .collect(Collectors.toList());

        Employee employee = new Employee(createUserRequest.getUsername(),
                createUserRequest.getPassword(),
                allMatchingPermissions,
                createUserRequest.getName(),
                createUserRequest.getSurname(),
                createUserRequest.getPosition(),
                createUserRequest.getPhoneNumber());

        return employee;
    }
@Transactional
    public void addUser(Employee user) {
        entityManager.persist(user);
    }
@Transactional
    public List getAllPermisions() {
        return entityManager.createQuery("SELECT p FROM UserPermission p")
                .getResultList();
    }
4

Nie chce mi się analizować, niepełny zbiór spostrzeżeń:

  • oczywiście wiesz, że List<Cokolwiek> w JPA ma ... specyficzną urodę, w tym zapis przebiega z wymiataniem poprzedniej listy? Wielu uważa, że Set<Cokolwiek> jest bardziej intuicyjne (ale ma problem, wymaga wiernego hashowania)
  • i że @Transactional też ma specyficzny brak urody, m.in. nie działa tak jak myślisz wołane z tej samej klasy
0

Problem rozwiązany, relacja powinna mieć postać @ManyToMany

1 użytkowników online, w tym zalogowanych: 0, gości: 1