【发布时间】:2016-11-10 16:55:34
【问题描述】:
我在 Web 应用程序上使用 Hibernate 4.3.8,看起来 persist() 方法不会更新 PersistentContext(缓存级别 1)。这是我的配置和管理持久操作的单例:
休眠配置
<persistence-unit name="PersistenceUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
<property name="hibernate.connection.driver_class" value="org.postgresql.Driver"/>
<property name="hibernate.connection.url" value="jdbc:postgresql://localhost:5432/irm"/>
<property name="hibernate.connection.username" value="nrossi"/>
<property name="hibernate.connection.password" value="nicolas"/>
<property name="hibernate.connection.pool_size" value="5"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.max_fetch_depth" value="5"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
</properties>
</persistence-unit>
持久性管理器
public class PersistenceManager
{
private static final Logger log = LogManager.getLogger();
private static final EntityManagerFactory emf;
private static final ThreadLocal<EntityManager> threadLocal;
static
{
emf = Persistence.createEntityManagerFactory("PersistenceUnit");
threadLocal = new ThreadLocal<EntityManager>();
}
public static EntityManager getEntityManager()
{
EntityManager em = threadLocal.get();
if (em == null)
{
em = emf.createEntityManager();
threadLocal.set(em);
}
return em;
}
public static <T>T get(Class<T> clazz, Object id)
{
return getEntityManager().find(clazz, id);
}
public static void save(Object object)
{
EntityManager em = getEntityManager();
EntityTransaction et = em.getTransaction();
et.begin();
try
{
em.persist(object);
et.commit();
}
catch (Exception e)
{
et.rollback();
throw new RuntimeException("Error saving object", e);
}
}
}
我更新了一个调用PersistenceManager.save(model) 的模型,它更新了数据库中的记录,但之后当我调用PersistenceManager.get(model.id) 它从内存中返回带有旧值的模型。看起来persist 方法没有更新PersistenceCache。
顺便说一句,如果我在新线程(即隐身窗口)上调用 PersistenceManager.get(model.id),它会返回更新后的模型。
我尝试在提交后添加刷新调用 em.refresh(model) 并且它正在工作,但我不确定这是否是更新上下文的正确方法。
更新信息 我编写了一个简单的 JSP 页面来重现该行为。如果我更新实体描述并等待 5' 并刷新页面它会返回旧值:
<%@page import="com.identicum.framework.persistence.PersistenceManager"%>
<%@page import="com.identicum.irm.core.model.Entity"%>
<%
Entity entity = PersistenceManager.get(Entity.class, 1L);
String value = request.getParameter("entityName");
if(value != null)
{
entity.setDescription(value);
PersistenceManager.save(entity);
}
%>
<html>
<body>
Entity description: <b><%= entity.getDescription() %></b>
<br>
<br>
<form method="post">
Enter new entity description <br>
<input type="text" name="entityName"/>
<input type="submit" />
</form>
</body>
</html>
** 新信息**
我的 PersistenceManager 是这个suggestion 的副本。我的应用程序是应用程序管理的 EntityManager。我必须在每个请求的生命周期内访问同一个 EntityManager。这就是这种方法的原因。还有其他方法可以实现吗?
【问题讨论】:
-
发布所有相关代码,包括加载和更新这些实体的位置。
-
有一个 servlet 处理每个请求并运行以下命令:1) 获取模型:
PersistenceManager.get(Entity.class, id);和 2) 更新模型:Entity entity = PersistenceManager.get(Entity.class , ID); entity.setName("B"); PersistenceManager.save(实体); PersistenceManager 代码在第一个问题上。 -
嗨艾伦,我简化了代码并编写了一个简单的jsp来重现该行为。你可以找到它here。我发现问题在几分钟后开始。我运行 jsp 并向实体发布新的描述。然后我等待 5 分钟,然后我再次运行 jsp(不带参数),我再次看到第一个描述。