如何限制自我联接中的重复记录

时间:2019-04-05 13:00:54

标签: java spring-boot jpa spring-data-jpa

我在自己的spring数据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 :(得分:0)

对于您提供的用例,没有开箱即用的解决方案。您需要使用以下名称手动测试现有经理的姓名:

@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关联没有意义
  • 您确定fnamelname足以唯一地标识Employee吗?有时候,人们恰好有相同的名字