简体   繁体   中英

Hibernate interceptor thread safety

I'm using a hibernate interceptor to intercept queries and alter them before they are sent to the postgresql database.

The change made on the queries is specific to every connected user(the interceptor is getting the user's information from his session).

The problem is, since i'm using spring along with hibernate, the interceptor is a singleton and made at the sessionFactory level, so it's not thread-safe.

This is the configuration of spring related to 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"/>

And the interceptor class :

@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;
    }

}

So I'm lookinf for a way to make this interceptor thread-safe by attaching a seperate instance for every client session and not only one instance used by all the users.

Any help will be appreciated..

First, your code seems thread safe to me, so I'm not sure if you really need this, but in case you do, you can set the interceptor to be an instance per session instead of a shared instance by creating it at Session level on HibernateTransactionManager by setting the property entityInterceptorBeanName

From Spring Doc ( HibernateTransactionManager.setEntityInterceptorBeanName ):

Typically used for prototype interceptors, ie a new interceptor instance per session.

So, make sure your interceptor bean is scoped as prototype

Take a look at this post

SingleTon objects can be treated as thread safe, as long as the object does not hold any state information (ie, instance variables with getters and setters). So, here in this example, HibernateInterceptor object is thread safe.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM