在 OpenShift 上使用 JPA 出现奇怪的错误
Strange error using JPA on OpenShift
我已经担心了几天的错误 - 也是因为很难测试它是否仍然发生。
我正在从 OpenShift 托管的 Java EE 应用程序连接到 MySQL 卡带。我正在使用 JPA (Hibernate) 来处理我的连接并用于 ORM 目的。
连接和应用程序本身工作正常 - 但在几个小时后尝试访问数据库时(我猜在 OpenShift "hibernated" 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)
我当然知道异常对我来说是什么 - 我只是不知道为什么抛出它...
我的数据库访问 class 如下所示:
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>
我已经查阅了很多示例和教程 - 但我找不到问题所在。
提前致谢!
保留对 EntityManager
实例的引用从来都不是一个好习惯,在您的情况下,静态变量 em
在连接关闭后保留一个停止对象。
最佳实践建议将 EntityManager
范围限定为当前交易。
我已经担心了几天的错误 - 也是因为很难测试它是否仍然发生。
我正在从 OpenShift 托管的 Java EE 应用程序连接到 MySQL 卡带。我正在使用 JPA (Hibernate) 来处理我的连接并用于 ORM 目的。
连接和应用程序本身工作正常 - 但在几个小时后尝试访问数据库时(我猜在 OpenShift "hibernated" 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)
我当然知道异常对我来说是什么 - 我只是不知道为什么抛出它...
我的数据库访问 class 如下所示:
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>
我已经查阅了很多示例和教程 - 但我找不到问题所在。
提前致谢!
保留对 EntityManager
实例的引用从来都不是一个好习惯,在您的情况下,静态变量 em
在连接关闭后保留一个停止对象。
最佳实践建议将 EntityManager
范围限定为当前交易。