私のセットアップ:
JPAを使用するJBossAS7.1.1、Hibernate(PostgreSQLに接続するため)、RESTEasy、JSONの場合はJackson 1.9.2、XMLの場合はEclipseLink MOXy 2.4.1
GroupとUserの2つのエンティティがあります。グループには多くのユーザーが含まれます(1対多)。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...
}
ユーザー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;
}
}
これがグループ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;
}
}
サイクルをテストするために、Jacksonを使用してユーザーを追加した後のGroupEndpointMOXyの応答は次のとおりです。
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>