我正在使用Spring MVC构建应用程序。流程是非常基本的,即控制器 - >服务 - > DAO和回来。
现在,我正在创建一个RestController,它将调用服务并执行我想要的任何操作。我遇到了一个奇怪的问题,我需要帮助。
我有两个实体用户和角色。一个用户可以拥有多个角色,并且可以将角色分配给许多用户 - 基本上是 ManyToMany 映射。我为这两个依赖项提供了 FetchType.LAZY 。
当我通过浏览器登录时,Web应用程序中的一切正常。但是,当我调用RESTController时,我收到以下错误
org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: failed to lazily initialize a collection of role: com.xx.yyy.entity.Role.users, could not initialize proxy - no Session (through reference chain: com.xx.yyy.entity.User["roles"]->org.hibernate.collection.internal.PersistentBag[0]->com.xx.yyy.entity.Role["users"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: failed to lazily initialize a collection of role: com.xx.yyy.entity.Role.users, could not initialize proxy - no Session (through reference chain: com.xx.yyy.entity.User["roles"]->org.hibernate.collection.internal.PersistentBag[0]->com.xx.yyy.entity.Role["users"])
org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:238)
org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:208)
org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:161)
org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:101)
org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:202)
org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:71)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:126)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:777)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:706)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857)
javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:150)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:199)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)
这里奇怪的是,当我在用户界面上(例如,在我的网络应用程序中)时,这种方法非常好用
以下是我的实体
User.java
@Entity
@Table(name="USERS")
public class User {
@Id
@Column (name="USER_ID")
private String id;
@NotEmpty(message = "First Name is mandatory")
@Column (name="FIRST_NAME")
private String firstName;
@Column (name="LAST_NAME")
private String lastName;
@NotEmpty(message= "Email ID is mandatory")
@Column (name="EMAIL_ID")
private String emailId;
@NotEmpty(message="Primary Phone Number is mandatory")
@Column (name="PHONE_1")
private String primaryPhone;
@Column (name="PHONE_2")
private String secondaryPhone;
@Column (name="PASS_WORD")
private String password;
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable( name="ROLESMAPPING", joinColumns={@JoinColumn(name="USER_ID")}, inverseJoinColumns={@JoinColumn(name="GROUP_ID")})
private List<Role> roles = new ArrayList<Role>();
@Transient
private List<String> roleIDs = new ArrayList<String>();
//Getters and Setters
}
Role.java
@Entity
@Table( name="ROLES" )
public class Role {
@Id
@Column( name="GROUP_ID")
private String id;
@Column( name="GROUP_DESC" )
private String description;
@ManyToMany(mappedBy="roles")
@LazyCollection(LazyCollectionOption.TRUE)
private List<User> users = new ArrayList<User>();
//Getters and Setters go here
}
我在发布此问题之前添加了LazyCollection
注释(在引用了许多其他帖子之后),但它没有帮助。
我认为将响应发送回我的客户端是有意义的,因为我试图在获取用户后在我的RestController中放置一个断点,令我惊讶的是,用户被取出。在执行return user;
语句之后出现错误。这是我的Rest控制器
@RestController
@RequestMapping("/api/user")
public class GenericController {
private static final Logger logger = LoggerFactory.getLogger(GenericController.class);
@Autowired
private UserService userService;
@RequestMapping("/get/{userid}")
public User get(@PathVariable(value="userid") String userId) {
try{
if(StringUtils.isEmptyString(userId)){
userId = "admin";
}
User user = userService.getUserById(userId);
return user;
}catch(Exception e){
logger.error(e.getMessage(),e);
return null;
}
}
}
这是我尝试做的事情
我在同一个错误上引用了其他一些帖子,我尝试在我的两个实体上制作Fetch类型EAGER(即fetch=FetchType.EAGER
)。接下来发生的事情是,用户详细信息与Roles一起获取,角色转而让用户随身携带,这种情况发生在无限循环中。我得到的JSON作为输出永无止境。
请帮助我了解我出错的地方。
答案 0 :(得分:0)
感谢@Boris the Spider,我看了this post,答案就在那里!
我所做的就是将@JsonIgnore
添加到我的Child类中的字段,该类引用Parent实体,就像这样
@Entity
@Table( name="ROLES" )
public class Role {
@Id
@Column( name="GROUP_ID")
private String id;
@Column( name="GROUP_DESC" )
private String description;
@ManyToMany(mappedBy="roles")
@JsonIgnore
private List<User> users = new ArrayList<User>();
//Getters and Setters go here
}
这解决了无限循环问题。