【问题标题】:Spring-MVC, Hibernate : Creating DTO objects from Domain objectsSpring-MVC,Hibernate:从域对象创建 DTO 对象
【发布时间】:2015-06-17 11:10:57
【问题描述】:

我正在开发一个 Spring-MVC 应用程序,我正在尝试在数据库中搜索 GroupNotes 列表。我项目中的映射是 GroupCanvas 与 GroupSection 具有一对多映射,而 GroupSection 与 GroupNotes 具有一对多映射。由于这些映射,我得到了 LazyInitializationException。正如 SO 所建议的那样,我应该将对象转换为 DTO 对象以进行传输。我在网上查过,但找不到合适的翻译方式。

我刚刚创建了一个新列表以避免错误,但一个字段仍然给我一个错误。如果有人告诉我如何修复此错误或将对象转换为 DTO 对象以便可以传输它们,我将不胜感激。

控制器代码:

 @RequestMapping(value = "/findgroupnotes/{days}/{canvasid}")
    public @ResponseBody List<GroupNotes> findGroupNotesByDays(@PathVariable("days")int days, @PathVariable("canvasid")int canvasid){
        List<GroupNotes> groupNotesList = this.groupNotesService.findGroupNotesByDays(days,canvasid);

        List<GroupNotes> toSendList = new ArrayList<>();
        for(GroupNotes groupNotes : groupNotesList){
            GroupNotes toSendNotes = new GroupNotes();
            toSendNotes.setMnotecolor(groupNotes.getMnotecolor());
            toSendNotes.setNoteCreationTime(groupNotes.getNoteCreationTime());
            toSendNotes.setMnotetag(groupNotes.getMnotetag());
            toSendNotes.setMnotetext(groupNotes.getMnotetext());
            toSendNotes.setAttachCount(groupNotes.getAttachCount());
            toSendNotes.setNoteDate(groupNotes.getNoteDate());
            toSendList.add(toSendNotes);
        }
        return toSendList;

    }

GroupNotesDAOImpl :

 @Override
    public List<GroupNotes> searchNotesByDays(int days, int mcanvasid) {
        Session session = this.sessionFactory.getCurrentSession();
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DAY_OF_YEAR, -days);
        long daysAgo = cal.getTimeInMillis();
        Timestamp nowMinusDaysAsTimestamp = new Timestamp(daysAgo);
        GroupCanvas groupCanvas = (GroupCanvas) session.get(GroupCanvas.class,mcanvasid);
        Query query = session.createQuery("from GroupSection as n where n.currentcanvas.mcanvasid=:mcanvasid");
        query.setParameter("mcanvasid", mcanvasid);

        List<GroupSection> sectionList = query.list();
        List<GroupNotes> notesList = new ArrayList<GroupNotes>();
        for (GroupSection e : sectionList) {
            System.out.println("Section name is "+e.getMsectionname());
            GroupSection groupSection = (GroupSection) session.get(GroupSection.class,e.getMsectionid());
            Query query1 = session.createQuery("from GroupNotes as gn where gn.ownednotes.msectionid=:msectionid and gn.noteCreationTime >:limit");
            query1.setParameter("limit", nowMinusDaysAsTimestamp);
            query1.setParameter("msectionid",e.getMsectionid());
            notesList.addAll(query1.list());
        }
// I am getting the data below, but I get JSON errors.
        for(GroupNotes groupNotes : notesList){
            System.out.println("Group notes found are "+groupNotes.getMnotetext());
        }
        return notesList;
    }

GroupCanvas 模型:

@Entity
@Table(name = "membercanvas")
public class GroupCanvas{
  @OneToMany(mappedBy = "currentcanvas",fetch=FetchType.LAZY, cascade = CascadeType.REMOVE)
    @JsonIgnore
    private Set<GroupSection> ownedsection = new HashSet<>();

    @JsonIgnore
    public Set<GroupSection> getOwnedsection() {
        return this.ownedsection;
    }

    public void setOwnedsection(Set<GroupSection> ownedsection) {
        this.ownedsection = ownedsection;
    }
}

GroupSection 模型:

@Entity
@Table(name = "membersection")
public class GroupSection{

    @OneToMany(mappedBy = "ownednotes", fetch = FetchType.EAGER,cascade = CascadeType.REMOVE)
    @JsonIgnore
    private Set<GroupNotes> sectionsnotes = new HashSet<>();

    public Set<GroupNotes> getSectionsnotes(){
        return this.sectionsnotes;
    }

    public void setSectionsnotes(Set<GroupNotes> sectionsnotes){
        this.sectionsnotes=sectionsnotes;
    }
}

GroupNotes 模型:

@Entity
@Table(name="groupnotes")
public class GroupNotes{

    @Id
    @Column(name="mnoteid")
    @GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "mnote_gen")
    @SequenceGenerator(name = "mnote_gen",sequenceName = "mnote_seq")
    @org.hibernate.annotations.Index(name = "mnoticesidindex")
    private int mnoticesid;

    @Column(name = "mnotetext")
    private String mnotetext;

    @Column(name = "mnoteheadline")
    private String mnotetag;

    @Column(name = "mnotecolor")
    private String mnotecolor;

    @Column(name = "mnoteorder")
    private double mnoteorder;

    @Column(name = "attachmentcount")
    private int attachCount;

    @Column(name = "notedate")
    private String noteDate;

    @Column(name = "uploader")
    private String uploader;

    @Column(name = "activeedit")
    private boolean activeEdit;

    @Column(name = "notedisabled")
    private boolean noteDisabled;

    @Column(name = "noteinactive")
    private boolean noteInActive;

    @Column(name = "notecreatoremail")
    private String noteCreatorEmail;

    @Column(name = "prefix")
    private String prefix;

    @Column(name = "timestamp")
    private Timestamp noteCreationTime;

    @Transient
    private boolean notRead;

    @Transient
    private String tempNote;

    @Transient
    private String canvasUrl;

    @ManyToOne
    @JoinColumn(name = "msectionid")
    @JsonIgnore
    private GroupSection ownednotes;

    @JsonIgnore
    public GroupSection getOwnednotes(){return this.ownednotes;}

    public void setOwnednotes(GroupSection ownednotes){this.ownednotes=ownednotes;}

    @JsonIgnore
    public int getOwnedSectionId(){
        return this.ownednotes.getMsectionid();
    }

    @OneToMany(mappedBy = "mnotedata",fetch = FetchType.LAZY,cascade = CascadeType.REMOVE)
    @JsonIgnore
    private Set<GroupAttachments> mattachments = new HashSet<>();

    public Set<GroupAttachments> getMattachments() {
        return this.mattachments;
    }

    public void setMattachments(Set<GroupAttachments> mattachments) {

        this.mattachments = mattachments;
    }

    @OneToMany(mappedBy = "mhistory",fetch = FetchType.LAZY,cascade = CascadeType.REMOVE)
    @JsonIgnore
    private Set<GroupNoteHistory> groupNoteHistorySet = new HashSet<>();

    public Set<GroupNoteHistory> getGroupNoteHistorySet(){
        return this.groupNoteHistorySet;
    }

    public void setGroupNoteHistorySet(Set<GroupNoteHistory> groupNoteHistorySet){
        this.groupNoteHistorySet = groupNoteHistorySet;
    }

    @OneToMany(mappedBy = "unreadNotes",fetch = FetchType.LAZY,cascade = CascadeType.REMOVE)
    @JsonIgnore
    private Set<UnreadNotes> unreadNotesSet = new HashSet<>();

    public Set<UnreadNotes> getUnreadNotesSet(){
        return this.unreadNotesSet;
    }

    public void setUnreadNotesSet(Set<UnreadNotes> unreadNotesSet){
        this.unreadNotesSet = unreadNotesSet;
    }
//getters and setters ignored
}

错误日志:

org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: (was java.lang.NullPointerException) (through reference chain: java.util.ArrayList[0]->com.journaldev.spring.model.GroupNotes["ownedSectionId"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: java.util.ArrayList[0]->com.journaldev.spring.model.GroupNotes["ownedSectionId"])

请让我知道该怎么做,因为一段时间以来我一直被这个错误困扰。

【问题讨论】:

  • 为什么你有@JsonIgnoreProperties({"ownedSectionId"}) 而你的班级却没有这样的属性?
  • @NikolayRusev :这是我得到的变量错误,所以我正在尝试。我以前没有,但我有同样的问题。你能帮我解决这个问题吗?
  • 我正在尝试找出问题所在:)
  • @NikolayRusev :如果您需要更多代码或信息,请告诉我。
  • 你有另一个组笔记dto对象吗?如果是,请发布代码

标签: java spring hibernate spring-mvc dto


【解决方案1】:

我认为发生的情况是 Jackson 尝试基于 getter 方法序列化层次结构中的所有字段。在某些情况下,NullPointerException 在以下方法中被抛出:

@JsonIgnore
public int getOwnedSectionId(){
    return this.ownednotes.getMsectionid();
}

用以下方法替换它:

@JsonIgnore
public int getOwnedSectionId(){
    if(this.ownednotes != null)
        return this.ownednotes.getMsectionid();
    return 1;
}

我没有解释为什么杰克逊会在@JsonIgnore 上市时尝试对其进行序列化,但您可以尝试我的建议

【讨论】:

  • 这行得通。非常感谢。但是为什么 JsonIgnore 不被尊重?我一定会标记你的答案。
  • 我不确定。我必须研究一下才能告诉你原因。我有一些建议,但我不确定。尝试从字段中删除@JsonIgnore:@JsonIgnore public GroupSection getOwnednotes(){return this.ownednotes;}
  • 这没有帮助。只要你有时间,请帮助我理解这一点。非常感谢。 :-)
【解决方案2】:

如果有人告诉我如何修复此错误或将对象转换为 DTO 对象以便传输它们,我将不胜感激。

为此,我们在工作中使用DozerMapper

【讨论】:

    【解决方案3】:

    您可能想看看Blaze-Persistence Entity Views,而不是手动进行映射,它可用于通过 JPA 有效地实现 DTO 模式。这是如何解决您的问题的快速代码示例

    首先将 DTO 定义为实体视图

    @EntityView(GroupNotes.class)
    public interface GroupNoteView {
        @IdMapping("mnoticesid") int getId();
    
        String getMnotecolor();
        String getMnotetag();
        String getMnotetext();
        String getNoteDate();
        Timestamp getNoteCreationTime();
        int getAttachCount();
    }
    

    接下来你调整你的 DAO 以利用它

    @Override
    public List<GroupNoteView> searchNotesByDays(int days, int mcanvasid) {
        EntityManager entityManager = // get the entity manager from somewhere
        CriteriaBuilderFactory cbf = // factory for query building from Blaze-Persistence
        EntityViewManager evm = // factory for applying entity views on query builders
    
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DAY_OF_YEAR, -days);
        long daysAgo = cal.getTimeInMillis();
        Timestamp nowMinusDaysAsTimestamp = new Timestamp(daysAgo);
    
        CriteriaBuilder<GroupNotes> cb = cbf.create(entityManager, GroupNotes.class, "note")
            .where("noteCreationTime").gt(nowMinusDaysAsTimestamp)
            .where("ownednotes.ownedcanvas.mcanvasid").eq(mcanvasid);
    
        return evm.applySetting(EntityViewSetting.create(GroupNoteView.class), cb)
            .getResultList();
    }
    

    最后是调用代码

    @RequestMapping(value = "/findgroupnotes/{days}/{canvasid}")
    public @ResponseBody List<GroupNoteView> findGroupNotesByDays(@PathVariable("days")int days, @PathVariable("canvasid")int canvasid){
        return this.groupNotesService.findGroupNotesByDays(days, canvasid);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-22
      • 1970-01-01
      • 2014-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多