若是想要詳細瞭解一下Jackson,能夠去其github上的項目主頁查看其版本狀況以及各項功能。除此之外,須要格外提一下Jackson的版本問題。Jackson目前主流版本有兩種,1.x和2.x,而這兩者的核心包是不一樣的。在2.0之後的Jackson版本中,groupId從原來的org.codehaus.jackson.core轉而變成了com.fasterxml.jackson.core。因此若是但願用到新性能的Jackson,請將原來的maven依賴改成如下的依賴。html
下文中的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
前端
剛開始上手springmvc的時候並無詳細去了解更多的JSON操做,只是簡單的瞭解了一下如何將對象轉化爲JSON數據傳送回前端。可是在這時出現了一個問題,就是當兩個entity之間存在雙向依賴時,傳回的JSON數據會出現無限的讀取狀況。也就是說,由於兩個實體中都存在着指向對方的指針,致使序列化的時候會出現兩者之間不斷相互訪問的狀況。hibernate這種實體設計方式一直讓我有些困惑,畢竟在通常代碼的設計模式中是應當儘可能避免出現雙向依賴的。java
這裏舉一個具體的例子說明這個狀況。
假設我有一個訂單,訂單中有多個商品。也就是訂單和商品之間是一對多的關係。訂單和商品的實體類以下:git
訂單實體類github
import org.hibernate.annotations.Fetch; import org.hibernate.annotations.FetchMode; import javax.persistence.*; import java.util.ArrayList; import java.util.Date; import java.util.List; /** * Created by rale on 7/15/17. * 銷售單 */ @Entity @Table(name="sales_order") public class SalesOrder { @Id @Column(name = "sales_order_id") private Long salesOrderId; /**訂單建立人員**/ @Column(name = "salesman_id", nullable = false) private Long userId; @Temporal(TemporalType.TIMESTAMP) @Column(name = "sales_order_created_at") private Date createAt; /**訂單中商品列表清單**/ @OneToMany(mappedBy = "salesOrder", cascade = CascadeType.ALL, orphanRemoval = true) @OrderBy(value = "order_item_id") @Fetch(FetchMode.JOIN) private List<SalesOrderItem> salesOrderItems; public Long getSalesOrderId() { return salesOrderId; } public void setSalesSource(SalesSource salesSource) { this.salesSource = salesSource; } public Long getUserId() { return userId; } public void setUserId(Long userId) { this.userId = userId; } public Date getCreateAt() { return createAt; } public void setCreateAt(Date createAt) { this.createAt = createAt; } public List<SalesOrderItem> getSalesOrderItems() { return salesOrderItems==null ? new ArrayList<SalesOrderItem>() : salesOrderItems; } public void setSalesOrderItems(List<SalesOrderItem> salesOrderItems) { this.salesOrderItems = salesOrderItems; } public void addSalesOrderItem(SalesOrderItem salesOrderItem){ if (this.salesOrderItems == null) this.salesOrderItems = new ArrayList<SalesOrderItem>(); salesOrderItem.setSalesOrder(this); this.salesOrderItems.add(salesOrderItem); } }
訂單商品實體類面試
import javax.persistence.*; /** * 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; } }
解決雙向依賴的方法以下:ajax
在不但願被序列化的field或property上使用@JsonIgnore
標記,便可使該屬性在序列化和解序列化的過程當中不被訪問。spring
@Entity @Table(name="sales_order") public class SalesOrder { ... /**訂單中商品列表清單**/ @OneToMany(mappedBy = "salesOrder", cascade = CascadeType.ALL, orphanRemoval = true) @OrderBy(value = "order_item_id") @Fetch(FetchMode.JOIN) private List<SalesOrderItem> salesOrderItems; ... //getters and setters } @Entity @Table(name = "sales_order_item") public class SalesOrderItem { ... //對應的銷售單實體類 @ManyToOne @JoinColumn(name = "order_id") @JsonIgnore private SalesOrder salesOrder; ... //getters and setters }
這裏可能會出現不適用的場景,好比說,當我但願從SalesOrderItem的方向獲取SalesOrder的數據,將會出現沒法被序列化的狀況。json
這裏須要特別強調一下 不要使用transient標記屬性 會報錯
將@JsonManagedReference
標記在父類對子類的引用變量上,並將@JsonBackReference
標記在子類對父類的引用變量上。設計模式
@Entity @Table(name="sales_order") public class SalesOrder { ... /**訂單中商品列表清單**/ @OneToMany(mappedBy = "salesOrder", cascade = CascadeType.ALL, orphanRemoval = true) @OrderBy(value = "order_item_id") @Fetch(FetchMode.JOIN) @JsonManagedReference private List<SalesOrderItem> salesOrderItems; ... //getters and setters } @Entity @Table(name = "sales_order_item") public class SalesOrderItem { ... //對應的銷售單實體類 @ManyToOne @JoinColumn(name = "order_id") @JsonBackReference private SalesOrder salesOrder; ... //getters and setters }
經過這種方式確保在雙向關係中只有單個反向的實例被序列化
該annotation用於標註在entity上。當entity被標註後,jackson在每一次序列化的時候都會爲該實例生成專門的ID(也能夠是實例自帶的屬性),經過這種方式辨別實例。這種方式適用於存在一個實體關聯鏈的場景
。好比Order -> OrderLine -> User -> Order
@Entity @Table(name="sales_order") @JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="@id") public class SalesOrder { ... /**訂單中商品列表清單**/ @OneToMany(mappedBy = "salesOrder", cascade = CascadeType.ALL, orphanRemoval = true) @OrderBy(value = "order_item_id") @Fetch(FetchMode.JOIN) private List<SalesOrderItem> salesOrderItems; ... //getters and setters } @Entity @Table(name = "sales_order_item") @JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="@id") public class SalesOrderItem { ... //對應的銷售單實體類 @ManyToOne @JoinColumn(name = "order_id") private SalesOrder salesOrder; ... //getters and setters }
@JsonIgnoreProperties不一樣於@JsonIgnore在於,你能夠註明該變量中的哪一個屬相不被序列化。從而容許在雙向訪問上都不存在環或是缺失。
@Entity @Table(name="sales_order") public class SalesOrder { ... /**訂單中商品列表清單**/ @OneToMany(mappedBy = "salesOrder", cascade = CascadeType.ALL, orphanRemoval = true) @OrderBy(value = "order_item_id") @Fetch(FetchMode.JOIN) @JsonIgnoreProperties("salesOrder") private List<SalesOrderItem> salesOrderItems; ... //getters and setters } @Entity @Table(name = "sales_order_item") public class SalesOrderItem { ... //對應的銷售單實體類 @ManyToOne @JoinColumn(name = "order_id") @JsonIgnoreProperties("salesOrderItems") private SalesOrder salesOrder; ... //getters and setters }
其實jackson中還有不少很實用的功能,例如如何將Date類序列化成界面展現的格式等,將在下一次更新中說明。有興趣的能夠收藏加關注哦。
springmvc + ajax 實現
http://www.mkyong.com/spring-...
jackson annotation教程
http://tutorials.jenkov.com/j...
stack overflow上相關問題回答
https://stackoverflow.com/que...
https://stackoverflow.com/que...
https://stackoverflow.com/que...
這裏須要指出的是,雖然某些回答說,要將annotation標註在私有變量的get方法上,可是po主發現標註在私有變量上仍是能夠實現功能的。
data hiding using jsonignore and spring data jpa
https://dzone.com/articles/da...
想要了解更多開發技術,面試教程以及互聯網公司內推,歡迎關注個人微信公衆號!將會不按期的發放福利哦~