我試圖在JBoss 4.3.0和Hibernate 4.3.5的狀態專有Web框架上實現entitymanager-per-conversation模式。總之,我們的目標是:每個對話JPA 2(Hibernate)持久化上下文 - 關閉連接
- 從數據庫
- 在第二請求延遲加載屬性第一HTTP請求負載實體A,實體A的延遲加載特性是沒有例如訪問創建一個新的EntityManager並調用例如entityManager.merge(entityA)。
Entitymanager-per-conversation似乎是最佳選擇。這裏是我的嘗試:
public class EntityManagerHolder {
private static ThreadLocal<EntityManager> entityManager = new ThreadLocal<EntityManager>();
private static EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("myPersistence");
private static ConnectionProvider connectionProvider = new MyConnectionProvider();
public static synchronized EntityManager getEntityManager() {
createEntityManagerIfNeeded();
return entityManager.get();
}
public static synchronized void createEntityManagerIfNeeded() {
if (entityManager.get() == null) {
// Start the conversation
EntityManager newEntityManager = entityManagerFactory.createEntityManager();
entityManager.set(newEntityManager);
newEntityManager.getTransaction().begin();
} else {
// Entitymanager is alive but may have lost its connection
EntityManager existingEntityManager = entityManager.get();
SessionImpl session = existingEntityManager.unwrap(SessionImpl.class);
try {
if (session.connection() == null || session.connection().isClosed()) {
session.reconnect(connectionProvider.getConnection());
}
} catch (SQLException e) {
throw new RuntimeException(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_2_0.xsd"
version="2.0">
<persistence-unit name="myEntityManagerFactory">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<properties>
<!-- Scan for annotated classes and Hibernate mapping XML files from this JAR -->
<property name="hibernate.archive.autodetection" value="class, hbm" />
<!-- Database connection settings: Use framework connections for database connectivity -->
<property name="hibernate.connection.provider_class" value="foo.bar.MyConnectionProvider"/>
</properties>
</persistence-unit>
</persistence>
當一個新的HTTP請求通過框架到達,我叫EntityManagerHolder.createEntityManagerIfNeeded()。關於第二個HTTP請求了EntityManager的JDBC連接已關閉,並通過session.reconnect()來恢復它的嘗試會導致一個例外:
java.lang.IllegalStateException: cannot manually reconnect unless Connection was originally supplied
org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.manualReconnect(LogicalConnectionImpl.java:296)
org.hibernate.internal.SessionImpl.reconnect(SessionImpl.java:478)
我意識到我可能做的事情非常落後方式,但很好理解應該如何實施entitymanager-per-conversation。我發現了這種模式的基於過濾器的Hibernate-specific sample implementation,但還沒有設法使其符合我的需求。