Hibernate拦截器线程安全

Kha*_*hri 2 java postgresql spring multithreading hibernate

我使用 hibernate 拦截器来拦截查询并在将它们发送到 postgresql 数据库之前对其进行更改。

对查询所做的更改特定于每个连接的用户(拦截器从用户的会话中获取用户的信息)。

问题是,由于我使用 spring 和 hibernate,拦截器是一个单例并且是在 sessionFactory 级别制作的,所以它不是线程安全的。

这是spring与hibernate相关的配置:

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />

        <property name="configLocation" value="classpath:hibernate.cfg.xml"/>


          <property name="entityInterceptor">
        <ref bean="myEntityInterceptor"/>
    </property>

<property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${jdbc.dialect}</prop>
                <prop key="hibernate.show_sql">true</prop> 

</props>
</property>
</bean> 


  <bean id="myEntityInterceptor" class="dao.generic.HibernateInterceptor"/>
Run Code Online (Sandbox Code Playgroud)

和拦截器类:

@Component
public class HibernateInterceptor extends EmptyInterceptor {

    private static final long serialVersionUID = 1L;

    final static Logger logger = Logger.getLogger(HibernateInterceptor.class);

    @Override
    public String onPrepareStatement(String sql) {
        String ps = super.onPrepareStatement(sql);

        if (SecurityContextHolder.getContext().getAuthentication() != null) {
            UserDetails ud = (UserDetails) SecurityContextHolder
                    .getContext().getAuthentication().getDetails();
                ps = ps.replaceAll("dynamic.", ud.getDb() + ".");
            }
        return ps;
    }

}
Run Code Online (Sandbox Code Playgroud)

因此,我正在寻找一种方法,通过为每个客户端会话附加一个单独的实例,而不仅仅是所有用户使用的一个实例,从而使该拦截器线程安全。

任何帮助将不胜感激..

Jon*_*n C 5

首先,您的代码对我来说似乎是线程安全的,所以我不确定您是否真的需要这个,但如果您需要,您可以通过在会话级别创建拦截器来将拦截器设置为每个会话的实例,而不是共享实例HibernateTransactionManager通过设置属性来打开entityInterceptorBeanName

来自 Spring 文档 ( HibernateTransactionManager.setEntityInterceptorBeanName):

通常用于原型拦截器,即每个会话一个新的拦截器实例。

因此,请确保您的拦截器 bean 的范围为原型

看看这个帖子