2

JPA では、エンティティは注釈付きのプレーンな古い Java オブジェクトです。しかし、それらとデータベースを操作する良い方法が見つかりませんでした。

私の現在のアプリでは、基本的な設計は常に主キーとしてシーケンス ベースの ID を持つため、通常は PK 以外のプロパティでエンティティを検索する必要があります。

そして、エンティティごとに、次のステートレス EJB があります。

@Stateless
public class MyEntApiBean implements MyEntApi {


@PersistenceContext(unitName = "xxx") @Inject EntityManager entityManager;

すべてが何らかのバリエーションであるクエリメソッドを使用

/**
 * @return A List of all MyEnts that have some property
 * @param someProp some property
 */
public List<MyEnt> getAllMyEntsFromProp(final String someProp) {

    try {
        final Query query = entityManager.createQuery("select me from MyEnt me where me.someProp = :someProp");
        query.setParameter("someProp", someProp);
        return query.getResultList();
    } catch(final NoResultException nre) {
        log.warn("No MyEnts found");
    }
    return new ArrayList<MyEnt>();
}

そう:

  1. これらのメソッドがエンティティ自体に属しているように見えるため、EJB にこれらのメソッドを含めるのは本当に嫌いです。また、EJB ローカル インターフェイスは、私を悩ませます。

  2. 「try、createQuery、getResultList、catch、log、return」を使用して各メソッドに重複があるのは嫌いです(ほとんどの場合、クロージャーがないか、「withステートメント」などのJavaの結果です)。

私の問題の 1 つまたは両方に対処するエンティティおよびデータベースとやり取りするためのより良い方法について、誰か提案がありますか?

私は現在、ジェネリックとリフレクションを使用していくつかの基本メソッドを実行して、重複を減らすためにいくつかのジェネリッククエリメソッドを取得することを考えています (問題 2) (後でレビューのためにプロトタイプを公開します)。

ありがとう、アンダース

4

6 に答える 6

4

Seam を試してみてください。クエリ オブジェクトはほとんどの作業を行い、簡単に拡張できます。または、常に同様のパターンを実装できます。

一般に、Seam は、JPA とビューおよびビジネス層の間のギャップを埋めるために多くの便利なことを行います。Seam を有効にするために JSF を使用する必要はありません。

于 2008-10-07T10:55:07.770 に答える
3

あなたは不必要に冗長になっています。一つには、行が返されない場合、getResultList()は例外をスローしません(少なくともEclipseやToplinkでは-別のプロバイダーが異なるとは想像できません)。getSingleResult()は行いますが、getResultList()は行いません。また、ビルダーパターンを使用して次のようにすることもできます。

@SuppressWarnings("unchecked")
public List<MyEnt> getAllMyEntsFromProp(final String someProp) {
  return entityManager.createQuery("select me from MyEnt me where me.someProp = :someProp")
    .setParameter("someProp", someProp);
    .getResultList();
}

結果のリストがある場合は結果のリストを返すか、ない場合は空のリストを返すのに十分なはずです。注意すべき2つのこと:

  1. @SuppressWarnings( "unchecked")は不要ですが、getResultList()からの非ジェネリックリストの結果をジェネリックリストにキャストするときに、他の方法では避けられない警告を取り除きます。と

  2. (通常)MyEntでcreateQuery()呼び出しを@NamedQueryに置き換えることはおそらく価値があります。一つには、これにより、デプロイ時の検証やその他の便利なことが可能になります。

その合理的に簡潔で完全です。

于 2008-10-07T14:35:27.623 に答える
1

多くのテキスト検索を行う場合は、Compassなどのインデックス作成フレームワークも検討する必要があります。
アプリケーションに適しているかどうかはわかりませんが、適している場合は、コードの設計とパフォーマンスの両方を向上させることができます。

于 2008-10-07T11:46:12.207 に答える
1

私は実際にSeamを使用しています。そして、Query オブジェクトの提案により、Hibernates Criteria クエリ(例によるクエリ)機能を見つけることができました。それは私が探していたものに非常に近いようです。

多分基本クラスで、そしてジェネリックのダッシュで....?

于 2008-10-07T12:31:33.317 に答える
1

モイン!

これが単一の結果の私のバージョンです(TopLink Essentialsを備えたデスクトップJPAアプリケーションで使用しています):

public class JPA {
  @SuppressWarnings ("unchecked")
  public static <T> T querySingle(
      EntityManager em, 
      Class<T> clazz, 
      String namedQuery, 
      Pair... params) 
  {
    Query q = em.createNamedQuery(namedQuery);
    for (Pair pair : params) {
      q.setParameter(pair.key, pair.value);      
    }
    List<T> result = q.getResultList();
    if ( result.size() == 0 ) {
      return null;
    }
    if ( result.size() == 1 ) {
      return result.get(0);
    }
    throw new 
      IllegalStateException(
        "To many result rows for query: " 
         + namedQuery 
         + " where " 
         + Arrays.toString(params));
  }

  public static class Pair {
    String key;
    Object value;

    public static Pair param (String key, Object value) {
      return new Pair (key, value);
    }

    public Pair (String key, Object value) {
      this.key = key;
      this.value = value;
    }

    @Override
    public String toString() {
      return key + "=" + value;
    }
  }
}

そして使用法:

import static org.sepix.JPA.*;
...

String id = ...
Customer customer = querySingle (em, Customer.class, 
                      "Customer.findByID", Pair.param ("id", id));

また:

String inquiryID = ...
Boolean current = Boolean.TRUE;
Inquiry inq = querySingle (em, Inquiry.class, 
                      "Inquiry.findCurrent", 
                      Pair.param ("inquiry", inquiryID),
                      Pair.param ("current", current));

よろしく、ジョシュ。

于 2009-10-19T07:50:50.480 に答える
0

私は、JPA に対処するのに役立つ Spring の JpaDaoSupport を使用することを好みます。良い例はhttp://github.com/rafalrusin/jpaqb/blob/master/src/test/java/jpaqb/CarDao.javaです。

ロジックを適切に分離するには、DAO クラス (データ アクセス オブジェクト) と DTO (データ転送オブジェクト) を使用します。通常、DAO には必要なクエリがすべて含まれており、DTO はフィールドを持つエンティティです。

于 2010-02-04T20:29:04.467 に答える