0

JPA フレームワークを使用して、情報のデータベースの永続性を実現しています。

これは私がこのようなクラスを作成した方法です:

public class ManageConnection {

 private static EntityManagerFactory emf = null;
 private static EntityManager em = null;
 private static String persitenceName="locationtracker";

 public static EntityManager getEntityManager(){
    if(emf==null || !emf.isOpen())
        emf =  Persistence.createEntityManagerFactory(persitenceName);
    if(em==null || !em.isOpen())
        em=emf.createEntityManager();

    return em;
 }
 public static void closeEntityManager(){
    if(em!=null && em.isOpen())
        em.close()
 }
}

次に、サーブレットで次のように使用しています:

public void doPost(blablah){   
    .
    .
    .
    .
    .
    .
    .
    .
    .
    .
    .
    for(blah blah){

         Manageconnection.getEntityManager().getTransaction().begin();
            <PersistenceObject> objName = new <PersistenceObject>();
                 //properties of the objName to persist
         ManageConnection.getEntityManager().persist(<objName>);
         Manageconnection.getEntityManager().getTransaction().commit();
    }

    Manageconnection.closeEntityManager();
}

今私の問題は、値をサーブレットに渡すたびにトランザクションが既にアクティブな例外を取得することです。また、サーブレットがない場合でも同じコードが完全に機能します。つまり、テストクラスでメインメソッドを使用すると、チャームのように実行されますが、スローされますサーブレットで実行する場合の例外。

助けてください.............. ;(事前に感謝します、Ankur

4

3 に答える 3

1
  1. 私はあなたがEJBを使いたくないと思いますが、代わりにPOJOを使いたいと思います。
    (Session BeansがJPA操作を実行し、サーブレットがEJBを呼び出す単純なソリューションがあることに注意してください-コードが少なく、醜くなく、必要なことを実行します。)

  2. 各サーブレットセッションには、独自のエンティティマネージャインスタンスが必要です。クラスManageConnectionから「静的」のすべてのケースを削除します。次に、サーブレットでHttpSessionを作成するときに、ManageConnectionのインスタンスを追加で作成し、それを属性としてセッションに格納します。

    パブリッククラスMyServletはHttpServletを拡張します{

    private ManageConnections getManageConnections(HttpSession sess) {
        ManageConnection manageConnection = 
            (ManageConnection)sess.getAttribute("userManageConnection");
        if (manageConnection == null) {
            ManageConnection manageConnection = new ManageConnection();
            sess.setAttribute("userManageConnection", manageConnection);
        }
    }
    
    public void doPost(HttpServletRequest req, HttpServletResponse resp) 
         throws ServletException, IOException {
       this.processRequest(req, resp);
    }
    
    public void processRequest(HttpServletRequest req, HttpServletResponse resp) 
         throws ServletException, IOException {
        HttpSession sess = req.getSession(true);
        ManageConnections manageConnections = this.getManageConnections(sess);
        // remaining JPA operations
    }
    

    }

  3. EntityManagerを取得します。

    // inside processRequest() above
    EntityManager em = manageConnection.getEntityManager();
    
  4. Txを開始し、エンティティ操作を実行し、Txを終了します

    // inside processRequest() above
     em.getTransaction().begin();
     <PersistenceObject> objName = new <PersistenceObject>();
     //properties of the objName to persist
     em.persist(<objName>);
     em.getTransaction().commit();
    
  5. ユーザーがセッションを終了する前に、EntityManagerを閉じます。これがないと、一部の実装を頻繁に再起動する必要があるため、これは重要です。特に、開発中に頻繁に再構築および再デプロイする場合(Netbeansモジュールを使用してデプロイされたGlassfish上のEclipseLinkを参照)。

     make servlet:  extends HttpSessionListener
    
     // add the following methods, so we get a callback to sessionDestroyed when the 
     // session is closed via user logout (terminateSession) or session timeout:
    
     public void init(ServletConfig config) throws ServletException {
        config.getServletContext().addListenter(this.class.getName());
     }
    
    
     public void sessionCreated(HttpSessionEvent se) {
     }
    
     public void sessionDestroyed(HttpSessionEvent se) {
           ManageConnections manageConnections = this.getManageConnections();
           manageConnections.getEntityManager().close();
           manageConnections.getEntityManagerFactor().close();
     }
    

As I said - a bit ugly, because we are using a very stateful Application Managed Entity Manager in a stateless Servlet. Much cleaner to use a Transaction Scoped Entity Manager in a Stateless Session Bean or Extended Scope (or Application Managed) Entity Manager in a Stateful Session Bean... quite a JPA mouthful, but easier than it sounds. :-)

于 2012-10-16T08:29:02.890 に答える
1

あなたのすべてEntityManagerFactoryEntityManagerFactoryが使用されstaticます。これはクラスレベルであり、のすべてのインスタンスに対してManageConnectionです。最初に、のインスタンスManageConnectionが作成されると、他ののインスタンスを共有しますManageConnection。私の提案は、を使用せずに試してみることstaticです。

于 2012-10-15T15:50:02.440 に答える
0

次のような 2 つのクラスを作成しました。

 //This class has the EntityManagerFactory instance that is going to be shared between the classes
 public class ManageConnection {

  protected static EntityManagerFactory emf = null;
  private static String persitenceName="locationtracker";

  //Anonymous Block that is going to be called (beofre) on every call for constructor of this class
  //whether through inheritance or normal instantiation
  {
    if(emf==null || !emf.isOpen())
        emf =  Persistence.createEntityManagerFactory(persitenceName);
  }


  public static EntityManagerFactory getEntityManagerFactory(){
    return ManageConnection.emf;
  }
}
//This class actually handles the trasactional management
 public class ManageTransaction extends ManageConnection{

   /**
    * 
    */
   public ManageTransaction() {
    super();
    this.entityManager = emf.createEntityManager();
    this.transaction = this.entityManager.getTransaction();

   }

   /**
    * @param entityManager
    * @param transaction
    */
   public ManageTransaction(EntityManager entityManager,EntityTransaction transaction) {
    super();
    this.entityManager = entityManager;
    this.transaction = transaction;
   }

   private EntityManager entityManager;
   private EntityTransaction transaction;

   /**
    * @return the entityManager
    */
   public EntityManager getEntityManager() {
    return entityManager;
   }

   /**
    * @param entityManager the entityManager to set
    */
   public void setEntityManager(EntityManager entityManager) {
    this.entityManager = entityManager;
   }

   /**
    * @return the transaction
    */
   public EntityTransaction getTransaction() {
    return transaction;
   }

   /**
    * @param transaction the transaction to set
    */
   public void setTransaction(EntityTransaction transaction) {
    this.transaction = transaction;
   }

   public void closeEntityManager(){
    if(entityManager!=null && entityManager.isOpen()){
        entityManager.close();
    }
   }

   public void close(){
    this.closeEntityManager();
   }

   public void flush(){
    entityManager.flush();
   }

   public void begin(){
    this.transaction.begin();
   }

   public void commit(){
    this.flush();
    this.transaction.commit();
   }

   public void persist(Object objToPersist){
    this.entityManager.persist(objToPersist);
   }
 }//end of ManageTransaction class

これを使用したい場合は、次のように使用します。

.
.
.
.
.
.
ManageTransaction mt = new ManageTransaction();

シナリオ 1

 mt.getEntityManager().find(blah,blah);//works perfectly

シナリオ 2

mt.begin();
<PersistenceObject> objName = new <PersistenceObject>();
mt.persist(objName);
mt.close();

シナリオ 3

String jpaquery = "blah blah";
TypedQuery<ClassType> tq = mt.getEntityManager().createQuery(jpaquery,<Class>.class);
List<ClassType> all = tq.getResultList();

このようにして、新しいトランザクションを作成する必要がないたびに、単一のトランザクションを作成し、クラス内のあらゆる場所でそのトランザクションを使用し、最後にそれを閉じます。

そうすれば、 EntityManagerを共有するという私の問題が解決され、例外がスローされることはありません。

:)

于 2012-10-16T12:59:58.700 に答える