Избегайте создания дубликатов для функций TImeline в Spring
Я работаю над проектом Spring -MVC, для которого я сейчас работаю над функциональностью Timeline. У меня уже есть базовая инфраструктура, но в настоящее время я имею дело с сопоставлениями и как избежать создания дубликатов для функциональности Timeline.
Ситуация:
В нашем инструменте есть GroupSection, который имеет сопоставление "один ко многим" с GroupNote. Объект GroupNote имеет сопоставление "один ко многим" с вложениями, история.
Что это за функциональность временной шкалы?
В функциональности временной шкалы любой пользователь может перейти в любой момент времени и проверить, как содержимое GroupSection, GroupNotes, вложений и истории.
Как я планирую его реализовать?
У меня есть 4 переменные в каждом из вышеперечисленных объектов для обработки этого. Они Date SavedDate
, boolean initialNote
, boolean noteModified
, boolean latestNote
.
Вместе с тем, каждый GroupNote имеет самостоятельное соединение, скоро объяснит это.
Теперь, каждый раз, когда изменяется примечание, измененный флаг имеет значение true. В ночное время я запускаю метод, который проверяет все измененные объекты, и только если объект изменен, он создает дубликат экземпляра для объекта, помещает новую дату в него, отмечает его как последнюю и сохраняет его,
Таким образом, я могу загрузить все объекты для данной даты. И для обычного ежедневного использования будут загружены все заметки, отмеченные как latest
.
Всякий раз, когда создается новый объект для сохранения, он соединяется со старым объектом с Cascade.Remove
. Это происходит, если пользователь возвращается и удаляет объект с 2015 года, тогда все последующие объекты до настоящего времени также удаляются. Это дает время, подобное поведению.
Проблема:
Теперь, если GroupSection изменен, я создам экземпляр GroupSection и сохраняю его, скопировав свойства из модифицированного GroupSection и пометьте его как последний.
Теперь заметки, которые удерживает это GroupSection, не были изменены, но если я не создаю его повторяющиеся записи, я не увижу никаких заметок, загруженных в интерфейс. Но я хотел бы избежать этого. Как я могу это сделать?
Код наконец:
Модель GroupSection:
@Entity
@Table(name = "membersection")
public class GroupSection {
@Column(name = "section_save_date", columnDefinition = "date")
private Date secnSavedDate;
@Column(name = "initial_section", columnDefinition = "boolean default true")
private boolean initialSection;
@Column(name = "section_modified", columnDefinition = "boolean default false")
private boolean sectionModified;
@Column(name = "latest_section", columnDefinition = "boolean default false")
private boolean latestSection;
@JsonIgnore
@ManyToOne
@JoinColumn(name = "owned_section_id", nullable = true)
private GroupSection primarySection;
@OneToMany(mappedBy = "primarySection", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
private Set<GroupSection> groupSectionSet = new HashSet<>();
@OneToMany(mappedBy = "ownednotes", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
@JsonIgnore
private Set<GroupNotes> sectionsnotes = new HashSet<>();
}
Модель GroupNotes:
@Entity
@Table(name = "groupnotes")
public class GroupNotes implements Serializable {
@Column(name = "note_save_date", columnDefinition = "date")
private Date noteSavedDate;
@Column(name = "initial_note", columnDefinition = "boolean default true")
private boolean initialNote;
@Column(name = "note_modified", columnDefinition = "boolean default false")
private boolean noteModified;
@Column(name = "latest_note", columnDefinition = "boolean default false")
private boolean latestNote;
@JsonIgnore
@ManyToOne
@JoinColumn(name = "owned_note_id", nullable = true)
private GroupNotes primaryNote;
@OneToMany(mappedBy = "primaryNote", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
private Set<GroupNotes> groupNotesSet = new HashSet<>();
}
GroupSectionDAOImpl:
@Override
@Transactional(readOnly = true)
public List<GroupSection> listGroupSectionByCanvasAndDate(int mcanvasid, Date dateToLoad) {
Session session = this.sessionFactory.getCurrentSession();
org.hibernate.Query query = session.createQuery("From GroupSection as msection where " +
"msection.currentcanvas.mcanvasid=:mcanvasid and " +
"msection.secnSavedDate>:dateToLoad " +
" and msection.sectionDisabled=false and msection.latestSection=true and msection.sectionInActive=false order by msection.secnSavedDate asc");
query.setParameter("mcanvasid", mcanvasid);
query.setParameter("dateToLoad",dateToLoad);
return query.list();
}
@Override
public List<GroupSection> listModifiedSectionsForYesterday() {
Session session = this.sessionFactory.getCurrentSession();
Calendar cal = Calendar.getInstance();
Query query = session.createQuery("from GroupSection as gs where gs.sectionModified=true and gs.latestSection=true and gs.secnSavedDate<:loadDate order by gs.secnSavedDate asc");
query.setParameter("loadDate",cal.getTime());
return query.list();
}
Вышеуказанные методы DAO дают мне измененные разделы со вчерашнего дня или последние измененные разделы и аналогичные разделы для данной даты. У меня есть аналогичные методы в GroupNotesDAOImpl
GroupSectionServiceImpl:
@Override
public List<GroupSection> retrieveModifiedSections() {
List<GroupSection> groupSectionList = this.groupSectionDAO.listModifiedSectionsForYesterday();
for (GroupSection yesterdaySection : groupSectionList) {
yesterdaySection.setLatestSection(false);
this.groupSectionDAO.updateGroupSection(yesterdaySection);
GroupSection newDaySection = new GroupSection();
BeanUtils.copyProperties(yesterdaySection, newDaySection);
newDaySection.setInitialSection(false);
newDaySection.setSectionModified(false);
newDaySection.setLatestSection(true);
newDaySection.setMsectionid(0);
newDaySection.setSortedSectionSet(null);
newDaySection.setSecnSavedDate(Calendar.getInstance().getTime());
int sectionSavedId = directAddGroupSection(newDaySection, yesterdaySection.getCurrentCanvasId());
List<GroupNotes> groupNotesList = this.groupNotesService.directListGroupNotesBySectionIdForCanvasCopying(yesterdaySection.getMsectionid());
for(GroupNotes groupNotes : groupNotesList){
Problem --> // No option but to create duplicates.
}
}
return this.groupSectionDAO.listModifiedSectionsForYesterday();
}
Надеюсь, этот вопрос понятен. Если есть какие-либо сомнения, любезно сообщите мне.
Изменить
Одна стратегия, о которой я могу думать, касается сопоставлений "много-ко-многим" между GroupSection и GroupNotes. К сожалению, уже существует много бэкэнд, а также интерфейсный код с сопоставлением "один ко многим" между GroupSection и GroupNotes.
Тем не менее, я добавлял сопоставления "много-ко-многим", но набор данных не загружается, а также значительно увеличивает сложность, здесь идет процесс . Я все же предпочел бы другой вариант.
Ответы
Ответ 1
Я не уверен, что мне удалось запустить эту функцию удаления.
Для меня жизнеспособной стратегией было бы следовать соотношению "один ко многим" из
историческое GroupSection (первое из которых будет удалено из цепочки истории) в соответствующие GroupNotes. Это отношение должно идентифицировать каждую из затронутых GroupNotes
соответствующий исторический экземпляр и вызывать удаление такого экземпляра.
Вам может потребоваться собрать ссылки на эти GroupNotes при работе с GroupSections (там, возможно, будут изменения в этом наборе с течением времени, я бы предположил)
и очистить результирующий набор в конце, чтобы избежать проверки надписей GroupNotes и выше.
Ответ 2
Я предлагаю изменить связь между GroupSection и GroupNotes со многими для многих, чтобы избежать дублирования групповых комментариев.
@Entity
@Table(name = "membersection")
public class GroupSection {
@Column(name = "section_save_date", columnDefinition = "date")
private Date secnSavedDate;
@Column(name = "initial_section", columnDefinition = "boolean default true")
private boolean initialSection;
@Column(name = "section_modified", columnDefinition = "boolean default false")
private boolean sectionModified;
@Column(name = "latest_section", columnDefinition = "boolean default false")
private boolean latestSection;
@JsonIgnore
@ManyToOne
@JoinColumn(name = "owned_section_id", nullable = true)
private GroupSection primarySection;
@OneToMany(mappedBy = "primarySection", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
private Set<GroupSection> groupSectionSet = new HashSet<>();
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinTable(name = "groupsection_groupnote", joinColumns = {
@JoinColumn(name = "GROUP_SECTION_ID", nullable = false, updatable = false) },
inverseJoinColumns = { @JoinColumn(name = "GROUP_NOTE_ID",
nullable = false, updatable = false) })
@JsonIgnore
private Set<GroupNotes> sectionsnotes = new HashSet<>();
}
GroupSectionServiceImpl:
@Override
public List<GroupSection> retrieveModifiedSections() {
List<GroupSection> groupSectionList = this.groupSectionDAO.listModifiedSectionsForYesterday();
for (GroupSection yesterdaySection : groupSectionList) {
yesterdaySection.setLatestSection(false);
this.groupSectionDAO.updateGroupSection(yesterdaySection);
GroupSection newDaySection = new GroupSection();
BeanUtils.copyProperties(yesterdaySection, newDaySection);
newDaySection.setInitialSection(false);
newDaySection.setSectionModified(false);
newDaySection.setLatestSection(true);
newDaySection.setMsectionid(0);
newDaySection.setSortedSectionSet(null);
newDaySection.setSecnSavedDate(Calendar.getInstance().getTime());
int sectionSavedId = directAddGroupSection(newDaySection, yesterdaySection.getCurrentCanvasId());
List<GroupNotes> groupNotesList = this.groupNotesService.directListGroupNotesBySectionIdForCanvasCopying(yesterdaySection.getMsectionid());
newDaySection.setGroupNotesSet(groupNotesList);
}
return this.groupSectionDAO.listModifiedSectionsForYesterday();
}
Ответ 3
Как насчет того, что @ManyToOne для GroupNote → GroupSection, вместо ссылки GroupNote в GroupSection?
При изменении любого GroupSection вы можете просто обновить GroupSection и дату его изменения. Если вы хотите, чтобы GroupNote также обновлялся, вы можете обрабатывать его на уровне сервиса, используя отдельный запрос.