我的应用程序使用Struts2(mvc),Spring(依赖注入),JPA with Hibernate,JUnit以及struts2 -junit插件和struts2弹簧插件。保持会话在JUnit/JPA/Hibernate/Struts和Spring集成测试中打开 - 没有会话或会话关闭 - LazyInitialization异常
这里是我的测试类:
@RunWith(SpringJUnit4ClassRunner.class)
public class CustomerSearchIntegrationTest extends StrutsSpringTestCase {
@Test
@Transactional
public void testGetActionProxy() throws Exception {
ActionProxy proxy;
String result;
ActionMapping mapping = getActionMapping("userInfo");
assertNotNull(mapping);
..... // Some JUnit init code..
ActionProxy proxy = getActionProxy("userInfo");
UserInfo user = (UserInfo) proxy.getAction();
result = proxy.execute();
assertEquals("details", result);
System.out.prinltn("Username:" + user.getFirstName());
}
}
GetUserInfo
public class UserInfo extends ActionSupport {
User user; // Entity
UDetails details; // Entity
public String getUserDetails() { //Action method
user = userMgmt.getUser(usrId);
if (user != null) {
for(UDetails det : user.getUDetails()) { // user.getUDetails() there is where exception gets thrown.
if(det.getStreet().equals(street)){
details = det;
break;
}
}
}
...
...
}
}
用户和UDetails都是实体。 UDetalis为ManyToMany
,User
和Lazily提取。所有实体都被注释。
UserMgmt
public class UserMgmt {
public User getUser(String userId) {
return userDao.getUser(userId);
}
}
UserDAO的
public class UserDAO extends AbstractJPAImpl{
public User getUser(String userId) {
User user = (User) getSession().get(User.class, userId);
return user;
}
}
AbstractJPAImpl
@Transactional
public abstract class AbstractJPAImpl {
private EntityManager em;
@PersistenceContext
protected void setEntityManager(EntityManager em) {
this.em = em;
}
@Transactional
protected Session getSession() {
return (Session) em.getDelegate();
}
....
}
jpaContext.xml
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
// other config stuff
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
所有配置/上下文文件加载正常。 Struts.xml,jpacontext.xml,beans.xml等全部被加载。
但我得到一个异常:
failed to lazily initialize a collection of role: com.my.data.User.udetails, no session or session was closed
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role:
在下面一行:
for(UDetails det : user.getUDetails())
显然,它试图加载UDetails
懒洋洋地,然后异常抛出。 但是,此应用程序在AppServer(WebSphere)中部署时工作正常。
我会做什么错?我如何保持会话打开?
更新:更多信息
我使用OpenEntityManagerInViewFilter
。我下面的web.xml
<filter>
<filter-name>OpenEntityManagerInViewFilter</filter-name>
<filter-class>
org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>OpenEntityManagerInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
更新:
这最后的作品,如果我通过了参数@PersistenceContext
注解如下图所示:
@PersistenceContext(type=PersistenceContextType.EXTENDED)
所以我想,本次交易获得关闭,但由于EXTENDED上下文类型,实体可以在事务外运行。但是,我不能修改上面的代码并永久保留它。所以我需要删除它。
所以我想,我有这些选项,但不知道如果这些都是可行的,如何:
获得从Spring应用程序上下文的持久化上下文和传递参数。不确定这是否相关且可能。
从应用程序上下文获取会话/实体管理器并添加另一层事务。以这种方式,会话运行在两个事务中。一个是从我的测试代码开始,另一个是现有的代码,它会自动关闭,而我的测试代码完成执行之前,我的代码仍处于打开状态。
对于第二个,我尝试使用@Transactional
注释该方法。但那并不奏效。不知道为什么。
任何帮助?
更新
样子,Struts的JUnit的插件不加载/读取web.xml中,它具有OpenEntityManagerInViewFilter
。所以它没有被加载。
任何其他解决方法或设置此过滤器?
您可以发布测试类的完整代码,或者至少是类定义以及在类级应用的任何注释吗? – 2014-11-06 16:22:16
@AlanHay更新了我的测试课程。请检查。 – 2014-11-06 16:25:48
您正在运行容器测试,因此In不会期望Filter会触发。如果一切都配置正确,我会希望外部交易(在测试方法上)保持活跃并允许实体保持“附加”。我看到你在这里看到了接受的答案。你有没有试过这个解决方案http://stackoverflow.com/a/19109838/1356423 – 2014-11-07 10:35:12