![](/img/trans.png)
[英]Hibernate Lazy loading not working with Spring Boot => failed to lazily initialize a collection of role could not initialize proxy - no Session
[英]Spring JPA Lazy Loading - Could Not Initialize Proxy
以下是一些背景代码:
InitiativeProfileQuestion.java:
@Entity
@Table
public class InitiativeProfileQuestion implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@Column(nullable = false)
private String question;
@Column
private String description;
@Column
private int sortOrder;
@OneToMany(mappedBy = "initiativeProfileQuestion", fetch = FetchType.LAZY)
private List<InitiativeProfileAnswer> answers;
public List<InitiativeProfileAnswer> getAnswers() {
return answers;
}
public void setAnswers(List<InitiativeProfileAnswer> answers) {
this.answers = answers;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getQuestion() {
return question;
}
public void setQuestion(String question) {
this.question = question;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getSortOrder() {
return sortOrder;
}
public void setSortOrder(int sortOrder) {
this.sortOrder = sortOrder;
}
}
InitiativeProfileAnswer.java:
@Entity
@Table
public class InitiativeProfileAnswer {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@Column
private String answer;
@Column
private int sortOrder;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "initiativeProfileQuestionId")
@JsonIgnore
private InitiativeProfileQuestion initiativeProfileQuestion;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getAnswer() {
return answer;
}
public void setAnswer(String answer) {
this.answer = answer;
}
public int getSortOrder() {
return sortOrder;
}
public void setSortOrder(int sortOrder) {
this.sortOrder = sortOrder;
}
public InitiativeProfileQuestion getInitiativeProfileQuestion() {
return initiativeProfileQuestion;
}
public void setInitiativeProfileQuestion(InitiativeProfileQuestion initiativeProfileQuestion) {
this.initiativeProfileQuestion = initiativeProfileQuestion;
}
}
InitiativeProfileQuestionRepository.java:
public interface InitiativeProfileQuestionRepository extends JpaRepository<InitiativeProfileQuestion, Long> {
@Query("select ipa from InitiativeProfileQuestion ipa join fetch ipa.answers")
public List<InitiativeProfileQuestion> getAllQuestions();
}
InitiativeProfileService.java:
@Service
public class InitiativeProfileService {
@Autowired
private InitiativeProfileQuestionRepository initiativeProfileQuestionRepository;
public List<InitiativeProfileQuestion> getAllQuestions() {
return initiativeProfileQuestionRepository.findAll();
}
public List<InitiativeProfileQuestion> getAllQuestionsFetch() {
return initiativeProfileQuestionRepository.getAllQuestions();
}
}
BaseController.java:
@RestController
@RequestMapping("/api")
public class BaseController {
@Autowired
InitiativeProfileService initiativeProfileService;
@RequestMapping("/question")
public List<InitiativeProfileQuestion> getQuestions() {
return initiativeProfileService.getAllQuestions();
}
@RequestMapping("/questionFetch")
public List<InitiativeProfileQuestion> getQuestionsFetch() {
return initiativeProfileService.getAllQuestionsFetch();
}
}
在我的BaseController中调用getQuestions()会返回“无法初始化代理-没有会话”错误。 但是,在我的BaseController中调用getQuestionsFetch()会很好。
我希望它以某种方式工作,如果我调用getQuestions(),则该对象将返回没有答案(因为在任何地方都不会调用延迟加载的对象)。 但是,这只是给我一个错误。 如果我正在使用联接提取进行查询,那么它也可以通过显示答案(预期行为)来工作。
我究竟做错了什么? 我在不同的地方尝试了@Transactional,但没有运气。 我也没有.xml文件-到目前为止,所有操作都使用注释完成。
我得到的错误是:
exception
org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: failed to lazily initialize a collection of role: com.testApp.domain.InitiativeProfileQuestion.answers, could not initialize proxy - no Session (through reference chain: java.util.ArrayList[0]->com.testApp.domain.InitiativeProfileQuestion["answers"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: failed to lazily initialize a collection of role: com.testApp.domain.InitiativeProfileQuestion.answers, could not initialize proxy - no Session (through reference chain: java.util.ArrayList[0]->com.testApp.domain.InitiativeProfileQuestion["answers"])
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:185)
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:776)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:705)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:858)
javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:85)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
root cause
com.fasterxml.jackson.databind.JsonMappingException: failed to lazily initialize a collection of role: com.testApp.domain.InitiativeProfileQuestion.answers, could not initialize proxy - no Session (through reference chain: java.util.ArrayList[0]->com.testApp.domain.InitiativeProfileQuestion["answers"])
com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:210)
com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:177)
com.fasterxml.jackson.databind.ser.std.StdSerializer.wrapAndThrow(StdSerializer.java:187)
com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:647)
com.fasterxml.jackson.databind.ser.std.BeanSerializerBase._serializeWithObjectId(BeanSerializerBase.java:558)
com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:145)
com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedListSerializer.java:100)
com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedListSerializer.java:21)
com.fasterxml.jackson.databind.ser.std.AsArraySerializerBase.serialize(AsArraySerializerBase.java:183)
com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:128)
com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:1902)
org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:231)
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:185)
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:776)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:705)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:858)
javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:85)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
对于延迟加载的例外情况,您必须尝试在会话外部获取关联的对象。 将延迟加载更改为热切,或者将正在获取关联对象的代码放入会话内。 例如:
public void test() {
Session session = HibernateUtil.currentSession();
session.beginTransaction();
Vehicle vehicle= (Vehicle) session.get(Vehicle.class, 2);
System.out.println(vehicle.getVehicleName());
session.getTransaction().commit();
session.close();
System.out.println(vehicle.getVehicleName()); //No exception here
System.out.println(vehicle.getUser().getUserName());
// Exception here change the loading to EAGER or put this line of code within the session above. Put it before session.close() or before session.getTransaction().commit();
}
从堆栈跟踪中可以看到,当Jackson尝试访问延迟加载的对象以将其序列化为JSON时,将发生错误。 此时,spring事务已经完成,并且Hibernate会话关闭,这就是为什么Hibernate无法再加载该对象的原因。
如果您不希望将该字段序列化,则可能希望使用@JsonIgnore或Spring的Jackson序列化视图支持 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.