java - Web 服务接收对象时子对象丢失

标签 java rest jaxb jersey jax-rs

我有一个 RESTful Web 服务,可以为对象执行一些持久性操作。该对象有一些包含在集合中的子对象。一旦 Web 服务接收到该对象,子对象的集合就是空的。

我编写的调用该服务的代码如下所示:

//create a Foo
Foo f = new Foo();
FooAttribute fa = new FooAttribute();
fa.setFooId(f);
Collection<FooAttribute> fAttribColl = new Arraylist<FooAttribute>();
fAttribColl.add(fa);
//Add a collection of attributes
f.setFooAttributeCollection(fAttribColl);

f.setName("fooname");
WebResource resource = new WebResource();
//send f to the service.
Foo fNew = resource.path(URI+"/createFoo")
                   .accept(javax.ws.rs.core.MediaType.APPLICATION_XML)
                   .post(Foo.class, f);

持久性 Web 服务看起来像这样:

@Stateless
@Path("my.application.service.path")
public class MyFooService(){

    @Path("/createFoo")
    @POST
    @Consumes({ "application/json", "application/xml" })
    @Produces({ "application/xml" })
    public Foo createFoo(Foo f)
    {
        //Inspecting with the debugger shows that 
        //f.getFooAttributeCollection() returns an 
        //empty collection, even though it was populated in the client   code.
        this.getEntityManager().persist(f);
    }

如果我在 createFoo 的第一行设置断点并在调试器中检查 f,我可以看到 fooAttributeCollection 成员为空,即使其他“简单”成员(在本例中均为 String 类型)都具有正确的值。我不确定为什么集合对象是空的。

我不确定这是否重要,但 Foo 和 FooAttribute 的生成代码如下所示:

@Entity
@Table(name = "foo")
@XmlRootElement
public class Foo implements Serializable {
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "fooId")
    private Collection<FooAttribute> fooAttributeCollection;

    @XmlTransient
    public Collection<FooAttribute> getFooAttributeCollection() {
        return fooAttributeCollection;
    }

    public void setFooAttributeCollection(Collection<FooAttribute> fooAttributeCollection) {
        this.fooAttributeCollection = fooAttributeCollection;
    }
}

@Entity
@Table(name = "foo_attribute")
@XmlRootElement   
public class FooAttribute implements Serializable {
    @JoinColumn(name = "foo_id", referencedColumnName = "foo_id")
    @ManyToOne(optional = false)
    private Study fooId;

    public Foo getFooId() {
        return this.fooId;
    }
    public void setFooId(Foo f) {
        this.fooId = f;
    }
}

最佳答案

问题是 @XmlTransient

@XmlTransient
public Collection<FooAttribute> getFooAttributeCollection() {
    return fooAttributeCollection;
}

它会导致属性无法映射。只需使用 JAXB API 打印 Foo 即可看到发送之前对象

// Foo f = new Foo()
// set the collection like you did in your post
JAXBContext context = JAXBContext.newInstance(Foo.class);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
Unmarshaller unmarshaller = context.createUnmarshaller();

StringWriter writer = new StringWriter();
marshaller.marshal(f, writer);
System.out.println(writer.toString());

Result:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<foo/>

编码或解编码也是如此。因此,如果您尝试发送原始 xml,解码时 xml 元素仍然不会映射。

现在我确信您使用此注释的原因是为了避免循环引用。但这就是问题所在。一种选择是仅使用此类的 DTO。另外,我不使用 MOXy,但我发现它具有一些处理 JPA 双向关系的功能,就像您在这里所拥有的那样。

关于java - Web 服务接收对象时子对象丢失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29086219/

相关文章:

java - 使用 JAXB 处理丢失的节点

java - 如何为 Android 创建类似 iphone 的搜索

java - 是否存在使用 AWS SDK InitiateAuth 的 Camel 组件?

ios - 不工作 - 以编程方式在 Api 中注册用户

javascript - 来自 javascript 的 http GET 和 PUT 二进制数据(CouchDB 附件)

java - xjc 和 XSD 的选择

java - 这个java日期算术代码在不同的平台上给出了不同的答案

java - Glassfish 3.0 : Exception while deploying ejb module. ..无效的 ejb j ar:它包含零个 ejb

http - HTTP 中的 POST 和 PUT 有什么区别?

java - 设置 xs :datetime type from java setter method omits milliseconds part of timestamp value