创建父实体时@OneToMany Pesist子级

时间:2019-03-05 15:47:54

标签: postgresql hibernate spring-boot jpa spring-data

我有一个一对多的关系(用户到EmailAddress)

也许我正在以错误的方式进行操作,我的数据库为空,但是如果要发布一个User对象并将其添加到数据库中,请连同 emailAdresses对象,并保留EmailAddress。

我希望数据库中有2条记录: 1个用户和1个EmailAddress(带有指向用户表的fk)

服务等级

当前我实现该功能的方法是:

@Service
public class UserService {

private UserRepository userRepository;
private ModelMapper modelMapper;

   public UserService(UserRepository userRepository, ModelMapper modelMapper) {
      this.userRepository = userRepository;
      this.modelMapper = modelMapper;

      //Used for mapping List
      modelMapper.getConfiguration()
              .setFieldMatchingEnabled(true)
              .setFieldAccessLevel(Configuration.AccessLevel.PRIVATE)
              .setSourceNamingConvention(NamingConventions.JAVABEANS_MUTATOR);

  }
  public User createUser(UserCreateDTO userCreateDTO) {

      User user = modelMapper.map(userCreateDTO, User.class);
      //persist User to EmailAddress object
      if(user.getEmailAddresses() != null){
          user.getEmailAddresses().forEach(user::persistUser);
      }

      return userRepository.save(user);
  }

  public UserDTO getUserById(Long id) {
      User found = userRepository.findById(id).get();
      return modelMapper.map(found, UserDTO.class);
  }
  // .....

我曾经在某些双向关系中使用过

用户实体

@Entity
@Table(name = "Users")
@Getter @Setter @ToString @NoArgsConstructor
public class User {

   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   @Column(name = "user_id", updatable = false, nullable = false)
   private Long id;

   private String firstName;
   private String lastName;
   private int age;

   @OneToMany(fetch = FetchType.LAZY, mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
   private List<EmailAddress> emailAddresses;

电子邮件地址实体

@Entity
@Table(name = "Email")
@Getter @Setter @ToString @NoArgsConstructor
public class EmailAddress {

   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   @Column(name="email_id", updatable = false, nullable = false)
   private Long emailId;
   private String email;

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

是否有更好的方法建立Join关系?

示例POST请求

{"firstName":"Joe", "lastName":"Bloggs", "age": 30, "emailAddresses" : [ "joe-private@email.com" , "joe-work@email.com" ] }

2 个答案:

答案 0 :(得分:1)

我想您还需要将此电子邮件与用户相关联,而不仅仅是将用户设置为电子邮件实体。

public void persistUser(EmailAddress emailAddress) {
    // set this email to the user
    // if email EmailAddresses list is null you might need to init it first
    this.getEmailAddresses().add(emailAddress);   
    emailAddress.setUser(this);
}

答案 1 :(得分:1)

Firstly, I believe that a method persistUser should not be a part of a service layer - due to its implementation it mostly like a Domain layer method that should be implemented within a User entity class. Secondly, since it's a POST method you shouldn't care of emails existence - you are adding a new user with a new set of emails Closer to a question, I'd suggest you to try this:

public class UserService {

  /************/
  @Autowired
  private UserManager userManager;

  public void addUser(UserModel model) {
    User user = new User(model);
    List<EmailAddress> emails = model.getEmailAddresses().stream().map(EmailAddress::new).collect(Collectors.toList());
    user.setEmailAddresses(emails);
    userManager.saveUser(user);
  }  
}

and at the User add this:

public void setEmailAddresses(List<EmailAddress> emails) {
  emails.forEach(item -> item.setUser(this));
  this.emailAddresses = emails;
}

And don't forget to implement constructors for entities with model paremeters