0

100 個のテーブル (エンティティ クラス) と 100 個のスクリーン (それぞれに 1 つ) がある状況にあります。ShipviaTopComponent と RouteTopComponent の 2 つの画面を見てみましょう。RouteTopComponent には次のメソッドがあります。

public static void saveRecord() {
    Route r = resultList.get(currentPos);
    EntityManager entityManager = Persistence.createEntityManagerFactory("EntityLibraryPU").createEntityManager();
    entityManager.getTransaction().begin();
    r = entityManager.find(Route.class, r.getRouteKey());
    r.setRoute(txtRoute.getText());;
    entityManager.persist(r);
    entityManager.getTransaction().commit();
}

このメソッドを 100 個の画面のそれぞれに配置すると、すべてが機能します。ただし、それを独自のクラスに抽出することを検討しています。つまり、常にルートになるとは限りませんが、Shipvia またはその他のエンティティ クラスになる可能性があります。

RouteTopComponent が次のように呼び出すことを期待しています。

com.demo.viewer.SaveRecord.SaveRecord(r);

その r には、私が必要とするほぼすべてのものが含まれています。これが SaveRecord クラスです。

public class SaveRecord {

public static void saveRecord(entity.Route r) {

    EntityManager entityManager = Persistence.createEntityManagerFactory("EntityLibraryPU").createEntityManager();
    entityManager.getTransaction().begin();
    r = entityManager.find(Route.class, r.getRouteKey());
    r.setRoute("01-banana"); //Hardcode this for now
    entityManager.persist(r);
    entityManager.getTransaction().commit();
}

私が抱えている問題の1つ-「r」を渡すと、エンティティ.ルートが期待されます。でもシップビアを通り過ぎると壊れる。entity.Anything のようなものを期待できるいくつかの方法は何ですか

編集:提案に従って、スーパークラス エンティティを作成しようとしています。

スーパークラス AddChg エンティティ - http://pastebin.com/1iW67NVn

Shipvia エンティティ - http://pastebin.com/R53tNHyp (オリジナルの通常のエンティティ)

ルート エンティティ - http://pastebin.com/5DCvj340 (AddChg を拡張)

SaveRecord のコード (私は SaveResult と名付けました) は次のようになります。

 public static <T extends AddChg> void SaveResult(T r) {
    EntityManager entityManager = Persistence.createEntityManagerFactory(
         "EntityLibraryPU").createEntityManager();
      entityManager.getTransaction().begin();
      r = entityManager.find(Route.class, r.getId());
      r.setSomething("01-banana");
      entityManager.persist(r);
      entityManager.getTransaction().commit();
 }

今、ある意味ではうまくいくようです。スーパークラスからすべてを引き出します。私に問題を引き起こしているように見えるのは1行だけです:

      r = entityManager.find(Route.class, r.getId());

Route.class は、アクセスしようとしているエンティティによっても異なる必要があります。そして、r.getId()保存されているエンティティの PK でなければなりません。

たとえば、ユーザーが RouteTop Screen を編集したい場合、行は次のようになります。

r = entityManager.find(Route.class, r.getRouteKey());

ただし、ShipviaTopScreen の場合は次のようになります。

r = entityManager.find(Shipvia.class, r.getShipvViaCd());

次のようなパラメーターとしてそれらを渡すことができますか?

 public static <T extends AddChg> void SaveResult(T r, Class c, String PK)

Edit3:上記の解決策は機能しますが、最後に最後の問題/質問があります。

保存結果:

public static <T extends AddChg> void SaveResult(T r, Class c, String pk) {
        EntityManager entityManager = Persistence.createEntityManagerFactory(
             "EntityLibraryPU").createEntityManager();
          entityManager.getTransaction().begin();
          r = entityManager.find(c, pk);
          r.setSomething("01-banana");
          entityManager.persist(r);
          entityManager.getTransaction().commit();
 }

RouteTopComponent:

public static void saveRecord() {
    if (r.getRouteKey() != null) {
        r.setRoute(txtRoute.getText());
    }
    SaveResult.SaveResult(r, Route.class, r.getRouteKey());
}

問題は、r.setSomething(""); r と入力したときです。私の唯一の提案はスーパークラスのものです(この質問については、ペーストビンのリンクを参照する必要があります)。

RouteTopComponent ではできますr.setRouteが、SaveResult =( ではできません

Edit4:汎用 (共通) フィールドをスーパークラスに残しながら、エンティティ固有のデータを TopComponent に保存するアプローチを追求しました。私のコードは次のようになります。

RouteTopComponent:

public static void saveRecord() {
        WWEntityManager.entityManager.getTransaction().begin();
        r = WWEntityManager.entityManager.find(Route.class, r.getRouteKey());
        r.setRoute(txtRoute.getText());
        WWEntityManager.entityManager.persist(r);
        WWEntityManager.entityManager.getTransaction().commit();
        SaveResult.SaveResult(r, Route.class, r.getRouteKey());
    }

ご覧のとおり、Route.class 固有のフィールドを最初にコミットしています。次に、一般的な内容を保存する SaveResult メソッドを呼び出します。

結果の保存

public class SaveResult {

    public static <T extends AddChg> void SaveResult(T r, Class c, String pk) {
        WWEntityManager.entityManager.getTransaction().begin();
        r = (T) WWEntityManager.entityManager.find(c, pk);
        r.setChgDate("2012-05-31");
        WWEntityManager.entityManager.persist(r);
        WWEntityManager.entityManager.getTransaction().commit();
    }
}

それが実際に単一のレコードを保存する方法であるかどうか(2つのコミットで)疑問に思っていますか?それは機能しますが、それを処理する方法についてより良い練習があれば、それはかなり素晴らしいでしょう!

4

2 に答える 2

2

すべてのエンティティが Id などの基本フィールドを継承するスーパークラス (PersistentObject と呼びましょう) を使用します。

次に、メソッドのパラメーターは、特定のエンティティ Route ではなく PersistentObject になります。必要に応じて、PersistentObject を拡張する任意のクラスとしてパラメーターを定義することもできます。

public <T extends PersistentObject> static void saveRecord(T newRecord) {
    //your persistence logic here
}

このサイトでは、基本をわかりやすく説明しています。

編集:「EntityManager.find()」の問題について:

EntityManager. find() メソッドは、最初の引数が実際にクラスであるかどうかを主キーチェックし、2番目の引数がエンティティの主キーのタイプと一致するかどうかをチェックすることによってエンティティを返すため、あなたのオプションは私には問題ないようです. Class c 引数を持つ代わりに r.getClass() を直接実行することで、トラブルを回避できると思います。それでも、SaveResult メソッドですべてを行うには、PK を提供する必要があります。

提案として (面倒な場合や単純に不可能な場合は破棄してください)、その find() ロジックを別のメソッドに抽出し、取得したエンティティをパラメーターとして save メソッドに渡し、オブジェクト固有の属性から独立させることができます。

別のオプションがあります: NamedQueries です。各エンティティで「findById」クエリを定義してから、検索しているオブジェクトを返す entity.createQuery メソッドを呼び出すことができます。これは「いいえ」になる可能性があります。あなたの特定のケースでは、100 個のエンティティがあるため、100 個の特定のクエリを実行する必要があるためです (ここでは、コピーと貼り付けは、災害を引き起こすように呼びかけるサイレンです...)。

私はこれを自分で行ったことはありませんが、マップされたスーパークラスで一意の「findById」NamedQuery を作成し、対応する Id を渡すことができるかもしれませんが、特定のキャスト処理を行う必要があります。

編集 2:実際、T 型は AddChg を拡張するため、アクセスできることがわかっているメソッドはスーパークラスのものだけです。これを念頭に置いて(そしてやり過ぎを避けるために)、スーパークラスで「setRoute()」を定義し、特定のクラスでそれをオーバーライドして、必要な特定の動作を与えることができます。

多くのインスタンス固有の属性を含むより複雑なアプローチが必要な場合は、オブジェクトを保存する前に準備する必要があります。save メソッドには、オブジェクトの保存に必要な持続性関連の操作のみを含める必要があります。その「setSomething()」はオブジェクトのデータそのものに関係しているように見えるので、そのままRouteTopComponentで行う方が適切です。

編集 3:最後の持続を使用するだけです。最初のものは情報の半分を保持し、最後のものはすべてを保持します。

于 2012-05-29T14:16:22.797 に答える
1

ジェネリックを使用する

スーパークラスにする

interface IParent  
{  
   long getId();

   void setSomething(String smth);   
}  

各エンティティimplements IParent

public class SaveRecord
{
   public static <T extends IParent> void saveRecord(T r)
   {
      EntityManager entityManager = Persistence.createEntityManagerFactory(
         "EntityLibraryPU").createEntityManager();
      entityManager.getTransaction().begin();
      r = entityManager.find(Route.class, r.getId());
      r.setSomething("01-banana");
      entityManager.persist(r);
      entityManager.getTransaction().commit();
   }
于 2012-05-29T14:37:44.410 に答える