【问题标题】:Avoiding creating duplicates for TImeline functionality in Spring避免在 Spring 中为 TImeline 功能创建重复项
【发布时间】:2016-06-13 16:10:35
【问题描述】:

我正在开发一个 Spring-MVC 项目,我目前正在为此开发 Timeline 功能。我的基础架构已经在进行中,但目前我正在处理映射,以及如何避免为时间轴功能创建重复项。

情况:

在我们的工具中,GroupSection 与 GroupNote 具有一对多的映射关系。 GroupNote 对象与附件、历史记录具有一对多的映射关系。

这个时间线功能是什么?

在时间轴功能中,任何用户都可以在任何时间点跳转并查看 GroupSection、GroupNotes、附件和历史记录的内容。

我打算如何实施它?

我在上述每个对象中都有 4 个变量来处理这个问题。它们是Date SavedDateboolean initialNoteboolean noteModifiedboolean latestNote

除此之外,每个GroupNote都有一个self-join,稍后会解释。

现在,每次修改注释时,修改标志都会设置为 true。晚上,我运行一个方法,它检查所有修改的对象,只有当对象被修改时,它才会为该对象创建一个重复的实例,将新的日期放入其中,将其标记为最新的,并将其持久化.

这样,我可以加载给定日期的所有对象。对于正常的日常使用,所有标记为latest 的笔记都会被加载。

每当为持久性创建新对象时,它都会与旧对象自联接,Cascade.Remove。这样做的目的是,如果用户返回并从 2015 年删除该对象,那么直到当前的所有后续对象也将被删除。这给出了类似时间的行为。

问题:

现在,如果 GroupSection 被修改,那么我将创建一个 GroupSection 实例并通过从修改后的 GroupSection 复制属性来持久化它,并将其标记为最新。

现在,GroupSection 持有的 Notes 没有被修改,但如果我不创建它的重复条目,那么我将看不到前端加载的任何 Notes。但我想避免这种情况。我该怎么做?

代码终于:

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 之间使用一对多映射进行开发。 尽管如此,我确实添加了多对多映射,但数据集没有被加载,而且它也增加了很多复杂性,一个正在进行的问题here。我仍然更喜欢其他选择。

【问题讨论】:

标签: java spring hibernate spring-mvc mapping


【解决方案1】:

我不确定我应该如何触发此删除功能。 对我来说,一个可行的策略是遵循一对多的关系 历史的 GroupSection(历史链中第一个被删除的)到相关的 GroupNotes。这种关系需要识别每个受影响的 GroupNotes 相应的历史实例并导致删除该实例。

在处理 GroupSections 时,您可能需要收集对这些 GroupNotes 的引用(我假设随着时间的推移,这个集合可能会发生变化) 并在最后清理结果集以避免反复检查 GroupNotes。

【讨论】:

    【解决方案2】:

    我建议将 GroupSection 和 GroupNotes 之间的关联更改为多对多,以避免重复的 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 for GroupNote -> GroupSection,而不是在 GroupSection 中引用 GroupNote 怎么样?

      当需要修改任何 GroupSection 时,您只需更新 GroupSection 及其修改日期即可。如果您希望 GroupNote 也被更新,您可以在服务级别通过单独的查询进行处理。

      【讨论】:

        【解决方案4】:

        我认为你应该试试这个想法。

        @ManyToOne for GroupNote -> GroupSection,而不是在 GroupSection 中引用 GroupNote?

        【讨论】:

          猜你喜欢
          • 2022-01-04
          • 2015-09-23
          • 2021-12-05
          • 1970-01-01
          • 2016-06-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多