• hibernate中因双向依赖而造成的json怪相--springmvc项目


    简单说一下Jackson

    如果想要详细了解一下Jackson,可以去其github上的项目主页查看其版本情况以及各项功能。除此以外,需要格外提一下Jackson的版本问题。Jackson目前主流版本有两种,1.x和2.x,而这二者的核心包是不同的。在2.0以后的Jackson版本中,groupId从原来的org.codehaus.jackson.core转而变成了com.fasterxml.jackson.core。所以如果希望用到新性能的Jackson,请将原来的maven依赖改为以下的依赖。

    下文中的jackson-2-version是指特定的版本,当前的稳定版本为2.8.9。想要了解最新的版本情况还请去项目主页或是maven官网上查看。但是如果是要和spring mvc配合使用的话,还要注意一下他们之间的兼容问题。目前我采用的是4.2.6版本的springmvc和2.6.6版本的jackson
    <!-- the core, which includes Streaming API, shared low-level abstractions (but NOT data-binding) -->
     <dependency>
       <groupId>com.fasterxml.jackson.core</groupId>
       <artifactId>jackson-core</artifactId>
       <version>${jackson-2-version}</version>
     </dependency>
    

    <!-- Just the annotations; use this dependency if you want to
    attach annotations to classes without connecting them to the code. -->

    <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>${jackson-2-version}</version>
    </dependency>

    <!-- databinding; ObjectMapper, JsonNode and related classes are here -->
    <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>${jackson-2-version}</version>
    </dependency>

    <!-- smile (binary JSON). Other artifacts in this group do other formats. -->
    <dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-smile</artifactId>
    <version>${jackson-2-version}</version>
    </dependency>
    <!-- JAX-RS provider -->
    <dependency>
    <groupId>com.fasterxml.jackson.jaxrs</groupId>
    <artifactId>jackson-jaxrs-json-provider</artifactId>
    <version>${jackson-2-version}</version>
    </dependency>
    <!-- Support for JAX-B annotations as additional configuration -->
    <dependency>
    <groupId>com.fasterxml.jackson.module</groupId>
    <artifactId>jackson-module-jaxb-annotations</artifactId>
    <version>${jackson-2-version}</version>
    </dependency>

    如果是在springmvc中配置maven依赖,则需要的依赖包为core,annotation和databind

    从一个bug说起

    刚开始上手springmvc的时候并没有详细去了解更多的JSON操作,只是简单的了解了一下如何将对象转化为JSON数据传送回前端。但是在这时出现了一个问题,就是当两个entity之间存在双向依赖时,传回的JSON数据会出现无限的读取情况。也就是说,因为两个实体中都存在着指向对方的指针,导致序列化的时候会出现二者之间不断相互访问的情况。hibernate这种实体设计方式一直让我有些困惑,毕竟在一般代码的设计模式中是应当尽量避免出现双向依赖的。


    这里举一个具体的例子说明这个情况。
    假设我有一个订单,订单中有多个商品。也就是订单和商品之间是一对多的关系。订单和商品的实体类如下:

    订单实体类

/**

  • Created by rale on 7/15/17.

  • 销售清单中的单品和数量
    */
    @Entity
    @Table(name = "sales_order_item")
    public class SalesOrderItem {
    @Id
    @GeneratedValue
    @Column(name = "order_item_id")
    private Long salesOrderItemId;

    @Column(name = "order_item_quantity")
    private int quantity;

    @Column(name = "order_item_price")
    private double salesPrice;

    //对应的销售单实体类
    @ManyToOne
    @JoinColumn(name = "order_id")
    private SalesOrder salesOrder;

    public SalesOrderItem() {
    }

    public SalesOrderItem(Long salesOrderItemId){
    this.salesOrderItemId = salesOrderItemId;
    }

    public Long getSalesOrderItemId() {
    return salesOrderItemId;
    }

    public void setSalesOrderItemId(Long salesOrderItemId) {
    this.salesOrderItemId = salesOrderItemId;
    }

    public int getQuantity() {
    return quantity;
    }

    public void setQuantity(int quantity) {
    this.quantity = quantity;
    }

    public double getSalesPrice() {
    return salesPrice;
    }

    public void setSalesPrice(double salesPrice) {
    this.salesPrice = salesPrice;
    }

    public SalesOrder getSalesOrder() {
    return salesOrder;
    }

    public void setSalesOrder(SalesOrder salesOrder) {
    this.salesOrder = salesOrder;
    }
    }

解决双向依赖的方法如下:

@JsonIgnore

在不希望被序列化的field或property上使用@JsonIgnore标记,即可使该属性在序列化和解序列化的过程中不被访问。