Transaction management for native Hibernate Session instances with Spring's declarative transaction infrastructure.
import org.hibernate.SessionFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableTransactionManagement
public class HibernateConfig {
@Bean
public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {
return new HibernateTransactionManager(sessionFactory);
}
}import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.List;
@Service
@Transactional
public class ProductService {
private final SessionFactory sessionFactory;
public ProductService(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public Product create(String name, BigDecimal price) {
Session session = sessionFactory.getCurrentSession();
Product product = new Product();
product.setName(name);
product.setPrice(price);
session.persist(product);
return product;
}
@Transactional(readOnly = true)
public Product findById(Long id) {
Session session = sessionFactory.getCurrentSession();
return session.get(Product.class, id);
}
public void update(Long id, String name) {
Session session = sessionFactory.getCurrentSession();
Product product = session.get(Product.class, id);
if (product != null) {
product.setName(name);
// Flush happens automatically on transaction commit
}
}
public void delete(Long id) {
Session session = sessionFactory.getCurrentSession();
Product product = session.load(Product.class, id);
session.remove(product);
}
@Transactional(readOnly = true)
public List<Product> search(String namePattern) {
Session session = sessionFactory.getCurrentSession();
return session.createQuery(
"from Product p where p.name like :pattern", Product.class)
.setParameter("pattern", "%" + namePattern + "%")
.list();
}
}import javax.sql.DataSource;
@Bean
public HibernateTransactionManager transactionManager(
SessionFactory sessionFactory, DataSource dataSource) {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(sessionFactory);
txManager.setDataSource(dataSource);
txManager.setPrepareConnection(true); // Enable for read-only txns
return txManager;
}import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
@Service
public class OrderService {
private final SessionFactory sessionFactory;
public OrderService(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
@Transactional(
isolation = Isolation.SERIALIZABLE,
propagation = Propagation.REQUIRED,
timeout = 30,
rollbackFor = {BusinessException.class}
)
public Order processOrder(OrderRequest request) {
Session session = sessionFactory.getCurrentSession();
Order order = new Order();
// Process order
session.persist(order);
return order;
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void logOrderEvent(Long orderId, String eventType) {
// Always executed in new transaction
Session session = sessionFactory.getCurrentSession();
OrderEvent event = new OrderEvent();
event.setOrderId(orderId);
event.setEventType(eventType);
session.persist(event);
}
@Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
public OrderStatistics calculateStatistics() {
// Executed outside transaction context
Session session = sessionFactory.getCurrentSession();
// Calculate statistics
return new OrderStatistics();
}
}import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.transaction.PlatformTransactionManager;
@Service
public class ProductService {
private final TransactionTemplate transactionTemplate;
private final SessionFactory sessionFactory;
public ProductService(HibernateTransactionManager transactionManager,
SessionFactory sessionFactory) {
this.transactionTemplate = new TransactionTemplate(transactionManager);
this.sessionFactory = sessionFactory;
}
public Product createProgrammatically(String name, BigDecimal price) {
return transactionTemplate.execute(status -> {
Session session = sessionFactory.getCurrentSession();
Product product = new Product();
product.setName(name);
product.setPrice(price);
session.persist(product);
return product;
});
}
public void updateWithRollback(Long id, String name) {
transactionTemplate.execute(status -> {
try {
Session session = sessionFactory.getCurrentSession();
Product product = session.get(Product.class, id);
product.setName(name);
if (name.contains("invalid")) {
status.setRollbackOnly(); // Manually mark for rollback
}
} catch (Exception e) {
status.setRollbackOnly();
throw e;
}
return null;
});
}
}@Repository
public class GenericDao<T> {
private final SessionFactory sessionFactory;
private final Class<T> entityClass;
public GenericDao(SessionFactory sessionFactory, Class<T> entityClass) {
this.sessionFactory = sessionFactory;
this.entityClass = entityClass;
}
protected Session getCurrentSession() {
return sessionFactory.getCurrentSession();
}
public T findById(Long id) {
return getCurrentSession().get(entityClass, id);
}
public void save(T entity) {
getCurrentSession().persist(entity);
}
public void update(T entity) {
getCurrentSession().merge(entity);
}
public void delete(T entity) {
getCurrentSession().remove(entity);
}
public List<T> findAll() {
CriteriaBuilder cb = getCurrentSession().getCriteriaBuilder();
CriteriaQuery<T> cq = cb.createQuery(entityClass);
cq.from(entityClass);
return getCurrentSession().createQuery(cq).getResultList();
}
}@Service
@Transactional
public class BatchService {
private final SessionFactory sessionFactory;
public BatchService(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public void processBatch(List<Product> products) {
Session session = sessionFactory.getCurrentSession();
int batchSize = 50;
for (int i = 0; i < products.size(); i++) {
session.persist(products.get(i));
if (i > 0 && i % batchSize == 0) {
session.flush(); // Write to database
session.clear(); // Clear persistence context
}
}
}
}class HibernateTransactionManager {
// Constructors
HibernateTransactionManager();
HibernateTransactionManager(SessionFactory sessionFactory);
// SessionFactory configuration
void setSessionFactory(SessionFactory sessionFactory);
SessionFactory getSessionFactory();
// DataSource (for exception translation)
void setDataSource(DataSource dataSource);
DataSource getDataSource();
void setAutodetectDataSource(boolean autodetect);
// Connection preparation
void setPrepareConnection(boolean prepareConnection);
// Hibernate properties
void setHibernateProperties(Properties properties);
// Entity interceptor
void setEntityInterceptor(Interceptor interceptor);
void setEntityInterceptorBeanName(String beanName);
// JDBC exception translator
void setJdbcExceptionTranslator(SQLExceptionTranslator translator);
}