我有一个 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/