2

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

摘要:当我在 .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,也会发生同样的情况。

我想这是我这边的某种误解,但找不到在哪里。任何的想法?

4

1 回答 1

2

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

一个好的做法是将您的服务层对象放到专用包中,并使用特定的包名称作为<context:component-scan/>base-package限定符(如“com.myproject.services”)。您还可以使用过滤器表达式来包含和排除元素,请参见此处的示例:@Service 被构造两次和Spring 文档 的 4.10.3 部分

另请参阅Spring Framework 中 applicationContext.xml 和 spring-servlet.xml 之间的区别

于 2012-09-04T07:18:13.180 回答