# EntityManager Operations — Hibernate / JPA

Source: https://www.skillbyai.com/en/hibernate-jpa/p-em

> Use persist, find, getReference, merge and remove correctly.

## The core API

The **`EntityManager`** is the main JPA interface for working with entities (Hibernate's `Session` implements it and adds more). **`persist(entity)`** makes a **new** entity managed; it is inserted at the next flush. **`find(Class, id)`** loads an entity by primary key, returning `null` if it does not exist, and returns the **same instance** if it is already in the persistence context, without another query. **`getReference(Class, id)`** returns a lazy **proxy** without querying, useful for setting a foreign key (`order.setCustomer(em.getReference(Customer.class, 42L))`); accessing its fields later triggers the load, or `EntityNotFoundException` if it does not exist. **`merge(entity)`** copies the state of a **detached** object onto a managed instance (loading it if necessary) and **returns the managed copy**; the argument itself stays detached, a classic source of bugs. **`remove(entity)`** schedules deletion of a **managed** entity. **`refresh`** reloads state from the database, and **`detach`** or **`clear`** remove entities from management. In Spring applications you usually inject the `EntityManager` with `@PersistenceContext` or use Spring Data repositories, which call these methods for you.

## Operations and their effects

persist and find bring entities into the persistence context; flush turns changes into SQL.

![A central rounded area holding several entity icons, with arrows entering from the left for persist and find, and an arrow from the area down to a database cylinder.](assets/figures/hibernate-jpa/section-2-map.svg) — Figure 2.1 — EntityManager operations around the persistence context.

## Using the EntityManager directly

Note that merge returns the managed instance you should keep using.

```java
@Service
public class ProductService {

    @PersistenceContext
    private EntityManager em;

    @Transactional
    public Long create(String sku, String title, BigDecimal price) {
        Product p = new Product(sku, title, price);   // transient
        em.persist(p);                                 // managed; INSERT at flush/commit
        return p.getId();                              // id assigned (sequence) during persist
    }

    @Transactional
    public Product updateFromDto(ProductDto dto) {
        Product detached = dto.toEntity();
        Product managed = em.merge(detached);          // use the RETURNED instance
        managed.changePrice(dto.price());              // tracked; 'detached' is not
        return managed;
    }

    @Transactional
    public void delete(Long id) {
        Product p = em.find(Product.class, id);
        if (p != null) em.remove(p);                   // remove requires a managed entity
    }
}
```

## Do not call save on managed entities

Inside a transaction, a loaded entity is already managed: changing its fields is enough, and Hibernate writes the UPDATE at flush. Calling `merge` or `repository.save` again is unnecessary noise.

**Quiz:** What does `em.merge(detachedProduct)` return?

- [ ] Nothing; it updates the argument in place
- [ ] A new transient object
- [x] A managed instance with the detached object's state copied onto it
- [ ] The database row count

*Answer:* A managed instance with the detached object's state copied onto it. merge returns the managed copy; the argument itself remains detached.
