Кэш первого уровня JPA не очищается после завершения транзакции

Я использую JPA 2.1 (с реализацией EclipseLink), чтобы получить запись из базы данных. По умолчанию кеш первого уровня включен, он кэширует запись в PersistenceContext. Если я попытаюсь получить ту же запись, я получу ее из кеша первого уровня, поэтому во второй раз запрос не будет запущен в базе данных.

Как только транзакция завершится, кеш первого уровня будет очищен, и если я попытаюсь получить ту же запись еще раз, запрос должен быть запущен, поскольку кеш очищается, и он должен поступать из базы данных, но это не так.

По крайней мере, запрос должен быть запущен в базе данных, если я закрою текущий менеджер сущностей, снова открою его и попытаюсь получить запись.

Даже сейчас второй запрос не отправляется в базу данных. Как только я впервые получаю запись из базы данных (в это время я вижу запрос выбора в журналах консоли), после этого, если я пытаюсь получить еще раз, он поступает из кэш-памяти (поскольку я не вижу запрос больше времени в журналах консоли, я притворяюсь, что это происходит из кеша), независимо от того, что я делаю (использую новую транзакцию или закрываю и снова открываю диспетчер сущностей), кеш первого уровня не очищается.

Код, который я использую, приведен ниже:

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();

Класс сотрудников выглядит следующим образом:

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.

Теперь мой вопрос, почему не очищается кеш первого уровня??


person Jagadeesh    schedule 24.04.2015    source источник
comment
и если кэш l1 не очищен, вы можете убедиться в этом, проверив, что объект все еще управляется EntityManager, вы это сделали? или вы просто предполагаете, что кэш l1 не очищается? Очевидно, что кеш l1 будет очищаться ТОЛЬКО при закрытии EM, а не при фиксации tx (в зависимости от типа PersistenceContext — какой тип вы используете?)   -  person Neil Stockton    schedule 24.04.2015


Ответы (1)


EclipseLink имеет кеш общих объектов (2-го уровня), который включен по умолчанию и который:

... существует на время существования единицы сохраняемости (EntityManagerFactory или сервера) и используется всеми EntityManagers и пользователями единицы сохраняемости.

Если вы отключите это в соответствии с приведенными ниже инструкциями, вы должны увидеть запуск второго запроса.

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

person Alan Hay    schedule 24.04.2015