Skip to content

Commit

Permalink
LAZY, added tests for check synchronization
Browse files Browse the repository at this point in the history
  • Loading branch information
Alina Tarasova committed Jul 24, 2024
1 parent 65ab862 commit b418847
Show file tree
Hide file tree
Showing 11 changed files with 83 additions and 124 deletions.
3 changes: 1 addition & 2 deletions src/main/java/hexlet/code/model/Label.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
@Getter
@Setter
@EqualsAndHashCode(of = {"name"})
//@CacheConfig(cacheNames = "labels")
public class Label implements BaseEntity {

@Id
Expand All @@ -43,7 +42,7 @@ public class Label implements BaseEntity {
@CreatedDate
private LocalDate createdAt;

@ManyToMany(mappedBy = "labels", fetch = FetchType.LAZY, cascade = CascadeType.MERGE)
@ManyToMany(mappedBy = "labels", cascade = CascadeType.MERGE)
private Set<Task> tasks = new HashSet<>();


Expand Down
2 changes: 1 addition & 1 deletion src/main/java/hexlet/code/model/Task.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public class Task implements BaseEntity {
@ManyToOne(fetch = FetchType.LAZY)
private User assignee;

@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.MERGE)
@ManyToMany
private Set<Label> labels = new HashSet<>();


Expand Down
1 change: 0 additions & 1 deletion src/main/java/hexlet/code/model/TaskStatus.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ public class TaskStatus implements BaseEntity {
@CreatedDate
private LocalDate createdAt;

//@OneToMany(mappedBy = "taskStatus", cascade = CascadeType.MERGE, fetch = FetchType.LAZY)
@OneToMany(mappedBy = "taskStatus", cascade = CascadeType.MERGE)
private Set<Task> tasks = new HashSet<>();

Expand Down
2 changes: 0 additions & 2 deletions src/main/java/hexlet/code/model/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,7 @@ public class User implements UserDetails, BaseEntity {
@Column(name = "updated_at")
private LocalDate updatedAt;

//@OneToMany(mappedBy = "assignee", fetch = FetchType.LAZY, cascade = CascadeType.MERGE)
@OneToMany(mappedBy = "assignee", cascade = CascadeType.MERGE)
//private List<Task> tasks = new ArrayList<>();
private Set<Task> tasks = new HashSet<>();


Expand Down
3 changes: 0 additions & 3 deletions src/main/java/hexlet/code/repository/LabelRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,12 @@
@Repository
public interface LabelRepository extends JpaRepository<Label, Long> {

//@Cacheable(cacheNames = "labels", key = "#name")
@Query("SELECT l FROM Label l LEFT JOIN FETCH l.tasks WHERE l.name = :name")
Optional<Label> findByNameWithTasks(@Param("name") String name);

//@Cacheable(cacheNames = "labels", key = "#labelsIds")
@Query("SELECT l FROM Label l WHERE l.id IN :labelsIds")
Set<Label> findByIdIn(@Param("labelsIds") Set<Long> labelsIds);

//@Cacheable(cacheNames = "labels", key = "#id")
@Query("SELECT l FROM Label l LEFT JOIN FETCH l.tasks WHERE l.id = :id")
Optional<Label> findByIdWithTasks(@Param("id") Long id);

Expand Down
9 changes: 0 additions & 9 deletions src/main/java/hexlet/code/repository/TaskRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,33 +14,24 @@
@Repository
public interface TaskRepository extends JpaRepository<Task, Long>, JpaSpecificationExecutor<Task> {

// TODO: написать JPQL
// сделать кеш (ehcache), чтобы запрос цеплял из кеша, а не из базы
// проверить, что все работает!

//@Cacheable(cacheNames = "tasks", key = "#taskIds")
@Query("SELECT t FROM Task t WHERE t.id IN :taskIds")
Set<Task> findByIdIn(@Param("taskIds") Set<Long> taskIds);

//@Cacheable(cacheNames = "tasks", key = "#name")
@Query("SELECT t FROM Task t LEFT JOIN FETCH t.labels LEFT JOIN FETCH t.assignee LEFT JOIN FETCH t.taskStatus WHERE t.name = :name")
Optional<Task> findByNameWithLazyFields(@Param("name") String name);

@Query("SELECT t FROM Task t LEFT JOIN FETCH t.labels LEFT JOIN FETCH t.assignee LEFT JOIN FETCH t.taskStatus WHERE t.id = :id")
Optional<Task> findByIdWithLazyFields(@Param("id") Long id);



//@EntityGraph(attributePaths = {"labels", "assignee", "taskStatus"})
Optional<Task> findByName(String name);

//Set<Task> findByIdIn(Set<Long> taskIds);

//@Cacheable(cacheNames = "tasks", key = "#name")
@Query("SELECT t FROM Task AS t LEFT JOIN FETCH t.labels WHERE t.name=:name")
Optional<Task> findByNameWithLabels(@Param("name") String name);

//@Cacheable(cacheNames = "tasks", key = "#id")
@Query("SELECT t FROM Task AS t LEFT JOIN FETCH t.labels WHERE t.id=:id")
Optional<Task> findByIdWithLabels(@Param("id") Long id);
}
27 changes: 1 addition & 26 deletions src/main/java/hexlet/code/service/LabelService.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,36 +16,27 @@
@Slf4j
@Service
@AllArgsConstructor
//@CacheConfig(cacheNames = {"labels"})
public class LabelService {

private final LabelRepository labelRepository;
private final LabelMapper labelMapper;
private final TaskRepository taskRepository;

//@CacheEvict(allEntries = true)
//@CacheEvict(cacheNames = "labels", key = "#label.id")

public LabelDTO create(LabelCreateDTO labelCreateDTO) {
var label = labelMapper.map(labelCreateDTO);
labelRepository.save(label);
return labelMapper.map(label);
}


public List<LabelDTO> getAll() {
var tasks = labelRepository.findAll();
return tasks.stream()
.map(labelMapper::map)
.toList();
}

// @Cacheable(cacheNames = "labels", key = "#id")
public LabelDTO findById(Long id) {

// // захожу в сервисный метод findById(), пишу об этом в лог:
// log.info("Finding label by id: {}", id);

// вместо findById(id)
var label = labelRepository.findByIdWithTasks(id)
.orElseThrow(() -> new ResourceNotFoundException("Label With Id: " + id + " Not Found"));

Expand All @@ -54,28 +45,12 @@ public LabelDTO findById(Long id) {
return labelMapper.map(label);
}

//@Cacheable(cacheNames = "labels", key = "#id") //IllegalArgumentException
//@CacheEvict(allEntries = true)
//@CacheEvict(cacheNames = "labels", key = "#label.id")
public LabelDTO update(LabelUpdateDTO labelUpdateDTO, Long id) {
// вместо findById(id)
var label = labelRepository.findByIdWithTasks(id)
.orElseThrow(() -> new ResourceNotFoundException("Label With Id: " + id + " Not Found"));

labelMapper.update(labelUpdateDTO, label);

// TODO: НЕ НУЖНО, УДАЛИТЬ.
// В данном методе загружается label, обновляется и сохраняется. Должно всё и так работать.
// Синхронизировать данные полей необходимо, если они изменились.

// // записываю метку в таску:
// Set<Long> tasksIds = label.getTasks().stream()
// .map(Task::getId)
// .collect(Collectors.toSet());
//
// Set<Task> tasks = taskRepository.findByIdIn(tasksIds);
// tasks.forEach(task -> task.addLabel(label));

labelRepository.save(label);
return labelMapper.map(label);
}
Expand Down
79 changes: 8 additions & 71 deletions src/main/java/hexlet/code/service/TaskService.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,12 @@
import hexlet.code.repository.UserRepository;
import hexlet.code.specification.TaskSpecification;
import lombok.AllArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.server.ResponseStatusException;
import java.util.List;
import java.util.NoSuchElementException;


@Service
@AllArgsConstructor
//@CacheConfig(cacheNames = {"tasks"})
public class TaskService {

private final TaskRepository taskRepository;
Expand All @@ -31,35 +27,11 @@ public class TaskService {
private final TaskStatusRepository taskStatusRepository;
private final LabelRepository labelRepository;

//@CacheEvict(allEntries = true)
//@CacheEvict(cacheNames = "tasks", key = "#task.id")
public TaskDTO create(TaskCreateDTO taskCreateDTO) {

// TODO: УБРАТЬ try-catch
// TODO: пусть исключение обрабатывается в ControllerAdvice
try {
var task = taskMapper.map(taskCreateDTO);

//записываю таску автору и автора таске:
var assignee = task.getAssignee();
if (assignee != null) {
assignee.addTask(task);
}

//записываю таску статусу и статус таске:
var status = task.getTaskStatus();
status.addTask(task);

//записываю таску в метку и метку в таску:
var labels = task.getLabels();
labels.forEach(label -> label.addTask(task));

taskRepository.save(task);
return taskMapper.map(task);

} catch (NoSuchElementException ex) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, ex.getMessage());
}
public TaskDTO create(TaskCreateDTO taskCreateDTO) {
var task = taskMapper.map(taskCreateDTO);
taskRepository.save(task);
return taskMapper.map(task);
}

public List<TaskDTO> getAll() {
Expand All @@ -76,55 +48,20 @@ public List<TaskDTO> getAll(TaskFilterDTO taskFilterDTO) {
.toList();
}

//@Cacheable(cacheNames = "tasks", key = "#id")
//@Cacheable(cacheNames = "tasks", key = "#id != null ? #id : '-1'")
public TaskDTO findById(Long id) {
// вместо findById(id)
var task = taskRepository.findByIdWithLazyFields(id)
.orElseThrow(() -> new ResourceNotFoundException("Task With Id: " + id + " Not Found"));
return taskMapper.map(task);
}

//@Cacheable("tasks")
//@CacheEvict(allEntries = true)
//@CacheEvict(cacheNames = "tasks", key = "#task.id")
public TaskDTO update(TaskUpdateDTO taskUpdateDTO, Long id) {

try {
// вместо findById(id)
var task = taskRepository.findByIdWithLazyFields(id)
var task = taskRepository.findByIdWithLazyFields(id)
.orElseThrow(() -> new ResourceNotFoundException("Task With Id: " + id + " Not Found"));

taskMapper.update(taskUpdateDTO, task);

// TODO: выходит, ЭТО ТОЖЕ НЕ НУЖНО?
taskMapper.update(taskUpdateDTO, task);

// //записываю таску автору и автора таске:
// var assignee = task.getAssignee();
// if (assignee != null) {
// userRepository.findByEmail(assignee.getEmail())
// .ifPresent(user -> user.addTask(task));
// }
//
// //записываю таску статусу и статус таске:
// // вместо findBySlug(id)
// taskStatusRepository.findBySlugWithTasks(task.getTaskStatus().getSlug())
// .ifPresent(status -> status.addTask(task));
//
// //записываю таску в метки:
// Set<Long> labelIds = task.getLabels().stream()
// .map(Label::getId)
// .collect(Collectors.toSet());
//
// Set<Label> labels = labelRepository.findByIdIn(labelIds);
// labels.forEach(label -> label.addTask(task));

taskRepository.save(task);
return taskMapper.map(task);

} catch (NoSuchElementException ex) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, ex.getMessage());
}
taskRepository.save(task);
return taskMapper.map(task);
}

public void delete(Long id) {
Expand Down
2 changes: 0 additions & 2 deletions src/main/java/hexlet/code/service/TaskStatusService.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,13 @@ public List<TaskStatusDTO> getAll() {
}

public TaskStatusDTO findById(Long id) {
// вместо findById():
var taskStatus = taskStatusRepository.findByIdWithTasks(id)
.orElseThrow(() -> new ResourceNotFoundException("TaskStatus With Id: " + id + " Not Found"));

return taskStatusMapper.map(taskStatus);
}

public TaskStatusDTO update(TaskStatusUpdateDTO taskStatusUpdateDTO, Long id) {
// вместо findById():
var taskStatus = taskStatusRepository.findByIdWithTasks(id)
.orElseThrow(() -> new ResourceNotFoundException("TaskStatus With Id: " + id + " Not Found"));

Expand Down
2 changes: 0 additions & 2 deletions src/main/java/hexlet/code/service/UserService.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,13 @@ public List<UserDTO> getAll() {
}

public UserDTO findById(Long id) {
// вместо findById():
var user = userRepository.findByIdWithTasks(id)
.orElseThrow(() -> new ResourceNotFoundException("User With Id: " + id + " Not Found"));

return userMapper.map(user);
}

public UserDTO update(UserUpdateDTO userUpdateDTO, Long id) {
// вместо findById():
var user = userRepository.findByIdWithTasks(id)
.orElseThrow(() -> new ResourceNotFoundException("User With Id: " + id + " Not Found"));

Expand Down
Loading

0 comments on commit b418847

Please sign in to comment.