0

REST アプリケーションには Jersey/Jackson を使用します。着信 JSON 文字列は、Jackson によってバックエンドの @Entity オブジェクトにマッピングされ、永続化されます。

問題は、すべてのエンティティに使用する基本クラスから発生します。これには protected id プロパティがあり、これを REST 経由でも交換して、依存関係を持つオブジェクトを送信すると、hibernate がこれらの依存関係を ID によって自動的にフェッチするようにします。

ただし、サブクラスでオーバーライドして public にしても、Jackson はセッターにアクセスしません。@JsonSetter も使用してみましたが、役に立ちませんでした。おそらくジャクソンは基本クラスを見て、IDにアクセスできないことを確認したため、設定をスキップしました...

@MappedSuperclass
public abstract class AbstractPersistable<PK extends Serializable> implements Persistable<PK> {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private PK id;

    public PK getId() {
        return id;
    }

    protected void setId(final PK id) {
        this.id = id;
    }

サブクラス:

public class A extends AbstractPersistable<Long> {
    private String name;
}

public class B extends AbstractPersistable<Long> {
    private A a;

    private int value;

    // getter, setter

    // make base class setter accessible
    @Override
    @JsonSetter("id")
    public void setId(Long id) {
        super.setId(id);
    }
}

ここで、データベースにいくつかの As があり、REST リソースを介して新しい B を作成したい場合:

@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Transactional
public Response create(B b) {
    if (b.getA().getId() == null) 
        cry();
}

このような JSON 文字列を使用します{"a":{"id":"1","name":"foo"},"value":"123"}

着信 B には A 参照がありますが、ID はありません。


ベースクラスセッターを無視するか、代わりにサブクラスセッターを使用するようにジャクソンに指示する方法はありますか?

知ったばかり@JsonTypeInfoですが、これが必要なものなのか、それをどのように使用するのかわかりません。

助けてくれてありがとう!


編集

StaxMan は、ここに何かが欠けているのではないかと心配しているので、XML 注釈をセッター(私の答えで説明されているように):

<servlet>
    <servlet-name>jersey-serlvet</servlet-name>
    <servlet-class>
        com.sun.jersey.spi.spring.container.servlet.SpringServlet
    </servlet-class>
    <init-param>
        <param-name>com.sun.jersey.config.property.packages</param-name>
        <param-value>path.to.rest.resources</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>jersey-serlvet</servlet-name>
    <url-pattern>/rest/*</url-pattern>
</servlet-mapping>
4

2 に答える 2

2

だから、すでに解決策を見つけました:

@XmlElement(name="id")すべてのオーバーライド ID セッターで使用する必要があります。

@XmlElement(name="id")
public void setId(Long id) {
    super.setId(id);
}
于 2012-09-28T10:27:16.120 に答える
0

いいえ、そのまま動作するはずです。Jackson シリアライザーは、実際のランタイム クラス (すべての基本クラス プロパティを含む) を参照し、getter ("getId()") を確認する必要があります。だから何か他のことが起こっています。

解決策に基づいて、Jackson POJO ベースのマッピングを使用していないのではないかと思いますが、何か他のものを使用しています...

于 2012-09-28T20:45:33.847 に答える