在使用XmlInverseReference解组子进程时,如何让MOXy指定父进程?

时间:2013-02-13 00:54:32

标签: jpa jboss jaxb jackson moxy

我的设置:

JBoss AS 7.1.1使用JPA,Hibernate(连接到PostgreSQL),RESTEasy,Jackson 1.9.2 for JSON,EclipseLink MOXy 2.4.1 for XML

我有两个实体 - 群组用户。一个组包含许多用户(一对多)。我正在宣布与JPA注释的双向关系(见下文),所以我必须使用@JsonManagedReference / @JsonBackReference(对于JSON)和@XmlInverseReference(对于XML)来防止周期。这可以按预期工作,除非我尝试通过REST创建用户,在使用XML时我无法将她分配给组。使用JSON时,它可以工作:

Jackson JSON 作品(成功添加Jane Doe并将她放入第5组):

POST request to /user
Content-Type: application/json
Accept: application/json
Body: {"name":"Jane Doe", "group":{"id":5}}

Response:

{
   "id": 12,
   "name":"Jane Doe"
}

Hibernate: insert into users (group_id, name, id) values (5, 'Jane Doe', 12)

这是使用Jackson添加用户后的GroupEndpoint响应:

GET request to /group
Accept: application/json

Response:

[{"id":5,"name":"My User Group","users":[{"id":12,"name":"Jane Doe"}]}

MOXy XML 不起作用(Jane Doe是孤儿):

POST request to /user
Content-Type: application/xml
Accept: application/xml
Body: <name>Jane Doe</name><group><id>5</id></group>

Response:

    <user><name>Jane Doe</name><id>12</id></user>

Hibernate: insert into users (group_id, name, id) values (null, 'Jane Doe', 12)

这是使用MOXy添加用户后的GroupEndpoint响应:

GET request to /group
Accept: application/xml

Response:

<collection>
  <group><id>5</id><name>My User Group</name></group>
</collection>

我已尝试过@XmlID@XmlIDREF同样的问题。 @XmlTransient同样会忽略编组和解组的子到父关系。

我的问题:

如何在没有MOXy忽略新用户的组字段(标记为@XmlInverseReference)的情况下,通过用户REST端点将用户添加到组?

我应该扩充我的REST端点,创建XmlAdapter,还是编写自定义序列化程序?我错过了一个带有不同注释的简单解决方案吗? 是否有一种完全不同的方法通过REST首选暴露关系对象?非常感谢任何帮助。

以下是群组实体:

@Entity
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Group implements Serializable {
    @Id
    private Long id;

    @Column
    private String name;

    @OneToMany(mappedBy="group", cascade=CascadeType.ALL)
    @JsonManagedReference("group-user")
    private Set<User> users;

    // Omitting getters and setters etc...
}

这是用户实体:

@Entity
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class User implements Serializable {
    @Id
    private Long id;

    @Column
    private String name;

    @ManyToOne
    @JsonBackReference("group-user")
    @XmlInverseReference(mappedBy="users")
    private Group group;

    // Omitting getters and setters etc...
}

这是User REST端点:

@Stateful
@Path("/user")
@TransactionAttribute
public class UserEndpoint {
    @PersistenceContext(type = PersistenceContextType.EXTENDED)
    private EntityManager em;

    @POST
    @Consumes({"application/xml","application/json"})
    public User create(User entity) {
        em.joinTransaction();
        em.persist(entity);
        return entity;
    }
}

这是Group REST端点(包含以显示需要防止循环):

@Stateful
@Path("/group")
@TransactionAttribute
public class GroupEndpoint {
    @PersistenceContext(type = PersistenceContextType.EXTENDED)
    private EntityManager em;

    @GET
    @Produces({"application/xml","application/json"})
    public List<Group> listAll() {
        final List<Group> results = em.createQuery("SELECT x FROM Group x").getResultList();
        return results;
    }
}

添加杰克逊的用户后,这是GroupEndpoint MOXy 响应,以测试周期:

GET request to /group
Accept: application/xml

Response:

<collection>
  <group>
     <id>5</id>
     <name>My User Group</name>
     <users><id>12</id><name>Jane Doe</name></users>
  </group>
</collection>

1 个答案:

答案 0 :(得分:2)

注意:我是EclipseLink JAXB (MOXy)主管,是JAXB (JSR-222)专家组的成员。

现在,EclipseLink 2.5.0中已实现对用例的支持。您可以从以下链接下载夜间标签(盯着2013年3月1日)。

JAVA模型

现在,MOXy支持在关系的两个方向上指定@XmlInverseReference注释。单独指定时,它就像@XmlTransient一样用于编组,为了使其可写,您需要将其与@XmlElement结合使用。

用户

import java.io.Serializable;
import javax.persistence.*;
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlInverseReference;

@Entity
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class User implements Serializable {
    @Id
    private Long id;

    @Column
    private String name;

    @ManyToOne
    //@JsonBackReference("group-user")
    @XmlElement
    @XmlInverseReference(mappedBy="users")
    private Group group;

    public Group getGroup() {
        return group;
    }

    // Omitting other getters and setters etc...
}

<强>组

import java.io.Serializable;
import java.util.Set;
import javax.persistence.*;
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlInverseReference;

@Entity
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Group implements Serializable {
    @Id
    private Long id;

    @Column
    private String name;

    @OneToMany(mappedBy="group", cascade=CascadeType.ALL)
    //@JsonManagedReference("group-user")
    @XmlElement
    @XmlInverseReference(mappedBy="group")
    private Set<User> users;

    public Set<User> getUsers() {
        return users;
    }

    // Omitting other getters and setters etc...
}

DEMO CODE

<强>演示

下面是一些可以运行的代码,以证明一切正常。除了XML用例之外,MOXy还可以用于处理JSON。

import java.io.StringReader;
import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;
import org.eclipse.persistence.jaxb.UnmarshallerProperties;

public class Demo {

    public static void main(String[] args) throws Exception {

        JAXBContext jc = JAXBContext.newInstance(User.class);
        Unmarshaller unmarshaller = jc.createUnmarshaller();

        // XML USE CASE
        StringReader xml = new StringReader("<user><name>Jane Doe</name><group><id>5</id></group></user>");
        User userFromXML = (User) unmarshaller.unmarshal(xml);
        System.out.println(userFromXML.getGroup().getUsers());

        // JSON USE CASE
        StringReader json = new StringReader("{\"name\":\"Jane Doe\", \"group\":{\"id\":5}}");
        unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, "application/json");
        unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
        StreamSource jsonSource = new StreamSource(json);
        User userFromJSON = unmarshaller.unmarshal(jsonSource, User.class).getValue();
        System.out.println(userFromJSON.getGroup().getUsers());
    }

}

<强>输出

以下是运行演示代码的输出,显示后向指针已正确设置。

[forum14844691.User@147ee929]
[forum14844691.User@685c53ff]

更多信息