首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Jackson2与Spring4.0 (MVC + REST+ Hibernate)

使用Jackson2与Spring4.0 (MVC + REST+ Hibernate)
EN

Stack Overflow用户
提问于 2014-03-04 21:13:48
回答 3查看 3.6K关注 0票数 5

我正在创建一个restful应用程序,并试图将对象列表转换为特定url的json (@RequestMapping / @ResponseBody )

我的类路径中有jackson-hibernate4 4和jackson-core、databind等。

这是我想在json中转换的对象。

代码语言:javascript
复制
@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;

产品内部的两个对象也是POJO的..。

下面是我检索产品列表的方法

代码语言:javascript
复制
@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加载”,所以我将我的对象设置为急切地被抓取。这是我的控制器

代码语言:javascript
复制
@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;
}

现在,当我访问url localhost:8080/getMenu/1时,应该会显示一个json字符串,但是我得到了一个错误列表。

代码语言:javascript
复制
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:

我不确定我是不是错过了什么。请指点。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-03-04 21:43:49

我为@ManyToOne绑定使用了@JsonBackReference,在@OneToMany绑定上使用了@JsonManagedReference。

谢谢“索提里奥斯·德里马诺利”

票数 12
EN

Stack Overflow用户

发布于 2014-11-04 09:55:08

这个问题已经回答了。我只是简单地提出一个很好的例子,清楚地解释了问题和解决方案。http://geekabyte.blogspot.in/2013/09/fixing-converterhttpmessagenotwritablee.html

票数 1
EN

Stack Overflow用户

发布于 2014-03-05 11:37:09

我意识到这可能不是你想要的100%,但从来没有少,我想分享它,因为我花了很多时间与这个问题在过去的日子里。

另外,您可以考虑使用自定义Json解析器,而不是使用Json注释。确保对Jackson jars使用正确的包,因为它们最近更改了它们的包结构(当您使用它们的类中有数字2的任何类时,如下所示)。

首先创建一个HttpMessageConverter:

代码语言:javascript
复制
   @Bean
    public HttpMessageConverter jacksonMessageConverter() {
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        converter.setPrefixJson(false);
        converter.setPrettyPrint(true);
        converter.setObjectMapper(objectMapper());
        return converter;
    }

添加一个ObjectMapper,在其中附加映射模块并附加将要使用的序列化器。

代码语言:javascript
复制
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;
}

现在创建一个序列化程序。这个类将提供您在获取对象时看到的输出,而Jackson将执行其余的操作。你只是提供了它应该是什么样的骨架。

代码语言:javascript
复制
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();
    }
}

}

顺便提一句,但我仍然希望这将是有用的:当您懒洋洋地获取实体时,您需要确保有一个事务可用。您还应该记住,懒散是加载实体的最好方式,除非每次获取引用时都要彻底粉碎服务器。

尝试更改获取数据的方法,在其上面添加@Trans显着,以确保该方法在运行时有一个事务打开,如果没有,则可能在尝试获取子对象时关闭它。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22183160

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档