【问题标题】:How to add to a Set of entities when doing Many-to-many进行多对多时如何添加到一组实体
【发布时间】:2020-04-17 12:23:50
【问题描述】:

我有以下具有多对多关系的实体

用户实体

@Entity
@Table(name = "users")
public class User {
    ...
    @ManyToMany
    @JoinTable(
            name = "team_members",
            joinColumns = @JoinColumn(name = "team_id"),
            inverseJoinColumns = @JoinColumn(name = "user_id"))
    private Set<Team> teams;

团队实体

@Entity
@Table(name = "teams")
public class Team {
    ...
    @ManyToMany
    @JoinTable(
            name = "team_members",
            joinColumns = @JoinColumn(name = "user_id"),
            inverseJoinColumns = @JoinColumn(name = "team_id"))
    private Set<User> members;
}

我有这个用户服务

public interface UserService {
    UserDTO getById(Integer userId);
    ...
}

我想在 TeamService 中实现一个方法,如下所示:

@Override
@Transactional
public TeamDTO addMemberToTeam(Integer teamId, Integer userId, User currentUser) {
    checkCurrentUserIsAdmin(currentUser);
    User user = userService.getById(userId); <-------- PROBLEM LINE
    Team team = teamRepository.findById(teamId)
            .orElseThrow(() -> new RuntimeException("No such team"));
    team.getMembers().add(user);

    return TeamDTO.fromTeam(teamRepository.save(team));
}

问题是我有返回 UserDTO 的服务,但为了使关系正常工作,我需要一个用户。

我能想到的可能解决方案:

解决方案 1:

在 UserService 中有另一个方法显式返回 User like:

User getUserById(Integer userId);

但这不会破坏 UserService 只返回 UserDTO 的想法。是否有这样做的标准方法,并且仍然遵循服务接口的最佳实践来使用 DTO。

解决方案 2:

在 UserService 中有另一个方法,例如:

@Override
public void addUserToTeam(Integer userId, Team team) {
    User user = userRepository.findById(userId)
            .orElseThrow(() -> new RuntimeException("No such user"));
    user.getTeams().add(team);
    team.getMembers().add(user);
    userRepository.save(user);
}

并将 TeamService 中的方法更改为:

@Override
@Transactional
public TeamDTO addMemberToTeam(Integer teamId, Integer userId, User currentUser) {
    checkCurrentUserIsAdmin(currentUser);
    Team team = teamRepository.findById(teamId)
            .orElseThrow(() -> new RuntimeException("No such team"));

    userService.addUserToTeam(userId,team); <--- THIS NEW METHOD CALL

    return TeamDTO.fromTeam(teamRepository.save(team));
}

这似乎是一个更好的解决方案,但我仍然觉得我把它复杂化了。

在我的情况下哪个是更好的解决方案?

【问题讨论】:

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


    【解决方案1】:

    如果我理解正确,您尝试遵循的最佳实践是 1 @Service 拥有一个 @Entity,这就是为什么您如此努力地不直接在 userRepository 内部使用 userRepository

    恕我直言,DTO 仅在您与外部方通信时才需要,例如当您有一个 REST 端点向消费者返回 UserDTO 而不是返回 @Entity 本身时。在您自己的应用程序和服务的范围内,我认为在您需要的任何地方都可以使用存储库,而不是为自己创建一条硬线而使其变得困难。

    以防万一您仍想使用UserDTO 在服务之间以及与外部方进行通信,我建议这样做。

    public class UserDTO {
       ... 
       // your fields 
       ...
    
       @JsonIgnore
       private User userRecord;
    }
    

    这样,您的服务仍然可以访问实际的 @Entity,并且当您将此对象返回给 API 使用者时,他们将看不到该字段。

    【讨论】:

      猜你喜欢
      • 2021-05-18
      • 1970-01-01
      • 2015-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多