替换所有执行 PUT 的子项 (OneToMany),Spring,Java 8

Replacing all Children (OneToMany) doing PUT, Spring, Java 8

我有关系ManyToOne......

User entity/class

@Entity
@Table(name = "users")
public class User implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @JsonManagedReference
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "user")
    private Set<Phone> phones;
    

    @PrePersist
    public void prePersist() {
        this.created = new Date();
        this.lastLogin = new Date();
    }

    public User() {
        this.phones = new HashSet<>();
    }
    
    public Set<Phone> getPhones() {
        return phones;
    }

    public void setPhones(Set<Phone> phones) {
        this.phones = phones;
    }

    //Getters and Setters
    
}

Phone entity/class

@Entity
@Table(name = "phones")
public class Phone implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private Long number;

    @JsonBackReference
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id", nullable = false)
    private User user;

    //Getters and Setters
}

当从我的控制器调用 PUT 时

@Operation(summary = "edit User", security = @SecurityRequirement(name = "bearerAuth"))
@PutMapping("/{id}")
public ResponseEntity<?> edit(@RequestHeader(value="Authorization") String token, 
        @Valid @RequestBody User user, BindingResult result, @PathVariable Long id) {
    
    //Some Code
    
    Optional<User> optionalStoredUser = userService.findById(id);
    if (!optionalStoredUser.isPresent()) {
        return ResponseEntity.notFound().build();
    }
    
    User editedUser = optionalStoredUser.get();
    editedUser.setName(user.getName());
    editedUser.setEmail(user.getEmail());
    editedUser.setPassword(user.getPassword());
    editedUser.setPhones(user.getPhones());
    editedUser.setModified(new Date());
    editedUser.setIsactive(user.isIsactive());
    editedUser.setToken(token);
    try {
        User savedUser = userService.save(editedUser);
        return ResponseEntity.status(HttpStatus.CREATED).body(savedUser);
    } catch (Exception exp) {
        throw new DefaultException(exp.getLocalizedMessage());
    }
}

在我的 Phone 存储库界面中,我有:

public interface PhoneDao extends CrudRepository<Phone, Long> {
    List<Phone> deleteByUser_id(Long id);
    List<Phone> findByUser_id(Long id);
}

如您所见,我调用我的服务,我有:

@Autowired
private UserDao userDao;

@Autowired
private PhoneDao phoneDao;

我需要清除所有未在新 Phone 中列出的旧 Phone(已存储)。

@Override
@Transactional
public User save(User user) {
    if (user.getId() != null) {
        // phoneDao.deleteByUser_id(user.getId());
        List<Phone> listOldPhones = phoneDao.findByUser_id(user.getId());
        Set<Phone> listNewPhones = user.getPhones();
        if (listNewPhones != null && listOldPhones != null) {
            Set<Long> listOldIds = listOldPhones.stream().map(p -> p.getId()).collect(Collectors.toSet());
            Set<Long> listNewIds = listNewPhones.stream().map(p -> p.getId()).collect(Collectors.toSet());
            listOldIds.stream().filter(id -> !listNewIds.contains(id)).forEach(id -> phoneDao.deleteById(id));
        }

    }
    return userDao.save(user);
}

根据其父级 (User) 命名接口方法的正确方式是什么?

如何高效地做同样的事情(只删除丢弃的phone,保留确认的phone并创建插入的phone)?

谢谢

将存储库更改为 findByUser_Id 将 Id 更改为大写!

public interface PhoneDao extends CrudRepository<Phone, Long> {
    List<Phone> deleteByUser_Id(Long id);
    List<Phone> findByUser_Id(Long id);
}

如果需要,在 User class 中将 CascadeType.ALL 更改为 CascadeType.MERGE

@JsonManagedReference
@OneToMany(cascade = CascadeType.MERGE, fetch = FetchType.LAZY, mappedBy = "user")
private Set<Phone> phones;