java使用JPA第二次读取对象不会更新它
我有一个小的web应用程序;下面是它的简化可运行版本
每次http请求时,我都从数据库中读取一个对象,每次都是一样的 并使用它来显示页面的内容。发布到后的第一个请求 玻璃鱼,一切都很好。但是,如果我更改数据库中的值, 此更改不会反映在下一个请求中
与获取实体相关的代码:
// @WebServlet MyServlet
@Inject
private MyEJB ejb;
// MyServlet.doGet()
MyEntity e = ejb.getResource(1);
System.out.printf("%s: %s%n", e, e.getValue());
// @Stateless MyEJB
@PersistenceContext
private EntityManager em;
// MyEJB.getResource()
TypedQuery<MyEntity> q = em.createNamedQuery("MyEntity.selectById", MyEntity.class);
q.setParameter("id", id);
MyEntity e = q.getSingleResult();
return e;
在请求之间将值更改为asdf!
,登录doGet()
将输出:
Information: pkg.model.MyEntity@7bc0b80e: asdf
Information: pkg.model.MyEntity@5543a940: asdf
显然,该实体是在请求之间缓存的,尽管需要一个不同的对象
返回flush
在查询之前或之后的getResource
中调用实体管理器
没有什么不同,我不明白refresh
对实体进行加密不会
工作,但不是递归的,不能满足其他必然出现的需求
在原始应用程序中。我在尝试其他事情时遇到的异常证实了EntityManager是JTA管理的,正如我预期的那样
我正在使用GlassFish服务器开源版本4.0和默认的EclipseLink ORM
我认为有三种选择可以满足我的需求:
- 配置,位于Glassfish控制台或某些WEB-INF/META-INF文件或类似文件中
- 我可以在实际处理每个请求之前执行一些代码,确保 已缓存的对象是数据库的最新对象
- 一种不同的注入方式,可以实现这一点,也可以将缓存限制为 按请求计算
我如何才能实现其中的一个,或者它是我真正需要的不同的东西
完整代码如下
package pkg.model;
import javax.persistence.Basic;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
@Entity
@Table(schema = "MySchema")
@NamedQueries({
@NamedQuery(name = "MyEntity.selectById",
query = "SELECT e FROM MyEntity e WHERE e.id = :id")
})
public class MyEntity {
private Long id;
private String value;
@Id
@GeneratedValue
public Long getId() {
return id;
}
@SuppressWarnings("unused")
private void setId(Long id) {
this.id = id;
}
@Basic
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
package pkg;
import java.io.IOException;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.servlet.ServletException;
import pkg.model.MyEntity;
@Stateless
public class MyEJB {
@PersistenceContext
private EntityManager em;
public MyEntity getResource(long id) throws ServletException, IOException {
TypedQuery<MyEntity> q = em.createNamedQuery("MyEntity.selectById", MyEntity.class);
q.setParameter("id", id);
MyEntity e = q.getSingleResult();
return e;
}
}
package pkg;
import java.io.IOException;
import java.io.PrintWriter;
import javax.inject.Inject;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import pkg.model.MyEntity;
@WebServlet(name = "MyServlet", urlPatterns = "/")
public class MyServlet extends HttpServlet {
@Inject
private MyEJB ejb;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
MyEntity e = ejb.getResource(1);
System.out.printf("%s: %s%n", e, e.getValue());
resp.setContentType("text/html;charset=UTF-8");
try (PrintWriter out = resp.getWriter();) {
out.print(e.getValue());
}
}
}
另外,一个空的豆子。xml和普通web。xml(只是一个welcome-file-list
)
# 1 楼答案
有不同的选项来禁用缓存或强制刷新
通过将以下内容添加到
persistence.xml
中,可以禁用普通共享缓存:使用
NamedQueries
时,您可能还必须通过添加以下内容来禁用查询缓存:另一种更详细的禁用缓存的方法是通过查询提示。这可以通过以下方式完成:
EclipseLink wiki中有很多关于缓存的附加信息:
另请参见: