簡體   English   中英

在Spring 4.0中使用Jackson2(MVC + REST + Hibernate)

[英]Using Jackson2 with Spring 4.0 (MVC + REST+ Hibernate)

我正在制作一個安靜的應用程序並嘗試將對象列表轉換為json以獲取特定的URL(@RequestMapping / @ResponseBody)

我的classpath中有jackson-hibernate4和jackson-core,databind等。

這是我想要轉換為json的對象。

@Entity
@Table(name="Product")
public class Product {
@Id
@Column(name="productId")
@GeneratedValue
protected int productId;
@Column(name="Product_Name")
protected String name;

@Column(name="price")
protected BigDecimal baseprice;


@OneToMany(cascade = javax.persistence.CascadeType.ALL,mappedBy="product",fetch=FetchType.EAGER)
protected List<ProductOption> productoption = new ArrayList<ProductOption>();

@OneToMany(cascade = javax.persistence.CascadeType.ALL,mappedBy="product",fetch=FetchType.EAGER)
protected List<ProductSubOption> productSubOption = new ArrayList<ProductSubOption>();


@ManyToOne
@JoinColumn(name="ofVendor")
protected Vendor vendor;

Product里面的兩個對象也是POJO'S ..

這是我檢索產品列表的方法

@Override
public List<Product> getMenuForVendor(int vendorId) {
    List<Product> result = em.createQuery("from "+Product.class.getName()+" where ofVendor = :vendorId").setParameter("vendorId", vendorId).getResultList();
    System.out.println(result.size());
    return result;
}

當我嘗試在我的控制器中返回此列表時,我得到了“不能懶惰加載json”所以我設置我的對象急切地獲取。 這是我的控制器

@Autowired
private MenuDaoImpl ms;

@RequestMapping(value = "/{vendorId}", method = RequestMethod.GET)
public @ResponseBody List<Product> getMenu(@PathVariable int vendorId){

    List<Product> Menu = Collections.unmodifiableList(ms.getMenuForVendor(vendorId));
    return Menu;
}

現在,當我點擊我的網址localhost:8080 / getMenu / 1我應該顯示一個json字符串,但我得到一個很大的錯誤列表

WARN : org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver -       Handling of [org.springframework.http.converter.HttpMessageNotWritableException] resulted in Exception
  java.lang.IllegalStateException: Cannot call sendError() after the response has been     committed
at org.apache.catalina.connector.ResponseFacade.sendError(ResponseFacade.java:467)
 Could not write JSON: Infinite recursion (StackOverflowError) (through reference chain:

我不確定我是否遺漏了任何東西。 請指導。

我使用@JsonBackReference解決了@ManyToOne綁定和@OneToMany綁定的@JsonManagedReference。

謝謝“Sotirios Delimanolis”

問題已經得到解答。 我只是把一個很好的例子的鏈接清楚地解釋了問題和解決方案。 http://geekabyte.blogspot.in/2013/09/fixing-converterhttpmessagenotwritablee.html

我意識到這可能不是100%你所追求的,但從來沒有那么少,我覺得分享它,因為我花了很多時間來回應這個問題。

此外,您可以考慮使用自定義Json解析器,而不是使用Json注釋。 確保使用Jackson jar的正確包裝,因為他們最近改變了他們的包裝結構(當你使用其中任何一個數字為2的類時,如下所示)。

首先創建一個HttpMessageConverter:

   @Bean
    public HttpMessageConverter jacksonMessageConverter() {
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        converter.setPrefixJson(false);
        converter.setPrettyPrint(true);
        converter.setObjectMapper(objectMapper());
        return converter;
    }

添加一個ObjectMapper,您可以在其中附加映射模塊並附加您將使用的序列化程序。

public ObjectMapper objectMapper() {
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.configure(SerializationFeature.INDENT_OUTPUT, true);

    SimpleModule module = new SimpleModule("jacksonJsonMapper", Version.unknownVersion());
    module.addSerializer(Product.class, new Product());

    objectMapper.registerModule(module);

    return objectMapper;
}

現在創建一個序列化器。 這個類將提供你在獲取對象時看到的輸出,傑克遜將完成其余的工作。 你只需提供它應該如何看的骨架。

public class Product erializer extends JsonSerializer<Product> {

@Override
public void serialize(Product product, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
    if(product == null) { 
        //Handle it, if you want 
    }

    if(product != null) {

        jsonGenerator.writeStartObject();

        jsonGenerator.writeStringField("id", productId.getId().toString());
        jsonGenerator.writeStringField("title",  product.getName());
        jsonGenerator.writeStringField("basePrice", product.getBasePrice());


        //Add items to the json array representation
        jsonGenerator.writeArrayFieldStart("productoptions");
        for(ProductOption productOption: product.getProductoption()) {
            jsonGenerator.writeStartObject("field", productOption.getFoo());

            jsonGenerator.writeEndObject();
        }
        jsonGenerator.writeEndArray();

        jsonGenerator.writeEndObject();
    }
}

}

在旁注中,但我仍然希望它有用:您需要確保在懶惰地獲取實體時有可用的事務。 你還應該記住,懶惰是加載實體的首選方式,除非你想在每次獲取任何引用時徹底粉碎你的服務器。

嘗試通過在其上添加@Transactional來更改獲取數據的方法,以確保在其運行時為該方法打開事務,如果不是,則在您嘗試獲取子對象時可能會關閉該事務。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM