从控制器启动应用程序并调用服务时,出现“找不到会话”异常。但是,我可以从单元测试中成功调用相同的服务。
当我在控制器类上调用userService.userExists(username)方法时,就会发生这种情况。我开始在调试器中跟踪执行情况,发现即使我将服务装饰为事务性事务,TransactionSynchronizationManager资源对象映射也为空。但是,当我从单元测试中调用服务时,TransactionSynchronizationManager上有资源。
控制器类:
@Controller public class DiaryController { @Autowired private UserService userService; @RequestMapping(method = RequestMethod.GET, value = "/diary/{username}") public String home(@PathVariable String username, ModelMap model) { String authUser = SecurityContextHolder.getContext().getAuthentication().getName(); if(authUser.equals(username)) { model.addAttribute("message", "Hey there. How's it going " + username + "?"); } else if (userService.userExists(username)) { model.addAttribute("message", "You're looking at diary for " + username + "."); } else { model.addAttribute("message", "User " + username + " does not exist."); } return "diary"; } }
hibernate上下文:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:database.properties</value> </list> </property> </bean> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${jdbc.driver}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.user}" /> <property name="password" value="${jdbc.password}" /> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="mappingLocations"> <list> <value>classpath*:hbm/User.hbm.xml</value> </list> </property> <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="transactionManager"/> <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"/> </bean>
应用环境:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/jsp/" /> <property name="suffix" value=".jsp" /> </bean> <mvc:annotation-driven/> <mvc:resources mapping="/resources/**" location="/resources/"/>
UserDoaImpl:
@Repository public class UserDaoImpl extends AbstractDaoImpl<User, String> implements UserDao { protected UserDaoImpl() { super(User.class); } @Override public void saveUser(User user) { saveOrUpdate(user); } @Override public List<User> findUsers(String username) { return findByCriteria(Restrictions.like("username", username, MatchMode.EXACT)); } @Override public boolean exists(String username) { return findById(username) != null; } }
我的工作单元测试:
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath:/spring/applicationContext.xml", "classpath:/spring/securityContext.xml", "classpath:/spring/hibernateContext.xml" }) public class UserServiceTest { @Autowired private UserService userService; @Test public void userServiceTest() { Assert.assertTrue(userService.userExists("fergal")); } }
UserServiceImpl:
@Service("userService") @Transactional(readOnly = true) public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; @Override public User findByUserName(String userName) { return userDao.findById(userName); } @Override @Transactional(readOnly = false) public void saveUser(User user) { userDao.saveUser(user); } @Override @Transactional(readOnly = false) public void deleteUser(String userName) { User user = userDao.findById(userName); if (user != null) { userDao.delete(user); } } @Override public List<User> findUsers(String user) { return userDao.findUsers(user); } @Override public boolean userExists(String username) { return userDao.exists(username); }
web.xml
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <display-name>MyApp</display-name> <servlet> <servlet-name>myapp-dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:/spring/applicationContext.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>myapp-dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:/spring/**</param-value> </context-param> <filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> </web-app>
将以下过滤器添加到您的web.xml。您可以在http://static.springsource.org/spring/docs/3.1.x/javadoc- api/org/springframework/orm/hibernate4/support/OpenSessionInViewFilter.html中查看有关此过滤器的更多信息。
<filter> <filter-name>hibernateFilter</filter-name> <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class> <init-param> <param-name>sessionFactoryBeanName</param-name> <param-value>sessionFactory</param-value> </init-param> </filter> <filter-mapping> <filter-name>hibernateFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>