2014-04-18 45 views
4

我很难搞清楚如何在Web应用程序中正确定义和注释模型,以便它们可以有效地用于Web界面和REST Web服务。这是给我找麻烦的关系的简化版本:序列化与Spring MVC,Jackson和Hibernate的多对多关系的对象

Post模型:

@Entity 
@Table(name = "POST") 
public class Post implements Serializable { 

    @Id 
    @Column(name = "POST_ID") 
    @GeneratedValue(strategy-GenerationType.AUTO) 
    private Integer postId; 

    @Column(name = "POST_BODY") 
    private String postBody; 

    @ManyToMany(fetch = FetchType.EAGER) 
    @Cascade({CascadeType.SAVE_UPDATE}) 
    @JoinTable(name = "POST_TAGS", 
      joinColumns={@JoinColumn(name="POST_ID")}, 
      inverseJoinColumns={@JoinColumn(name="TAG_ID")}) 
    private Set<Tag> tags = new HashSet<Tag>(); 

    //Getters and setters... 
} 

标签模式

@Entity 
@Table(name = "TAG") 
public class Tag implements Serializable { 

    @Id 
    @Column(name = "TAG_ID") 
    @GeneratedValue(strategy-GenerationType.AUTO) 
    private Integer tagId; 

    @Column(name = "TAG_NAME") 
    private String tagName; 

    @ManyToMany(fetch = FetchType.EAGER, mappedBy="tags") 
    private Set<Post> posts = new HashSet<Post>(); 

    //Getters and setters... 
} 

我有获取一个网络服务控制器的方法所有帖子和一个获取所有标签的方法。理想情况下,每种方法都应该返回目标类和被引用类的列表。例如:

[{ 
    postId: 1, 
    postBody: "Hello world!", 
    tags: [{ 
     tagId: 1, 
     tagName: "hello" 
    },{ 
     tagId: 2, 
     tagName: "message" 
    }] 
}, { 
    postId: 2, 
    .... 
}] 

但我风看到的内容是无限递归,作为返回的标签为每个职位检索其相关联的支柱,其检索及其关联的标记等,以无穷大。我曾尝试在我的类的getter方法上使用@JsonIgnore,但后来我不再获取引用的对象。我曾尝试使用@JsonIdentityInfo将ID添加到我的对象,但是我仍然得到递归,但仅限于检索到的对象之间的所有引用都耗尽的点。我似乎无法找到解释如何处理这些情况的任何文档,这看起来很常见。

回答

0

您可以对此使用Jackson的注释(@JsonManagedReference@JsonBackReference)。

检查http://wiki.fasterxml.com/JacksonFeatureBiDirReferences

或者你可以写自己的串行器与跟踪你已经连载了什么,这是我落得这样做的时候,我不得不使用GSON而不是杰克逊。

+0

虽然这个例子中'@ JsonManagedReference'和'@ JsonBackReference'如何工作?根据上下文,“Post”和“Tag”都可以是父母或孩子。 – woemler

+0

嗯,我想我错过了这部分的问题。您仍然可以为这些对象创建自己的序列化程序,然后跟踪已经序列化的内容。 –

0

我写了杰克逊休眠模块的详细用法(https://github.com/FasterXML/jackson-datatype-hibernate) 对不起,我的英文不好。如下所示,如果我们使用默认的jackson + jackson-databind模块 - 我们在多对多序列化方面遇到了一些麻烦。如果我们不使用@JsonIgnore + @JsonIdentityInfo注释,这是一个“无限循环”。如果我们同时使用它们,它就是“ID作为结果”。

解决烦恼的最佳方法 - 使用模块。 1.添加行家DEP

<dependency> 
     <groupId>com.fasterxml.jackson.datatype</groupId> 
     <artifactId>jackson-datatype-hibernate4</artifactId> 
     <version>${jackson.version}</version> 
</dependency> 
  • 创建和使用定制ObjectMapper
  • HibernateAwareObjectMapper.java

    import com.fasterxml.jackson.databind.ObjectMapper; 
    import com.fasterxml.jackson.datatype.hibernate4.Hibernate4Module; 
    
    public class HibernateAwareObjectMapper extends ObjectMapper { 
    
        public HibernateAwareObjectMapper() { 
         registerModule(new Hibernate4Module()); 
        } 
    } 
    

    3.使用此映射器在春季XML配置

    <mvc:annotation-driven> 
         <mvc:message-converters> 
          <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> 
           <property name="objectMapper"> 
            <bean class="path.HibernateAwareObjectMapper"/> 
           </property> 
          </bean> 
         </mvc:message-converters> 
        </mvc:annotation-driven> 
    
    1. 向实体字段添加注释。

    邮政实体不需要注释。

    标记实体为修复“无限循环”错误添加@JsonIgnore注释。

    此外,我们可以将EAGER更改为LAZY fetchtype。通过ObjectMapper config获取规则FORCE_LAZY_LOADING 更多关于javadoc的信息(http://fasterxml.github.io/jackson-datatype-hibernate/javadoc/h4-2.4/com/fasterxml/jackson/datatype/hibernate4/Hibernate4Module.Feature.html#FORCE_LAZY_LOADING)或github上的代码