Работа с EntityManager
EntityManager
– это стандартный интерфейс JPA для загрузки и сохранения сущностей. Он также может выполнять собственные SQL-запросы.
Мы рекомендуем использовать DataManager для работы с сущностями и обращаться к EntityManager только если он вам действительно нужен.
|
Для получения информации о методах EntityManager
обратитесь к документации API javax.persistence.EntityManager.
EntityManager
можно использовать в приложениях Jmix для работы с сущностями JPA в основном таким же образом, как и в любом приложении Spring. Однако Jmix предоставляет собственную реализацию стандартного интерфейса, которая имеет некоторые особенности.
Получение EntityManager
Экземпляр EntityManager
можно инжектировать в любой бин Spring с помощью аннотации @PersistenceContext
. Для использования экземпляра EntityManager
у вас должна быть открытая транзакция. Например:
@PersistenceContext
private EntityManager entityManager;
@Transactional
public Customer createCustomer() {
Customer customer = metadata.create(Customer.class);
customer.setName("Bob");
entityManager.persist(customer);
return customer;
}
Если вам нужно работать с сущностями из дополнительного хранилища данных, получите экземпляр EntityManager
для этого хранилища, указав имя хранилища данных в параметре unitName
аннотации @PersistenceContext
, например:
@PersistenceContext(unitName = "db1")
private EntityManager entityManagerForDb1;
@Transactional("db1TransactionManager")
public Foo createFoo() {
Foo foo = metadata.create(Foo.class);
foo.setName("foo1");
entityManagerForDb1.persist(foo);
return foo;
}
EntityManager нельзя инжектировать в контроллеры UI.
|
Использование фетч-планов
По умолчанию при использовании EntityManager
для загрузки сущностей по id или запросу JPQL, он возвращает все локальные (непосредственные) атрибуты и жадно извлеченные ссылки по правилам спецификации JPA. Другие ссылки загружаются лениво в той же транзакции.
Вы можете использовать фетч-планы для оптимизации загрузки необходимого графа объектов независимо от инструкции извлечения FetchType.LAZY
в аннотациях атрибутов сущности. Фетч-план должен быть указан в свойствах. Например:
@PersistenceContext
private EntityManager entityManager;
@Autowired
private FetchPlans fetchPlans;
@Transactional
public Order findOrder(UUID orderId) {
FetchPlan fetchPlan = fetchPlans.builder(Order.class)
.add("customer")
.build();
Map<String, Object> properties = PersistenceHints.builder()
.withFetchPlan(fetchPlan)
.build();
return entityManager.find(Order.class, orderId, properties);
}
В приведенном выше примере будут загружены все локальные атрибуты сущности Order
и связанной с ней Customer
, даже если они не включены в план выборки явно. Если вы хотите загрузить только часть локальных атрибутов, создайте «частичный» фетч-план. Например:
@Transactional
public Order loadGraphOfPartialEntities(UUID orderId) {
FetchPlan fetchPlan = fetchPlans.builder(Order.class)
.addAll("number", "date", "customer.name")
.partial()
.build();
Map<String, Object> properties = PersistenceHints.builder()
.withFetchPlan(fetchPlan)
.build();
return entityManager.find(Order.class, orderId, properties);
}
Мягкое удаление
EntityManager
поддерживает мягкое удаление. Когда вы вызываете метод remove()
для сущности с чертой Soft Delete, он обновляет атрибуты @DeletedDate
и @DeletedBy
вместо удаления записи из базы данных.
Вы можете отключить мягкое удаление для конкретной транзакции, чтобы полностью удалить объекты с чертой Soft Delete и иметь возможность загружать экземпляры, помеченные как удаленные, указав свойство PersistenceHints.`SOFT_DELETION
. Например:
@Transactional
public void hardDelete(Product product) {
entityManager.setProperty(PersistenceHints.SOFT_DELETION, false);
entityManager.remove(product);
}
Ограничения EntityManager
-
События EntitySavingEvent и EntityLoadingEvent не отправляются при сохранении и загрузке сущностей с
EntityManager
. -
Ленивая загрузка ссылок вне транзакции, загружающей корневую сущность, не работает. Вы получите исключение "java.lang.IllegalStateException: Cannot get unfetched attribute …'’, если получите доступ к такой ссылке.
-
Ссылки между хранилищами данных не поддерживаются.
-
Проверки доступа к данным пропускаются.
-
Не поддерживаются следующие функции JPA: именованные запросы,
CriteriaBuilder
,EntityGraph
,EntityTransaction
.