Как ограничить повторяющиеся записи в Self Join - PullRequest
0 голосов
/ 05 апреля 2019

У меня есть отношения самосоединения, изображающие отношения Сотрудника и менеджера в моем коде JPA данных весны и раскрывающие его через конечную точку REST.

Вот мой EmployeeController

@Controller
@RequestMapping(path = "/employee")
public class EmployeeController {
    @Autowired
    private EmployeeRepository employeeRepository;

    @PostMapping

    public Employee addNewUser(@RequestBody Employee employee) {

        return employeeRepository.save(employee);
    }

    @GetMapping
    public @ResponseBody Iterable<Employee> getAllUsers() {
        // This returns a JSON or XML with the users
        return employeeRepository.findAll();
    }
}

ВотСущность сотрудника

@Entity
@Table(name = "EMPLOYEE")
public class Employee {

    @Id
    @Column(name = "id")
    @GeneratedValue
    private Long id;

    @Column(name = "fname")
    private String fname;

    @Column(name = "lname")
    private String lname;

    @ManyToOne(cascade = { CascadeType.ALL })
    @JoinColumn(name = "manager_id")
    private Employee manager;

    @OneToMany(mappedBy = "manager")
    private Set<Employee> subordinates = new HashSet<Employee>();

        //getters and setters
}

Теперь, когда я отправляю POST Запрос конечной точке /employee с показателем ниже

POST /employee
{
    "fname":"akash",
    "lname":"xavier",
    "manager":{
        "fname":"kiran",
        "lname":"Kumar"
    }
}

, он создает строки, как и ожидалось в базе данных

mysql> select * from employee;
+----+----------+---------+------------+
| id | fname    | lname   | manager_id |
+----+----------+---------+------------+
| 20 | kiran    | Kumar  |       NULL  |
| 19 | akash    | xavier |         20  |
+----+----------+---------+------------+

Теперь проблема в том, что я хотел под запросом подать

POST /employee

{
    "fname":"Vipul",
    "lname":"Kumar",
    "manager":{
        "fname":"kiran",
        "lname":"Kumar"
    }
}

, но не хочу, чтобы менеджер Kiran Kumar снова создавался.

1 Ответ

0 голосов
/ 05 апреля 2019

Нет решения, которое будет работать "из коробки" для предоставленного вами варианта использования. Вам необходимо вручную протестировать существующих менеджеров с таким же именем, например:

@PostMapping
public Employee addNewUser(@RequestBody Employee employee) {
    return employeeService.create(employee);
}

Где EmployeeService.create() реализовано следующим образом:

@Transactional
public void create(Employee employee) {
    Employee manager = Optional.ofNullable(employee.getManager()) 
        .flatMap(managerFromRequest -> employeeRepository.findByFnameAndLname(managerFromRequest.getFname(), managerFromRequest.getLname())
        .ifPresent(Employee:setManager);
    employeeRepository.save(employee);
}

и public Optional<Employee> findByFnameAndLname(String fname, String lname) объявлены EmployeeRepository.

В качестве примечания:

  • @ManyToOne(cascade = { CascadeType.ALL }) неправильно. В частности, CascadeType.REMOVE не имеет смысла для @ManyToOne ассоциации
  • Вы уверены, что fname и lname достаточно для однозначной идентификации Employee? Иногда люди просто имеют одинаковые имена
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...