事务完成后未清除 JPA 一级缓存
JPA first level cache not clreared after completion of transaction
我正在使用 JPA 2.1(带有 EclipseLink 实现)从数据库中获取记录。
默认情况下启用一级缓存,它将记录缓存在 PersistenceContext 中。如果我尝试获取相同的记录,我将从一级缓存中获取它,因此不会第二次在数据库上触发查询。
一旦事务结束,一级缓存将被清除,如果我再次尝试获取相同的条目,则必须触发查询,因为缓存已被清除,它应该来自数据库,但事实并非如此。
如果我关闭当前的实体管理器,重新打开它并尝试获取记录,至少应该在数据库上触发查询。
即使是现在,第二个查询也不会进入数据库。一旦我第一次从数据库中获取记录(此时我可以在控制台日志中看到 select 查询),之后如果我尝试再获取一次,它来自缓存内存(因为我不能在控制台日志中再次查看查询,我假装它来自缓存),无论我做什么(使用新事务或关闭并重新打开实体管理器)都不会清除一级缓存。
我使用的代码如下:
EntityManagerFactory entityManagerFactory=
Persistence.createEntityManagerFactory("01EmployeeBasics");
EntityManager entityManager=entityManagerFactory.createEntityManager();
System.out.println("EM1 : "+entityManager);
entityManager.getTransaction().begin();
System.out.println("Tx1 : "+entityManager.getTransaction());
Employee employee=entityManager.find(Employee.class, 123);
entityManager.getTransaction().commit();
entityManager.close();
entityManager=entityManagerFactory.createEntityManager();
System.out.println("EM2 : "+entityManager);
entityManager.getTransaction().begin();
System.out.println("Tx2 : "+entityManager.getTransaction());
Employee employee2=entityManager.find(Employee.class, 123);
entityManager.getTransaction().commit();
entityManager.close();
entityManagerFactory.close();
员工class如下:
package in.co.way2learn;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Employee {
@Id
private int id;
private String name;
private int salary;
public Employee() {
// TODO Auto-generated constructor stub
}
public Employee(int id, String name, int salary) {
super();
this.id = id;
this.name = name;
this.salary = salary;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
System.out.println("Employee.getName()");
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
}
在数据库中有一个 ID 为 123 的记录。
现在我的问题是为什么一级缓存没有清空??
EclipseLink 有一个默认启用的共享对象(二级)缓存:
...exists for the duration of the persistence unit (EntityManagerFactory,
or server) and is shared by all EntityManagers and users of the
persistence unit.
如果您根据下面的说明禁用它,那么您应该会看到第二个查询被触发。
我正在使用 JPA 2.1(带有 EclipseLink 实现)从数据库中获取记录。 默认情况下启用一级缓存,它将记录缓存在 PersistenceContext 中。如果我尝试获取相同的记录,我将从一级缓存中获取它,因此不会第二次在数据库上触发查询。
一旦事务结束,一级缓存将被清除,如果我再次尝试获取相同的条目,则必须触发查询,因为缓存已被清除,它应该来自数据库,但事实并非如此。
如果我关闭当前的实体管理器,重新打开它并尝试获取记录,至少应该在数据库上触发查询。
即使是现在,第二个查询也不会进入数据库。一旦我第一次从数据库中获取记录(此时我可以在控制台日志中看到 select 查询),之后如果我尝试再获取一次,它来自缓存内存(因为我不能在控制台日志中再次查看查询,我假装它来自缓存),无论我做什么(使用新事务或关闭并重新打开实体管理器)都不会清除一级缓存。
我使用的代码如下:
EntityManagerFactory entityManagerFactory=
Persistence.createEntityManagerFactory("01EmployeeBasics");
EntityManager entityManager=entityManagerFactory.createEntityManager();
System.out.println("EM1 : "+entityManager);
entityManager.getTransaction().begin();
System.out.println("Tx1 : "+entityManager.getTransaction());
Employee employee=entityManager.find(Employee.class, 123);
entityManager.getTransaction().commit();
entityManager.close();
entityManager=entityManagerFactory.createEntityManager();
System.out.println("EM2 : "+entityManager);
entityManager.getTransaction().begin();
System.out.println("Tx2 : "+entityManager.getTransaction());
Employee employee2=entityManager.find(Employee.class, 123);
entityManager.getTransaction().commit();
entityManager.close();
entityManagerFactory.close();
员工class如下:
package in.co.way2learn;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Employee {
@Id
private int id;
private String name;
private int salary;
public Employee() {
// TODO Auto-generated constructor stub
}
public Employee(int id, String name, int salary) {
super();
this.id = id;
this.name = name;
this.salary = salary;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
System.out.println("Employee.getName()");
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
}
在数据库中有一个 ID 为 123 的记录。
现在我的问题是为什么一级缓存没有清空??
EclipseLink 有一个默认启用的共享对象(二级)缓存:
...exists for the duration of the persistence unit (EntityManagerFactory, or server) and is shared by all EntityManagers and users of the persistence unit.
如果您根据下面的说明禁用它,那么您应该会看到第二个查询被触发。