Kev*_*ave 5 java junit spring jpa struts2
我的应用程序使用 Struts2(mvc)、Spring(依赖注入)、带有 Hibernate 的 JPA、JUnit 以及 struts2-junit 插件和 struts2 spring 插件。
这是我的测试课:
@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());
}
}
Run Code Online (Sandbox Code Playgroud)
获取用户信息
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;
}
}
}
...
...
}
}
Run Code Online (Sandbox Code Playgroud)
User 和 UDetails 是实体。UDetalisManyToMany
具有User
延迟获取功能。所有实体都带有注释。
用户管理
public class UserMgmt {
public User getUser(String userId) {
return userDao.getUser(userId);
}
}
Run Code Online (Sandbox Code Playgroud)
用户DAO
public class UserDAO extends AbstractJPAImpl{
public User getUser(String userId) {
User user = (User) getSession().get(User.class, userId);
return user;
}
}
Run Code Online (Sandbox Code Playgroud)
摘要JPAImpl
@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();
}
....
}
Run Code Online (Sandbox Code Playgroud)
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"/>
Run Code Online (Sandbox Code Playgroud)
所有配置/上下文文件都加载良好。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:
Run Code Online (Sandbox Code Playgroud)
在以下行:
for(UDetails det : user.getUDetails())
Run Code Online (Sandbox Code Playgroud)
显然,它试图延迟加载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>
Run Code Online (Sandbox Code Playgroud)
更新:
如果我将参数传递给@PersistenceContext
注释,这最终会起作用,如下所示:
@PersistenceContext(type=PersistenceContextType.EXTENDED)
Run Code Online (Sandbox Code Playgroud)
所以我猜想,事务正在关闭,但由于扩展上下文类型,实体可以在事务之外操作。但是,我无法像上面那样修改代码并永久保留它。所以我需要将其删除。
所以我想,我有这些选择,但不确定这些是否可行以及如何实现:
从spring应用程序上下文中获取持久化上下文并传递参数。不确定这是否相关且可能。
从应用程序上下文中获取会话/实体管理器并添加另一层事务。这样,会话就可以在两个事务中运行。一个是从我的测试代码开始的,另一个是在现有代码中,它会自动关闭,而我的则保持打开状态,直到我的测试代码完成执行。
对于第二个,我尝试用 注释该方法@Transactional
。但这没有用。不知道为什么。
有什么帮助吗?
更新
看起来,struts-junit 插件不会加载/读取 web.xml,它具有OpenEntityManagerInViewFilter
. 所以它没有被加载。
还有其他解决办法或设置此过滤器吗?
如果它对任何人有帮助,我无法让 @Transaction 工作。但我这样说:
@PersistenceContext(type=PersistenceContextType.EXTENDED)
Run Code Online (Sandbox Code Playgroud)
现在可以了!
……
归档时间: |
|
查看次数: |
3213 次 |
最近记录: |