2015-04-02 60 views
0

我得到了一個錯誤,我很擔心已經有好幾天了 - 還因爲很難測試它是否仍然存在。OpenShift上使用JPA的奇怪錯誤

從OpenShift託管的Java EE應用程序中,我連接到MySQL盒式磁帶。我正在使用JPA(Hibernate)來處理我的連接和ORM的目的。

連接和本身工作正常的應用程序 - 但試圖幾個小時後才能訪問數據庫的時候(我猜OpenShift後「休眠」該servlet),它不工作了。

我得到下面的異常(這僅僅是摘錄,但在我看來是最重要的部分):

Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after connection closed. 
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57) 
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 
at java.lang.reflect.Constructor.newInstance(Constructor.java:526) 
at com.mysql.jdbc.Util.handleNewInstance(Util.java:377) 
at com.mysql.jdbc.Util.getInstance(Util.java:360) 
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956) 
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:935) 
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:924) 
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:870) 

我當然知道什麼異常試圖將我 - 我只是不知道爲什麼它被拋出...

我的數據庫訪問類看起來如下:

public class JPAUtils implements ServletContextListener { 
    private static final Logger log = LoggerFactory.getLogger(JPAUtils.class); 
    private static EntityManagerFactory emf; 
    private static EntityManager em; 

    public static EntityManagerFactory getEntityManagerFactoryInstance() { 
     if (emf == null || !emf.isOpen()) { 
      String environment = "test"; 

      if (System.getenv("OPENSHIFT_MYSQL_DB_URL") != null) { 
       environment = "production"; 
      } 

      emf = Persistence.createEntityManagerFactory(environment); 
     } 

     return emf; 
    } 

    public static EntityManager getEntityManagerInstance() { 
     if (em == null || !em.isOpen()) { 
      em = getEntityManagerFactoryInstance().createEntityManager(); 
     } 

     return em; 
    } 

    @Override 
    public void contextInitialized(ServletContextEvent servletContextEvent) { 
     log.debug("Context initialized!"); 
    } 

    @Override 
    public void contextDestroyed(ServletContextEvent servletContextEvent) { 
     try { 
      log.debug("Closing JPA connection..."); 
      em.close(); 
      emf.close(); 
      em = null; 
      emf = null; 

      log.debug("Closed JPA connection!"); 
     } 
     catch (Exception e) { 
      log.error("Error occurred during closing of JPA connection!", e); 
     } 
    } 
} 

的persistence.xml:

<persistence xmlns="http://java.sun.com/xml/ns/persistence" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xsi:schemaLocation="http://java.sun.com/xml/ns/persistence 
    http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" 
      version="1.0"> 
    <persistence-unit name="test"> 
     <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider> 

     <properties> 
      <property name="hibernate.archive.autodetection" value="class, hbm" /> 
      <property name="hibernate.show_sql" value="false" /> 
      <property name="hibernate.format_sql" value="true" /> 
      <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" /> 

      <property name="hibernate.connection.url" value="jdbc:mysql://localhost/<db_name>?autoReconnect=true" /> 
      <property name="hibernate.connection.username" value="***" /> 
      <property name="hibernate.connection.password" value="***" /> 


      <property name="hibernate.hbm2ddl.auto" value="update" /> 

      <property name="hibernate.c3p0.min_size" value="5" /> 
      <property name="hibernate.c3p0.max_size" value="10" /> 
      <property name="hibernate.c3p0.timeout" value="300" /> 
      <property name="hibernate.c3p0.max_statements" value="50" /> 
      <property name="hibernate.c3p0.idle_test_period" value="300" /> 
      <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect" /> 
     </properties> 

    </persistence-unit> 
    <persistence-unit name="production"> 
     <!-- If you are running in a production environment, add a managed 
      data source, this example data source is just for development and testing! --> 
     <!-- The datasource is deployed as WEB-INF/kitchensink-quickstart-ds.xml, you 
      can find it in the source at src/main/webapp/WEB-INF/kitchensink-quickstart-ds.xml --> 
     <non-jta-data-source>java:comp/env/jdbc/MySQLDS</non-jta-data-source> 
     <properties> 
      <!-- Properties for Hibernate --> 
      <property name="hibernate.hbm2ddl.auto" value="update" /> 
      <property name="hibernate.show_sql" value="false" /> 
      <!--<property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform" />--> 
     </properties> 
    </persistence-unit> 
</persistence> 

我已經看過了許多例子和教程 - 但我不能發現問題。

提前致謝!

回答

1

保持對EntityManager實例的引用永遠不會是一個好習慣,您的情況下的靜態變量em在連接關閉後保留一個停止對象。

最佳實踐建議範圍EntityManager s到當前事務。

+0

好的,好點。 但是,這可能不會解決它,至少如果我得到您的建議正確的...... – 2015-04-02 11:37:28

+1

是的,我認爲它應該,如果連接因任何原因(鈍化等)關閉,您保留在EntityManager靜態變量繼續使用它,並關閉。這是我認爲的錯誤的起源。 – EmirCalabuch 2015-04-02 16:12:37

+0

好的,在耗盡測試後,它似乎以這種方式工作 - 謝謝! 所以它看起來(這也是什麼錯誤消息說)該entityManager已關閉 - 我只是希望em.isOpen()返回false以防連接關閉...好吧,這可能是因爲設置em = null,並且對於活動的entityManger實例可能有限制.... – 2015-04-05 08:25:34