2

コンテナ管理のトランザクションとコンテナが伝播する永続コンテキストを使用する Java EE 6 Web アプリケーションがあります。

@PersistenceContext
private EntityManager em;

JPAレイヤーには、継承戦略があり、 whereMyExtendedClassAMyEntendedClassBboth extends abstract MyClass.

メソッドによるデータ アクセスを実装するために、stateless facadeサービス クラスを使用します。findfindAllmergepersistremove

@Stateless
public class MyExtendedClassAFacade {
    @PersistenceContext
    private EntityManager em;
    public void persist(MyExtendedClassA a) {
        // ...
    }
    // other methods
}

ここまでは順調ですね。ここで、拡張クラスの動作にポリモーフィズムを実装する必要があります。この動作は、データベース内の他のいくつかのエンティティを管理することで構成されているため、PersistenceContext が必要です (したがって、他のStatelessEJB を使用する必要があります)。

@Stateful
public class MyBean {

    @EJB
    private MyClassFacade myClassFacade;   // stateless facade service class

    public void doSomething() {
        for (MyClass c : myClassFacade.findAll()) {
            // here I need to perform operations on the db. 
            // The implementation differs on each extended class.
            // I want to avoid a brute-force coding like:
            if (c.getClass().equals(MyExtendedClassA.class)) {
                @EJB MyExtendedClassAFacade myClassFacadeA;
                myClassFacadeA.doSomething((MyExtendedClassA) c);
            } else if (c.getClass().equals(MyExtendedClassB.class))
                @EJB MyExtendedClassBFacade myClassFacadeB;
                myClassFacadeB.doSomething((MyExtendedClassB) c);
            }
            // Instead, I would like to write something like:
            @EJB AnotherStatelessBean asb;
            asb.doSomething(c);
        }
    }
}

この目標に使用できる抽象化パターンはありますか?

4

1 に答える 1

3

これはEJBポリモーフィズムであり、他の状況に適用できます。JPAの継承とは直接関係ありません。

秘訣は@Local、EJBのインターフェースを使用することです。

@Local
public interface MyClassFacadeInterface {    
    public void doSomething(MyClass c);
}

そして、拡張クラスの既存のFacadeステートレスBeanにそのインターフェースを実装させます。

その後、statelessを使用してFacade実装クラスを検索する必要がありますInitialContext.lookup("java:module/MyExtendedClassAFacade")。ここでの秘訣は、ルックアップを容易にするために、エンティティクラスに関連するファサードクラスに名前を付けることです。ビジネスレイヤーで使用されるコードは次のとおりです。

public void doSomething() {      
    for (MyClass c : myClassFacade.findAll()) {      
        String lookupName = getNameFromClassName(c.getClass().name());
        MyClassFacadeInterface myInt =  (MyClassFacadeInterface) new InitialContex().lookup(lookupName);
        myInt.doSomething(c);
    }      
}      
于 2012-09-20T17:35:38.347 に答える