我正在做一个项目,我需要实现一些非规范化。 具体来说,我需要通过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);
}
}