2015-07-13 41 views
1

我正在开发一个在前端使用BackboneJS并在后端使用Java - Spring核心的项目。我有一个将实体(域)对象映射到DTO对象的问题。我收到一条错误消息,这样的:集合映射与推土机时的无限循环

org.apache.cxf.interceptor.Fault: Infinite recursion (StackOverflowError) (through reference chain: com.countdown.dto.CategoryDTO["countdownList"]->java.util.ArrayList[0]->com.countdown.dto.CountdownDTO["category"]->.......

User.java

@Entity 
@Table(name = "Users") 
public class User implements Serializable { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    @Column(name = "USER_ID", nullable = false) 
    private int id; 

    @Column(name = "EMAIL", nullable = false, unique = true) 
    private String email; 

    @Column(name = "NAME_SURNAME", nullable = false) 
    private String nameSurname; 

    @Column(name = "PASSWORD", nullable = false) 
    private String password; 

    @Column(name = "USERNAME", nullable = false, unique = true) 
    private String username; 

    @Column(name = "REGISTER_DATE", nullable = false) 
    private Date registerDate; 

    @ManyToOne 
    @JoinColumn(name = "ROLE_ID") 
    private Role role; 

    @OneToMany(mappedBy = "createUser") 
    private List<Countdown> createCountdownList = new ArrayList<Countdown>(); 

    @OneToMany(mappedBy = "updateUser") 
    private List<Countdown> updateCountdownList = new ArrayList<Countdown>(); 

    @ManyToMany 
    @JoinTable(name = "FOLLOWINGS", 
      joinColumns = @JoinColumn(name = "USER_ID"), 
      inverseJoinColumns = @JoinColumn(name = "COUNTDOWN_ID")) 
    private List<Countdown> followings = new ArrayList<Countdown>(); 

    //Getters and setters.. 

} 

Role.java

@Entity 
public class Role implements Serializable { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    @Column(name = "ROLE_ID") 
    private int id; 

    @Column(name = "ROLE_NAME", nullable = false) 
    private String roleName; 

    @OneToMany(mappedBy = "role",fetch = FetchType.LAZY) 
    List<User> userList = new ArrayList<User>(); 
} 

Countdown.java

@Entity 
@Table(name = "COUNTDOWN") 
public class Countdown implements Serializable { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    @Column(name = "COUNTDOWN_ID") 
    private int id; 

    @Column(name = "COUNTDOWN_NAME", nullable = false) 
    private String countdownName; 

    @Column(name = "COUNTDOWN_DATE", nullable = false) 
    private Date countdownDate; 

    @Column(columnDefinition = "varchar(5000)") 
    private String countdownDescription; 

    @JoinColumn(name = "CATEGORY_ID", nullable = false) 
    @ManyToOne 
    private Category category; 

    @JoinColumn(name = "CREATE_USER", nullable = false) 
    @ManyToOne 
    private User createUser; 

    @Column(name = "CREATE_DATE", nullable = false) 
    private Date createDate; 

    @JoinColumn(name = "UPDATE_USER", nullable = false) 
    @ManyToOne 
    private User updateUser; 

    @Column(name = "UPDATE_DATE", nullable = false) 
    private Date updateDate; 

    @Column(name = "CREATE_USER_IP", nullable = false) 
    private int createIP; 

    @ManyToMany 
    private List<User> followers = new ArrayList<User>(); 

} 

Category.java

@Entity 
@Table(name="CATEGORY") 
public class Category implements Serializable{ 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    @Column(name="CATEGORY_ID") 
    private int id; 

    @Column(name = "CATEGORY_NAME" , nullable = false) 
    private String categoryName; 

    @OneToMany(mappedBy = "category") 
    private List<Countdown> countdownList = new ArrayList<Countdown>(); 

} 

业务逻辑:CategoryServiceImpl.java 我收到错误forEach循环。

@Transactional(readOnly = true) 
public List<CategoryDTO> getAllCategories() { 
    List<Category> categoryList; 
    List<CategoryDTO> categoryDTOList = new ArrayList<CategoryDTO>(); 

    logger.debug("getAllCategories called"); 

    try { 
     categoryList = categoryDAO.findAll(); 
     for(Category category : categoryList){ 
      categoryDTOList.add(mapper.map(category,CategoryDTO.class)); 
     } 
    }catch (NoResultException e){ 
     logger.error("getAllCategories method : No Category wasn't found"); 
     logger.warn(e,e); 
    }catch (Exception e){ 
     logger.error("getAllCategories method : Categories wasn't found"); 
     logger.warn(e,e); 
    } 
    return categoryDTOList; 
} 

另外我是否必须在表示层使用DTO对象?我可以在表示层中使用实体对象而不是DTO对象吗?

我该如何解决这个问题?对不起,我英语不好。谢谢!

+0

如果是这样请接受/投票 – ozgur

回答

1

请尝试:

@Transactional(readOnly = true) 
    public List<CategoryDTO> getAllCategories() { 
     List<Category> categoryList; 
     List<CategoryDTO> categoryDTOList = new ArrayList<CategoryDTO>(); 

     logger.debug("getAllCategories called"); 

     try { 
      categoryList = categoryDAO.findAll(); 

      for(Category category : categoryList){ 
        if(category.getCountdownList() != null && !category.getCountdownList().isEmpty()){ 
         for(Countdown countdown : category.getCountdownList()){ 
          countdown.setCategory(null); 
         } 
        } 
       categoryDTOList.add(mapper.map(category,CategoryDTO.class)); 
      } 
     }catch (NoResultException e){ 
      logger.error("getAllCategories method : Hata: No Category wasn't found"); 
      logger.warn(e,e); 
     }catch (Exception e){ 
      logger.error("getAllCategories method : Hata: Categories wasn't found"); 
      logger.warn(e,e); 
     } 
     return categoryDTOList; 
    } 
+0

谢谢你的回答,但在if语句中IDE无法识别类别对象。 http://imgur.com/IGFJN6t –

+0

对不起。我写的不对。 代码现在已更新。 – ozgur

+0

我试过了,但我现在得到这个错误: 引起:org.postgresql.util.PSQLException:错误:列“category_id”中的空值违反了非空约束。 我认为我们将null设置为id列。 –

0

对于那些谁在用推土机无限递归问题挣扎。

我使用mapId来定义一个叶对象并停止递归。

让我们假设有两个实体CourseTeacher,其中包含多到许多关系,我们希望下面的对象图转换为通过CourseDTOTeacherDto代表之一。我们希望推土机在第三级停止。

Teacher 1 ---> m Course 1 ---> m Teacher ---> ... 
1st level  2nd level  3rd level 

我们可以先定义Teacher以下定义TeacherDTO转换。

此第一个映射用于根Teacher实体。 在映射中包含您需要的任何其他字段。

mapping(Teacher.class, TeacherDTO.class, 
        TypeMappingOptions.oneWay() 
        , mapNull(false) 
      ).fields("courses", "courses"); 

以下映射将防止推土机从去进一步映射包含Course。我们为它定义一个mapId teacherLeaf。 排除导致无限递归的字段。 (在我的示例中,它是课程) 在映射中包含您需要的任何其他字段。

   mapping(Teacher.class, TeacherDTO.class, 
        TypeMappingOptions.oneWay(), TypeMappingOptions.mapId("teacherLeaf") 
        , mapNull(false) 
      ).exclude("courses"); 

最后一个是CoursecourseDTO映射规则。关键是我们告诉映射器使用前面定义的映射规则teacherLeaf来转换包含的Teacher

   mapping(Course.class, CourseDTO.class, 
        TypeMappingOptions.oneWay() 
        , mapNull(false) 
      ).fields("teachers", "teachers", useMapId("teacherLeaf")); 

希望这会有所帮助!

我使用推土机6.1.0。