Helper utilities for EntityManager/Session management, JDBC connection access, and transaction timeout configuration.
Core utility class for JPA EntityManager handling and exception translation.
@Service
public class DynamicEntityManagerService {
@Autowired
private BeanFactory beanFactory;
public void processWithDynamicPU(String persistenceUnitName) {
EntityManagerFactory emf =
EntityManagerFactoryUtils.findEntityManagerFactory(
(ListableBeanFactory) beanFactory,
persistenceUnitName
);
EntityManager em =
EntityManagerFactoryUtils.getTransactionalEntityManager(emf);
// Use EntityManager
}
}@Service
@Transactional(timeout = 30)
public class ReportService {
@Autowired
private EntityManagerFactory entityManagerFactory;
public List<Report> generateComplexReport() {
EntityManager em =
EntityManagerFactoryUtils.getTransactionalEntityManager(entityManagerFactory);
TypedQuery<Report> query = em.createQuery(
"SELECT r FROM Report r WHERE r.complex = true",
Report.class
);
// Apply current transaction timeout to the query
EntityManagerFactoryUtils.applyTransactionTimeout(query, entityManagerFactory);
return query.getResultList();
}
}public class CustomDataAccessor {
private EntityManager entityManager;
public User findUser(Long id) {
try {
return entityManager.find(User.class, id);
} catch (RuntimeException ex) {
DataAccessException dae =
EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(ex);
if (dae != null) {
throw dae;
}
throw ex;
}
}
}@Service
public class BatchProcessingService {
@Autowired
private EntityManagerFactory entityManagerFactory;
public void processBatch() {
EntityManager em = null;
try {
em = EntityManagerFactoryUtils.getTransactionalEntityManager(
entityManagerFactory
);
// Process batch
for (int i = 0; i < 1000; i++) {
Entity entity = new Entity();
em.persist(entity);
if (i % 100 == 0) {
em.flush();
em.clear();
}
}
} finally {
if (em != null) {
EntityManagerFactoryUtils.closeEntityManager(em);
}
}
}
}@Service
public class TransactionalService {
@Autowired
private EntityManagerFactory entityManagerFactory;
@Transactional
public void performTransactionalWork() {
// Get EntityManager bound to current transaction
EntityManager em =
EntityManagerFactoryUtils.getTransactionalEntityManager(entityManagerFactory);
// All operations participate in same transaction
User user = new User();
em.persist(user);
Order order = new Order();
order.setUser(user);
em.persist(order);
// Changes flushed and committed when transaction completes
}
@Transactional(readOnly = true)
public List<User> readOnlyQuery() {
EntityManager em =
EntityManagerFactoryUtils.getTransactionalEntityManager(entityManagerFactory);
// EntityManager configured for read-only mode
return em.createQuery("SELECT u FROM User u", User.class)
.getResultList();
}
}@Service
public class CustomPropertyService {
@Autowired
private EntityManagerFactory entityManagerFactory;
@Transactional
public User findWithHints(Long id) {
Map<String, Object> properties = new HashMap<>();
properties.put("jakarta.persistence.cache.retrieveMode",
CacheRetrieveMode.BYPASS);
properties.put("jakarta.persistence.cache.storeMode",
CacheStoreMode.REFRESH);
EntityManager em =
EntityManagerFactoryUtils.getTransactionalEntityManager(
entityManagerFactory, properties
);
return em.find(User.class, id);
}
}abstract class EntityManagerFactoryUtils {
// Constant
int ENTITY_MANAGER_SYNCHRONIZATION_ORDER;
// Find EntityManagerFactory
static EntityManagerFactory findEntityManagerFactory(
ListableBeanFactory beanFactory,
String unitName
);
// Obtain transactional EntityManager
static EntityManager getTransactionalEntityManager(EntityManagerFactory emf);
static EntityManager getTransactionalEntityManager(
EntityManagerFactory emf,
Map<?, ?> properties
);
static EntityManager doGetTransactionalEntityManager(
EntityManagerFactory emf,
Map<?, ?> properties
);
static EntityManager doGetTransactionalEntityManager(
EntityManagerFactory emf,
Map<?, ?> properties,
boolean synchronizedWithTransaction
);
// Apply transaction timeout
static void applyTransactionTimeout(Query query, EntityManagerFactory emf);
// Exception translation
static DataAccessException convertJpaAccessExceptionIfPossible(RuntimeException ex);
// Close EntityManager
static void closeEntityManager(EntityManager em);
}Spring-based implementation of Hibernate's ManagedBeanRegistry for bean management:
@Configuration
public class HibernateConfig {
@Bean
public LocalSessionFactoryBean sessionFactory(
DataSource dataSource,
ConfigurableListableBeanFactory beanFactory) {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource);
sessionFactory.setPackagesToScan("com.example.domain");
Properties properties = new Properties();
properties.put("hibernate.dialect",
"org.hibernate.dialect.PostgreSQLDialect");
// Configure Spring bean container for Hibernate
properties.put("hibernate.resource.beans.container",
new SpringBeanContainer(beanFactory));
sessionFactory.setHibernateProperties(properties);
return sessionFactory;
}
}class SpringBeanContainer implements ManagedBeanRegistry {
// Constructor
SpringBeanContainer(ConfigurableListableBeanFactory beanFactory);
}Accessing underlying JDBC Connection through EntityManager:
@Service
public class JdbcOperationsService {
@Autowired
private EntityManagerFactory entityManagerFactory;
@Transactional
public void performJdbcOperation() {
EntityManager em =
EntityManagerFactoryUtils.getTransactionalEntityManager(entityManagerFactory);
// Unwrap to Hibernate Session (if using Hibernate)
Session session = em.unwrap(Session.class);
// Execute work with JDBC Connection
session.doWork(connection -> {
try (PreparedStatement ps = connection.prepareStatement(
"UPDATE users SET last_login = ? WHERE id = ?")) {
ps.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
ps.setLong(2, 123L);
ps.executeUpdate();
}
});
}
}EntityManagerFactoryUtils methods are thread-safe:
getTransactionalEntityManager() returns EntityManager bound to current thread's transaction@Service
public class ConcurrentService {
@Autowired
private EntityManagerFactory entityManagerFactory;
@Transactional
public void processInTransaction() {
// All these calls return the same EntityManager instance
EntityManager em1 =
EntityManagerFactoryUtils.getTransactionalEntityManager(entityManagerFactory);
EntityManager em2 =
EntityManagerFactoryUtils.getTransactionalEntityManager(entityManagerFactory);
assert em1 == em2; // Same instance within transaction
}
}