添加@Autowire时,“找不到当前线程的会话”

时间:2012-09-04 06:15:34

标签: spring hibernate

我见过几个类似的问题,但没有一个建议的解决方案对我有帮助。

总结:当我在.xml上创建并注入bean时,它可以工作;但是当我使用@Autowire或@Resource时,却没有。

环境:Spring3,Hibernate4,Tomcat7。

详细信息:以下设置可行:

web.xml

  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
      /WEB-INF/spring/root-context.xml
      /WEB-INF/spring/security-context.xml
      /WEB-INF/spring/users-context.xml
    </param-value>
  </context-param>

root-context.xml

  <bean id="dataSource"
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://localhost:3306/venus" />
    <property name="username" value="root" />
    <property name="password" value="" />
  </bean>

  <bean id="sessionFactory"
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="packagesToScan" value="com.airbus.genesis.marte.dal" />
    <property name="hibernateProperties">
      <props>
        <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
        <prop key="hibernate.show_sql">true</prop>
      </props>
    </property>
  </bean>

  <tx:annotation-driven transaction-manager="txManager" />
  <bean id="txManager"
    class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
  </bean>

users-context.xml

  <bean id="usersDAO" class="com.airbus.genesis.marte.dal.users.UsersDAO">
    <property name="sessionFactory" ref="sessionFactory" />
  </bean>

BL对象:

@Service("usersManager")
@Transactional(readOnly = true)
public class UsersManager implements IUsersManager {
  @Autowired
  @Qualifier("usersDAO")
  private IUsersDAO usersDAO;

  @Override
  public List<User> getUsers() {
    return usersDAO.getUsers();
  }

}

DAO对象(注意@Repository和@Resource被注释):

//@Repository("usersDAO")
@Transactional(readOnly = true)
public class UsersDAO implements IUsersDAO {

  // @Resource(name = "sessionFactory")
  private SessionFactory sessionFactory;

  @Override
  public List<User> getUsers() {
    @SuppressWarnings("unchecked")
    List<User> res = (List<User>) getSessionFactory().getCurrentSession()
        .createQuery("from User").list();
    return res;
  }

  public SessionFactory getSessionFactory() {
    return sessionFactory;
  }

  public void setSessionFactory(SessionFactory sessionFactory) {
    this.sessionFactory = sessionFactory;
  }
}

但以下一个不起作用:

users-context.xml

<!-- 
  <bean id="usersDAO" class="com.airbus.genesis.marte.dal.users.UsersDAO">
    <property name="sessionFactory" ref="sessionFactory" />
  </bean>
-->

DAO对象(注意@Repository和@Resource现在已取消注释):

@Repository("usersDAO")
@Transactional(readOnly = true)
public class UsersDAO implements IUsersDAO {

  @Resource(name = "sessionFactory")
  private SessionFactory sessionFactory;

  @Override
  public List<User> getUsers() {
    @SuppressWarnings("unchecked")
    List<User> res = (List<User>) getSessionFactory().getCurrentSession()
        .createQuery("from User").list();
    return res;
  }

  public SessionFactory getSessionFactory() {
    return sessionFactory;
  }

  public void setSessionFactory(SessionFactory sessionFactory) {
    this.sessionFactory = sessionFactory;
  }
}
提出了

org.hibernate.HibernateException: No Session found for current thread

org.hibernate.HibernateException: No Session found for current thread
    org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:97)
    org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:941)
    com.airbus.genesis.marte.dal.users.UsersDAO.getUsers(UsersDAO.java:23)
    com.airbus.genesis.marte.bl.users.UsersManager.getUsers(UsersManager.java:22)
[...]

如果我使用@Autowire而不是@Resource,也会发生同样的情况。

我想这是我身边的某种误解,但找不到哪里。有什么想法吗?

1 个答案:

答案 0 :(得分:2)

问题很可能是在dispatcher-servlet.xml配置中拾取@Repository@Service注释(你使用context:component-scan吗?),所以这些bean是在调度程序servlet上下文而不是根Web应用程序上下文。

一个好的做法是将服务层对象放到专用包中,并使用特定的包名称<context:component-scan /&gt; base-package限定符(如'com.myproject.services')。您还可以使用过滤器表达式来包含和排除元素,请参阅此处的示例:@Service are constructed twiceSpring documentation

的4.10.3部分

另见Difference between applicationContext.xml and spring-servlet.xml in Spring Framework