7

データベースで CRUD 操作を実行するための REST API を構築しています。私の暫定的なスタックは、Jersey、Spring、Spring Data、JPA、および Hibernate です。また、jersey-spring を使用してリソース クラスのインスタンスを提供し、Spring が自動配線できるようにしています。

API は、付随する JPA エンティティと Spring Data リポジトリに支えられた DAO を使用して、多数のテーブルで CRUD 操作をサポートします。DAO インターフェイスと関連する DTO のファミリは、次のようになります。

public interface CrudService<T extends PersistedObject> { /* ... */  }
public interface PersonService extends CrudService<Person> { /* ... */  }

public class PersistedObject { /* ... */ }
public class Person extends PersistedObject { /* ... */ }

以下は、JAX-RS リソース クラスの簡略化されたバージョンです。

@Component
@Path("/people")
public class PersonResource {

    @Autowired
    private PersonService personService;

    @Path("/{id}")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Person get(@PathParam("id") String id) {
        return personService.findOne(Long.valueOf(id));
    }

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    public Response post(Person person) {
        personService.save(person);
        return Response.created().build();
    }
}

問題は、残りの数十のリソース クラスがほとんど同じに見えることです。唯一の違いは、異なる PersistedObject サブクラスとそれに対応する DAO で動作することです。おそらく多形性とDAOの巧妙な注入によって、すべてのエンティティタイプでCRUD操作をサポートできる1つのリソースクラスを持つことで、DRYを維持したいと思います。次のようになります。

@Component
@Path("/{resourceType}")
public class CrudResource {

    @Autowired
    private CrudService crudService;

    @Path("/{id}")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public PersistedObject get(@PathParam("id") String id) {
        return crudService.findOne(Long.valueOf(id));
    }

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    public Response post(PersistedObject entity) {
        crudService.save(entity);
        return Response.created().build();
    }
}

私が解決する必要がある問題:

  • リソース メソッドが PersistedObject を受け入れて返す場合、Jersey/Jackson はシリアル化/逆シリアル化の方法をどのように知るのでしょうか? path パラメーターのresourceType変数は、ユーザーが要求している具体的な型を示していますが、これをうまく利用する方法がわかりません。
  • Spring がリソース クラス インスタンスを提供するとき、注入する DAO をどのように知るのでしょうか?

全体として、私が正しい道を進んでいるかどうかはわかりません。これを一般的な方法で実装することは可能ですか?

4

2 に答える 2

2

私は何度かこの問題に遭遇しました。ジェネリックエンドポイントとPersistedObjectDaoを作成でき、すべて正常に機能するはずです。Hibernateでは、persist()、merge()、delete()などのセッションメソッドは、それが管理対象オブジェクトであるか、管理対象オブジェクトになることができる限り(merge()の場合)、何を取得するかを気にしません。 。IDでのみ検索し、PersonクラスではなくPersistedObjectクラスで管理する必要があるため、DAOの機能は問題なく機能します。

このアプローチの唯一の問題は、Enunciateなどのドキュメントツールが壊れ、リソースのURLにグローバルに一意のIDが必要になることです。/ xxx/1と/yyy/1は共存できません。findOneメソッドは、両方に対して同じオブジェクトを返します。つまり、@ Inheritance(strategy = InheritanceType.JOINED)を使用して、IDの衝突を回避し、データベース内のすべての永続エンティティにわたってグローバルに一意のID列を作成する必要があります。

このため、私は通常、AbstractPersistedObjectDAOクラスを作成し、persist()、merge()、delete()を実装し、findOne()をサブクラスに抽象化して、CRUD以上のことを行う必要がある場合にコードをキャストする必要をなくします。しかし、私は通常、エンドポイントのボイラープレートのコストを食いつぶして、EnunciateでRESTドキュメントを作成できるようにし、必要に応じて将来追加のメソッドを実行するクラスを提供します。

于 2013-03-07T05:33:22.467 に答える
2

何らかの方法で JAX-RS に関連付けられているかどうかはわかりませんが、Spring Data ファミリーのプロジェクトには、Spring Data リポジトリによって管理されるエンティティをハイパーメディア主導の方法で自動的に公開するSpring Data RESTモジュールが付属しています。これは、Spring MVC に基づいています。

基本的に、エンティティに対する CRUD 操作は無料で利用でき、クエリ メソッドは透過的に公開され、必要に応じてすべてを微調整および調整できます。

詳細については、次のリンクを参照してください。

于 2013-03-07T09:59:03.317 に答える