Spring Boot:事务启动时自动启用Hibernate Session Filter相关问询
关于Hibernate Session与过滤器自动启用的问题解答
1. Spring Boot是否会为每个HTTP请求创建专属的Hibernate Session?
默认情况下,Spring Boot开启**Open Session in View(OSIV)**模式(配置spring.jpa.open-in-view=true为默认值),此时每个HTTP请求会绑定一个独立的Hibernate Session:
- Session在请求初始化时创建,直到响应返回后才关闭,整个请求周期内的所有数据库操作(包括多个事务)都会复用这个Session。
- 如果手动关闭OSIV(设置
spring.jpa.open-in-view=false),Session的生命周期将与事务绑定:每个@Transactional方法会创建或复用一个Session,一个HTTP请求若包含多个事务,可能对应多个Session,但单事务内共用一个Session。
2. 能否通过回调等方式拦截Session创建以启用Hibernate Filter?
可以,以下是几种可靠的实现方案:
方案一:利用Hibernate Session创建事件监听
通过监听SESSION_CREATED事件,在Session创建时自动启用过滤器:
import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.event.service.spi.EventListenerRegistry; import org.hibernate.event.spi.EventType; import org.hibernate.event.spi.SessionCreatedEvent; import org.hibernate.event.spi.SessionEventListener; import org.springframework.stereotype.Component; import jakarta.annotation.PostConstruct; import jakarta.persistence.EntityManagerFactory; @Component public class SessionFilterInitializer { private final EntityManagerFactory entityManagerFactory; public SessionFilterInitializer(EntityManagerFactory entityManagerFactory) { this.entityManagerFactory = entityManagerFactory; } @PostConstruct public void initSessionListener() { SessionFactory sessionFactory = entityManagerFactory.unwrap(SessionFactory.class); if (sessionFactory instanceof SessionFactoryImplementor) { EventListenerRegistry registry = ((SessionFactoryImplementor) sessionFactory) .getServiceRegistry().getService(EventListenerRegistry.class); registry.appendListeners(EventType.SESSION_CREATED, new SessionCreatedListener()); } } private static class SessionCreatedListener implements SessionEventListener { @Override public void sessionCreated(SessionCreatedEvent event) { Session session = event.getSession(); // 启用目标过滤器,可按需设置参数 session.enableFilter("yourTargetFilter") .setParameter("filterParam", "paramValue"); } } }
方案二:结合Spring事务同步机制
在事务启动时,通过TransactionSynchronization获取当前Session并启用过滤器,更贴合事务生命周期:
import org.hibernate.Session; import org.springframework.stereotype.Component; import org.springframework.transaction.support.TransactionSynchronization; import org.springframework.transaction.support.TransactionSynchronizationManager; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; @Component public class TransactionFilterEnabler { @PersistenceContext private EntityManager entityManager; public void enableFilterForCurrentTransaction() { if (TransactionSynchronizationManager.isSynchronizationActive()) { TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { @Override public void beforeCommit(boolean readOnly) { Session session = entityManager.unwrap(Session.class); session.enableFilter("yourTargetFilter") .setParameter("filterParam", "paramValue"); } }); } } }
搭配AOP全局拦截所有@Transactional方法,自动执行过滤器启用逻辑:
import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; @Aspect @Component public class TransactionAspect { private final TransactionFilterEnabler filterEnabler; public TransactionAspect(TransactionFilterEnabler filterEnabler) { this.filterEnabler = filterEnabler; } @Before("@annotation(org.springframework.transaction.annotation.Transactional)") public void enableFilterBeforeTransaction() { filterEnabler.enableFilterForCurrentTransaction(); } }
方案三:自定义Hibernate拦截器
实现EmptyInterceptor,在Session创建后触发过滤器启用:
import org.hibernate.EmptyInterceptor; import org.hibernate.Session; import org.springframework.stereotype.Component; @Component public class FilterEnablingInterceptor extends EmptyInterceptor { @Override public void postCreateSession(Session session) { session.enableFilter("yourTargetFilter") .setParameter("filterParam", "paramValue"); } }
通过配置类注册该拦截器:
import org.hibernate.boot.SessionFactoryBuilder; import org.hibernate.boot.spi.SessionFactoryBuilderFactory; import org.hibernate.boot.spi.SessionFactoryBuilderImplementor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class HibernateConfig { @Bean public SessionFactoryBuilderFactory sessionFactoryBuilderFactory(FilterEnablingInterceptor interceptor) { return defaultBuilder -> { defaultBuilder.applyInterceptor(interceptor); return defaultBuilder; }; } }
内容的提问来源于stack exchange,提问作者Massimo Intelisano
相关产品推荐
相关产品推荐

