Spring + Hibernate:没有Hibernate Session绑定到线程 [英] Spring + Hibernate: No Hibernate Session bound to thread

查看:151
本文介绍了Spring + Hibernate:没有Hibernate Session绑定到线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图实现以下内容:在SpringSecurity注销处理程序中清除数据库中的一些细节。尝试从DB获取用户详细信息后出现此错误的主要问题。其他代码甚至相同的方法在其他情况下都可以正常工作。

  public class CurrentUserLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {

/ **
*
* /
@Autowired
private RequestsService requestsService;

/ **
*
* /
@Autowired
私人OffersService offersService;

/ **
*
* /
@Autowired
private UsersService usersService;
$ b $ **


@Override
public void onLogoutSuccess(HttpServletRequest请求,HttpServletResponse响应,身份验证身份验证)
throws IOException,ServletException {
if(authentication!= null){
UserDetailsExtended details =(UserDetailsExtended)authentication.getPrincipal();
User user = usersService.get(details.getId()); //在这里失败

requestsService.unlockAllByBackoffice(user);
offersService.unlockAllByBackoffice(user);
}

setDefaultTargetUrl(/);
super.onLogoutSuccess(request,response,authentication);


$ / code $ / pre

$ p

 < bean id =sessionFactoryclass =org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean> 
< property name =dataSourceref =dataSource/>
< property name =packagesToScanvalue =com.ejl.butler.object.data/>
< property name =hibernateProperties>
<道具>
< prop key =hibernate.dialect> $ {hibernate.dialect}< / prop>
< prop key =hibernate.show_sql> $ {hibernate.show_sql}< / prop>
< prop key =hibernate.format_sql> $ {hibernate.format_sql}< / prop>
< prop key =hibernate.cache.use_query_cache> $ {hibernate.cache.use_query_cache}< / prop>
< prop key =hibernate.cache.region.factory_class> $ {hibernate.cache.region.factory_class}< / prop>
< /道具>
< / property>
< / bean>
< bean id =transactionManagerclass =org.springframework.orm.hibernate3.HibernateTransactionManager>
< property name =sessionFactoryref =sessionFactory/>
< / bean>

DAO:

  public User get(final Long id){
Session session = SessionFactoryUtils.getSession(sessionFactory,false);

return(User)session.get(User.class,id);

Spring安全配置:

 < logout invalidate-session =truelogout-url =/ logoutsuccess-handler-ref =logoutSuccessHandler/> 

例外:

 没有Hibernate Session绑定到线程,并且配置不允许在这里创建非事务性的$ b $ org.springframework.orm.hibernate3.SessionFactoryUtils.doGetSession(SessionFactoryUtils.java:356)
在org.springframework.orm.hibernate3.SessionFactoryUtils.getSession(SessionFactoryUtils.java:202)

@Transactional 解决了这个问题,但我不明白为什么?我的意思是它只会在所有其他调用中的这个处理函数中失败,没有这个注解,这个方法就可以正常工作!



UPD:
我的临时解决方案是将 @Transactional 添加到整个 onLogoutSuccess 方法中。 。它的工作原理)

解决方案

如果您在您的定义中有一个 TransactionManager spring上下文中,你必须指定 @Transactional 堆栈中的某处。否则,您会遇到您遇到的异常,因为您尝试在事务外部运行查询。



对此类指定有一些解决方法 current_session_context_class 在您的hibernate配置中 thread

 < property name =current_session_context_class> org.hibernate.context.ThreadLocalSessionContext< / property> 

但它不是生产安全的。



current_session_context_class 的可能值是 jta thread 托管。除此之外,休眠框支持 jta thread 。在大多数独立的hibernate应用程序或基于Spring轻量级框架和 jta 的应用程序中使用 thread Java EE环境。



另请尝试 sessionFactory.getCurrentSession(),而不是 SessionFactoryUtils.getSession ()


I am trying to implement the following: clear some details from DB on SpringSecurity logout handler. The main problem that after trying to get user details from DB I get this error. The rest of code and even the same method work fine in other cases.

public class CurrentUserLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {

    /**
     * 
     */
    @Autowired
    private RequestsService requestsService;

    /**
     * 
     */
    @Autowired
    private OffersService offersService;

    /**
     * 
     */
    @Autowired
    private UsersService usersService;

    /**
     * 
     */
    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
            throws IOException, ServletException {
        if (authentication != null) {
            UserDetailsExtended details = (UserDetailsExtended) authentication.getPrincipal();
            User user = usersService.get(details.getId()); // fails here

            requestsService.unlockAllByBackoffice(user);
            offersService.unlockAllByBackoffice(user);
        }

        setDefaultTargetUrl("/");
        super.onLogoutSuccess(request, response, authentication);
    }
}

Config:

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="packagesToScan" value="com.ejl.butler.object.data" />
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
                <prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
                <prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
                <prop key="hibernate.cache.region.factory_class">${hibernate.cache.region.factory_class}</prop>
           </props>
        </property>
    </bean>
    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

DAO:

public User get(final Long id) {
        Session session = SessionFactoryUtils.getSession(sessionFactory, false);

        return (User) session.get(User.class, id);
    }

Spring security config:

<logout invalidate-session="true" logout-url="/logout" success-handler-ref="logoutSuccessHandler"/>

Exception:

No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
    at org.springframework.orm.hibernate3.SessionFactoryUtils.doGetSession(SessionFactoryUtils.java:356)
    at org.springframework.orm.hibernate3.SessionFactoryUtils.getSession(SessionFactoryUtils.java:202)

@Transactional resolves the problem but I can't understand why? I mean it fails only in this handler in all other calls this method works fine without this annotation!

Thank you in advance!

UPD: My temporary solution is to add @Transactional to whole onLogoutSuccess method.. It works)

解决方案

If you have defined a TransactionManager in your spring context you have to specify @Transactional somewhere in the stack. Otherwise you will get the exception you encountered because you are trying to run a query outside of a transaction.

There are workarounds to this such specifying current_session_context_class in your hibernate configuration to thread or

<property name="current_session_context_class">org.hibernate.context.ThreadLocalSessionContext</property>

but it's not production safe..

The possible values for current_session_context_class are jta, thread and managed. Further to that, jta and thread are supported by hibernate out of box. thread context is used in most stand alone hibernate apps or those based on light weight frameworks like Spring and jta is used in Java EE environments.

Also try sessionFactory.getCurrentSession() instead of SessionFactoryUtils.getSession().

这篇关于Spring + Hibernate:没有Hibernate Session绑定到线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆