Работа с 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.