事务完成后未清除 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.

如果您根据下面的说明禁用它,那么您应该会看到第二个查询被触发。

https://wiki.eclipse.org/EclipseLink/Examples/JPA/Caching