Hibernate persist()不会更新PersistentContext中的模型

时间:2016-11-10 16:55:35

标签: java hibernate jpa

我正在使用Web应用程序上的Hibernate 4.3.8,看起来persist()方法不会更新PersistentContext(缓存级别1)。这是我的配置和管理持久操作的单例:

Hibernate配置

<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>

Persistence Manager

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>

**新信息**

My PersistenceManager是此suggestion的副本。我的应用程序是应用程序管理的EntityManager。我必须在每个请求的生命周期中访问相同的EntityManager。这就是这种方法的原因。还有其他方法可以实现吗?

2 个答案:

答案 0 :(得分:0)

首先,persist()用于新实体(数据库上没有记录)。 如果要更改对象,则必须使用merge()。

但问题是您可能处于多线程环境中。 所以你不能使用ThreadLocal。每个线程都有自己的PersistenceManager。

您使用的是哪个应用服务器或网络容器?

答案 1 :(得分:0)

我终于修改了它改变了我的方式并关闭了EntityManager。现在,我在每个请求开始时(在我的Rest Dispatcher上)从EntityManagerFactory获取EntityManager,并在结束时关闭它。这样每个请求都有自己的PersistentContext。

PersistenceMangaer.java几乎是一样的。主要区别在于我删除了ApplicationServiceContext的EntityManagerFactory引用,并在类外调用了setEntityManager()。这是一个例子:

PersistenceManager.setEntityManager(PersistenceFactory.createEntityManager);
FooService.createObject1();
FooService.createObject2();
PersistenceManager.closeEntityManager();

这些链接有助于找到问题:

Best practice to get EntityManagerFactory

Should JPA Entity Manager be closed?

http://www.objectdb.com/java/jpa/start/connection