Весной JPA денормализовать один ко многим - PullRequest
0 голосов
/ 05 ноября 2018

Я делаю проект, и мне нужно реализовать некоторые денормализации. В частности, мне нужно запросить проекты по taskCount и / или projectTotalCost . Это то, что я имею до сих пор. Мне кажется, это работает, но я больше не уверен. Боюсь, что он подвержен гоночным условиям и тому подобному. В частности, части, где я обновляю счетчики. Несмотря на то, что я использую транзакции внутри моего сервиса, я не уверен насчет транзакции IsolationLevels. Это нормально ? Нужно ли добавить что-то еще? Должен ли я использовать @Version (кроме транзакций)? Мне действительно нужно поддерживать эту денормализацию (taskCount, projectTotalCost) и поддерживать ее согласованной.

@Entity
@Data
public class Project {

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

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "project_id", referencedColumnName = "id")
    private List<Task> tasks;

    private int taskCount;
    private double projectTotalCost;

    public Project() {

        this.tasks = new ArrayList<>();
        this.taskCount = 0;
        this.projectTotalCost = 0;

    }

    public void addTask(Task t) {

        this.tasks.add(t);
        updateTaskCount();
        updateProjectCost();

    }

    public void removeTask(Task t) {

        this.tasks.remove(t);
        updateTaskCount();
        updateProjectCost();

    }

    public void removeWhere(Predicate<Task> spec) {

        this.tasks.removeIf(spec);
        updateTaskCount();
        updateProjectCost();

    }

    private void updateTaskCount() {
        this.taskCount = this.tasks.size();
    }

    private void updateProjectCost() {
        this.projectTotalCost = this.tasks.stream().mapToDouble((Task t) -> t.getCost()).sum();
    }

}



@Entity
@Data
public class Task {

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

    private String name;
    private String description;

    private double cost;

    public Task(String name, String description, double cost) {
        this.name = name;
        this.description = description;
        this.cost = cost;
    }

    public double getCost() {
        return this.cost;
    }

}




@Service
public class ProjectService {

    @Autowired
    private ProjectRepository repo;

    @Transactional
    public Project create(Project p) {

        return this.repo.save(p);

    }

    @Transactional
    public Project addTask(long projectId, Task t) {

        Project p = this.repo.findById(projectId);

        p.addTask(t);

        return repo.save(p);

    }

    @Transactional
    public Project removeTaskFromProject(long projectId, long taskId) {

        Project p = this.repo.findById(projectId);

        p.removeWhere((Task t) -> t.hasId(taskId));

        return repo.save(p);

    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...