JPA无交易活跃

时间:2012-10-15 14:48:32

标签: java servlets jpa

我正在使用JPA Framework来实现信息的数据库持久性。

这就是我使用的方法,我创建了一个这样的类:

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()
 }
}

然后在我的servlet中我这样使用:

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();
}

现在我的问题是我得到事务已经处于活动状态每当我将值传递给我的Servlet时异常,当没有Servlet事物时,相同的代码工作正常,我的意思是在测试中使用main方法class它像魅力一样运行,但在Servlet中运行时抛出异常。

请帮助我.............. ( 提前致谢, ANKUR

3 个答案:

答案 0 :(得分:1)

您使用的所有EntityManagerFactoryEntityManagerFactorystatic。它是类级别,适用于ManageConnection的所有实例。首先,如果创建了ManageConnection的实例,它将共享ManageConnection的其他实例。我的建议是在不使用static的情况下尝试。

答案 1 :(得分:1)

  1. 我假设您不想使用EJB,而是想使用POJO (注意,有一个简单的解决方案,其中Session Beans执行JPA操作,Servlet调用EJB - 代码更少,更难看,做你想要的。)

  2. 每个servlet会话都应该有自己的实体管理器实例。从类ManageConnection中删除“静态”的每个案例。然后在您的servlet中,当您创建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。这很重要,因为如果没有它,某些实现将需要经常重启 - 特别是在开发过程中,当您经常重建和重新部署时(我正在看着您,Glassfish上的EclipseLink,使用netbeans模块进行部署)。

     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();
     }
    
  6. 正如我所说 - 有点难看,因为我们在无状态Servlet中使用了一个非常有状态的Application Managed Entity Manager。在状态会话Bean中的无状态会话Bean或扩展范围(或应用程序管理)实体管理器中使用事务范围实体管理器更加清晰......相当JPA满口,但比听起来更容易。 : - )

答案 2 :(得分:0)

我创建了两个这样的类:

 //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();

通过这种方式,每次创建新的Transaction都不需要我创建一个事务,并在我的类中的每个位置使用该事务,最后将其关闭。

这样我的共享 EntityManager 的问题就解决了,因此在任何情况下都不会抛出异常

:)