Не удается сохранить дочернюю сущность с отношением OneToMany - PullRequest
0 голосов
/ 05 января 2020

Я хочу создать интеграционный тест для метода репозитория, который найдет тренинги тренера между двумя датами, чтобы проверить на следующем шаге, не будет ли предлагаемая дата тренинга совпадать с расписанием тренера.

Основное допущение в приложении заключается в том, что Пользователь является основным субъектом, а от него - учетная запись, обучение и т. Д. c. созданы соответственно. По этой причине пользователь является активной стороной в отношении учетной записи и обучения.

Метод выглядит следующим образом:

@Query(
      value =
          "SELECT t FROM Training t INNER JOIN t.trainingParticipants p "
              + "WHERE p.trainer.id = :trainer_id "
              + "AND t.trainingDate.startDate <= :trainingStartDate "
              + "AND t.trainingDate.endDate <= :trainingEndDate ")
  List<Training> findTrainingOfTrainer(
      @Param("trainer_id") Long trainerId,
      @Param("trainingStartDate") LocalDateTime trainingStartDate,
      @Param("trainingEndDate") LocalDateTime trainingEndDate);

Я использую этот метод в TrainingService, как показано ниже:

@Service
@Slf4j
@Transactional
class TrainingService {

  private final TrainingRepository trainingRepository;
  private final UserRepository userRepository;

  public TrainingService(TrainingRepository trainingRepository, UserRepository userRepository) {
    this.trainingRepository = trainingRepository;
    this.userRepository = userRepository;
  }

  public List<Training> findTrainingBetweenTwoDatesQuery(
      Long trainerId, LocalDateTime startDate, LocalDateTime endDate) {
    return trainingRepository.findTrainingOfTrainer(trainerId, startDate, endDate);
  }
}

Мой User.java класс выглядит так:

@Entity
@Table(name = "users")
@SuperBuilder
@AllArgsConstructor
@Getter
@Setter
public class User extends AbstractBaseEntity {

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

  @OneToOne(cascade = CascadeType.PERSIST)
  @JoinColumn(name = "user_account_id", unique = true)
  private Account account;

  @Enumerated(EnumType.STRING)
  private UserType userType;

  @OneToMany(mappedBy = "user", fetch = FetchType.EAGER)
  private Set<Training> training;

  @OneToOne(mappedBy = "trainer")
  private TrainingParticipants trainingParticipants;

  public User() {}

  public User(Account account) {
    this.account = account;
  }

  public Long getId() {
    return id;
  }

  public Account getAccount() {
    return account;
  }

  public UserType getUserType() {
    return userType;
  }
}

Обучение. java класс выглядит так:

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@Entity
@SuperBuilder
public class Training extends AbstractBaseEntity {

  @Id
  @GeneratedValue
  private Long id;

  @Column(name = "training_start_date")
  LocalDateTime trainingStartDate;

  @Column(name = "training_end_date")
  LocalDateTime trainingEndDate;

  @OneToMany(mappedBy = "training", cascade = CascadeType.ALL)
  List<Exercise> exercises = new ArrayList<>();

  @Column(name = "difficulty_level")
  @Enumerated(EnumType.STRING)
  private DifficultyLevel difficultyLevel;

  @Column(name = "completed")
  boolean completed;

  @OneToOne(cascade = CascadeType.PERSIST)
  @JoinColumn(name = "training_participants_id", unique = true)
  private TrainingParticipants trainingParticipants;

  @Embedded private TrainingDate trainingDate;

  @ManyToOne(cascade = CascadeType.PERSIST)
  private User user;

}

Мой тестовый класс выглядит так:

@SpringBootTest
@ExtendWith(SpringExtension.class)
class TrainingServiceTest {

  @Autowired private TrainingRepository trainingRepository;

  @Autowired private UserRepository userRepository;

  @Autowired private AccountRepository accountRepository;

  @Autowired private TrainingService trainingService;

  @BeforeEach
  void setUp() {
    trainingService = new TrainingService(trainingRepository, userRepository);
  }

  @Test
  void shouldReturnTrainerTrainingBetweenTwoDates() {
    LocalDateTime now = LocalDateTime.now();

    userRepository.saveAll(userWithTrainingDataStub());

    List<Training> trainingOfTrainer =
        trainingRepository.findTrainingOfTrainer(1L, now.minusDays(7), now.plusDays(7));

    assertEquals(4, userRepository.findAll().size());
    assertEquals(4, trainingRepository.findAll().size());
    assertEquals(2, trainingOfTrainer.size());
  }

  List<User> userWithTrainingDataStub() {

    User user4 = userRepository.saveAndFlush(
        User.builder()
            .account(Account.builder().build())
            .userType(UserType.TRAINER)
            .build());

    return List.of(
        User.builder()
            .account(Account.builder().build())
            .userType(UserType.TRAINEE)
            .training(
                newHashSet(
                    Training.builder()
                        .trainingParticipants(
                            TrainingParticipants.builder()
                                .trainer(user4)
                                .build())
                        .trainingDate(
                            TrainingDate.builder()
                                .startDate(LocalDateTime.now().minusDays(3))
                                .endDate(LocalDateTime.now().minusDays(2))
                                .build())
                        .build()))
            .build(),
        User.builder()
            .account(Account.builder().build())
            .userType(UserType.TRAINEE)
            .training(
                newHashSet(
                    Training.builder()
                        .trainingParticipants(
                            TrainingParticipants.builder()
                                .trainer(user4)
                                .build())
                        .trainingDate(
                            TrainingDate.builder()
                                .startDate(LocalDateTime.now().minusDays(5))
                                .endDate(LocalDateTime.now().minusDays(3))
                                .build())
                        .build()))
            .build(),
        User.builder()
            .account(Account.builder().build())
            .userType(UserType.TRAINEE)
            .training(
                newHashSet(
                    Training.builder()
                        .trainingParticipants(
                            TrainingParticipants.builder()
                                .trainer(user4)
                                .build())
                        .trainingDate(
                            TrainingDate.builder()
                                .startDate(LocalDateTime.now().minusDays(5))
                                .endDate(LocalDateTime.now().minusDays(3))
                                .build())
                        .build()))
            .build());

  }


}

Проблема в том, что первое утверждение проходит, и я могу сохранить 4 пользователей, но второе утверждение: assertEquals(4, trainingRepository.findAll().size()); не выполняется, и мои тренировки не сохраняются при создании пользователя. Все, что я хочу сделать, - это сохранить свои тренировки при создании пользователя. Я почти уверен, что существует проблема с отображением User <-> Training, но, честно говоря, я не вижу другого потенциального решения для достижения желаемой цели. Я буду благодарен за предложения о том, как исправить свое отображение, и получу возможность продолжать обучение во время создания пользователя.

...