or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

exception-translation.mdhibernate-configuration.mdhibernate-transaction-management.mdindex.mdjpa-configuration.mdjpa-transaction-management.mdjpa-vendor-adapters.mdpersistence-unit-management.mdshared-resources.mdutility-classes.mdweb-integration.md
tile.json

shared-resources.mddocs/

Shared EntityManager and Session Resources

Utilities for creating shared, thread-bound EntityManager and Session proxies that integrate with Spring transaction management.

Quick Reference

Prefer @PersistenceContext injection (automatic):

@Service
public class UserService {

    @PersistenceContext  // Automatically creates shared proxy
    private EntityManager entityManager;

    @Transactional
    public void saveUser(User user) {
        entityManager.persist(user);
        // No need to close - managed by Spring
    }
}

Use explicit creation only for advanced scenarios (documented below).

Shared EntityManager

Basic Creation

@Configuration
public class JpaConfig {

    @Bean
    public EntityManager sharedEntityManager(EntityManagerFactory emf) {
        return SharedEntityManagerCreator.createSharedEntityManager(emf);
    }
}

@Service
public class UserService {

    private final EntityManager entityManager;

    public UserService(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    @Transactional(readOnly = true)
    public User findUser(Long id) {
        return entityManager.find(User.class, id);
    }
}

With Custom Properties

@Bean
public EntityManager sharedEntityManager(EntityManagerFactory emf) {
    Map<String, Object> properties = new HashMap<>();
    properties.put("jakarta.persistence.cache.retrieveMode", CacheRetrieveMode.BYPASS);
    properties.put("jakarta.persistence.cache.storeMode", CacheStoreMode.REFRESH);

    return SharedEntityManagerCreator.createSharedEntityManager(emf, properties);
}

With Transaction Synchronization Control

@Bean
public EntityManager sharedEntityManager(EntityManagerFactory emf) {
    Map<String, Object> properties = new HashMap<>();
    boolean synchronizedWithTransaction = true;

    return SharedEntityManagerCreator.createSharedEntityManager(
        emf, properties, synchronizedWithTransaction);
}

Shared Hibernate Session

Basic Creation

@Configuration
public class HibernateConfig {

    @Bean
    public Session sharedSession(SessionFactory sessionFactory) {
        return SharedSessionCreator.createSharedSession(sessionFactory);
    }
}

@Service
public class ProductService {

    private final Session session;

    public ProductService(Session session) {
        this.session = session;
    }

    @Transactional(readOnly = true)
    public Product findProduct(Long id) {
        return session.get(Product.class, id);
    }
}

With Custom SessionBuilder

@Bean
public Session sharedSession(SessionFactory sessionFactory) {
    SessionBuilder sessionBuilder = sessionFactory.withOptions()
        .tenantIdentifier("tenant-123")
        .eventListeners(new CustomInterceptor());

    return SharedSessionCreator.createSharedSession(sessionFactory, sessionBuilder);
}

Extended EntityManager (Stateful Beans)

For application-managed or container-managed extended EntityManagers:

@Configuration
public class JpaConfig {

    @Bean
    @Scope("request")
    public EntityManager extendedEntityManager(EntityManagerFactory emf) {
        // Create container-managed extended EntityManager
        return ExtendedEntityManagerCreator.createContainerManagedEntityManager(emf);
    }
}

@Controller
@Scope("request")
public class ConversationController {

    private final EntityManager extendedEntityManager;

    public ConversationController(EntityManager extendedEntityManager) {
        this.extendedEntityManager = extendedEntityManager;
    }

    // EntityManager persists across multiple method calls
    // within the same request scope
}

Shared Resource Behavior

Transaction Participation

  • Automatically participate in active Spring transactions
  • Create thread-bound resources when needed
  • Clean up resources after transaction completion

Lifecycle Management

  • No need to manually close EntityManager/Session
  • Resources automatically managed by Spring
  • Thread-safe and shareable across components

Example: Same EntityManager Instance

@Service
@Transactional
public class OrderService {

    // Shared EntityManager - same instance injected everywhere
    private final EntityManager entityManager;
    private final ProductService productService;

    public OrderService(EntityManager entityManager, ProductService productService) {
        this.entityManager = entityManager;
        this.productService = productService;
    }

    public Order createOrder(Long productId, int quantity) {
        // Get product from ProductService (uses same shared EntityManager)
        Product product = productService.findProduct(productId);

        // Create order using same EntityManager instance
        Order order = new Order();
        order.setProduct(product);
        order.setQuantity(quantity);
        entityManager.persist(order);

        return order;
    }
}

@Service
@Transactional(readOnly = true)
public class ProductService {

    // Same shared EntityManager instance
    private final EntityManager entityManager;

    public ProductService(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    public Product findProduct(Long id) {
        return entityManager.find(Product.class, id);
    }
}

Comparison: Shared vs Direct EntityManager

Shared EntityManager (Recommended)

@Service
public class UserService {

    @Autowired  // or @PersistenceContext
    private EntityManager entityManager;  // Shared proxy

    @Transactional
    public void saveUser(User user) {
        entityManager.persist(user);
        // No need to close - managed by Spring
    }
}

Direct EntityManager (Not Recommended)

@Service
public class UserService {

    @PersistenceUnit
    private EntityManagerFactory emf;

    public void saveUser(User user) {
        EntityManager em = emf.createEntityManager();
        try {
            em.getTransaction().begin();
            em.persist(user);
            em.getTransaction().commit();
        } finally {
            em.close();  // Must manually close
        }
    }
}

The shared approach simplifies code, integrates with Spring's transaction management, and reduces boilerplate.

API Reference

SharedEntityManagerCreator

abstract class SharedEntityManagerCreator {

    // Basic creation
    static EntityManager createSharedEntityManager(EntityManagerFactory emf);

    // With properties
    static EntityManager createSharedEntityManager(
        EntityManagerFactory emf,
        Map<?, ?> properties
    );

    // With transaction synchronization control
    static EntityManager createSharedEntityManager(
        EntityManagerFactory emf,
        Map<?, ?> properties,
        boolean synchronizedWithTransaction
    );

    // With custom EntityManager interfaces
    static EntityManager createSharedEntityManager(
        EntityManagerFactory emf,
        Map<?, ?> properties,
        Class<?>... entityManagerInterfaces
    );

    // Full configuration
    static EntityManager createSharedEntityManager(
        EntityManagerFactory emf,
        Map<?, ?> properties,
        boolean synchronizedWithTransaction,
        Class<?>... entityManagerInterfaces
    );
}

SharedSessionCreator

abstract class SharedSessionCreator {

    // Basic creation
    static Session createSharedSession(SessionFactory sessionFactory);

    // With SessionBuilder
    static Session createSharedSession(
        SessionFactory sessionFactory,
        SessionBuilder sessionBuilder
    );
}

ExtendedEntityManagerCreator

abstract class ExtendedEntityManagerCreator {

    // Application-managed extended EntityManager
    static EntityManager createApplicationManagedEntityManager(
        EntityManager rawEntityManager,
        EntityManagerFactoryInfo emfInfo
    );

    static EntityManager createApplicationManagedEntityManager(
        EntityManager rawEntityManager,
        EntityManagerFactoryInfo emfInfo,
        boolean synchronizedWithTransaction
    );

    // Container-managed extended EntityManager
    static EntityManager createContainerManagedEntityManager(
        EntityManager rawEntityManager,
        EntityManagerFactoryInfo emfInfo
    );

    static EntityManager createContainerManagedEntityManager(EntityManagerFactory emf);

    static EntityManager createContainerManagedEntityManager(
        EntityManagerFactory emf,
        Map<?, ?> properties
    );

    static EntityManager createContainerManagedEntityManager(
        EntityManagerFactory emf,
        Map<?, ?> properties,
        boolean synchronizedWithTransaction
    );
}

Related Topics

  • JPA Configuration - EntityManagerFactory setup
  • Web Integration - Open EntityManager in View