我有一个Spring Boot项目,我无法进行延迟加载工作。我有2个实体:Question
和Answer
。一个问题可以有很多答案。
我想要的是,当我试图得到答案时,只得到答案而没有问题。而且,如果我想要两者,也有这种可能性。
我做了什么,是我在application.yml中添加的:spring.jpa.open-in-view:true。
Answer
实体就像:
@Entity
@Table(name = "mst_ans_answer", schema = "lquest_sc")
public class Answer implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "lquest_sc.mst_ans_answer_ans_lqs_id_seq")
@SequenceGenerator( name = "lquest_sc.mst_ans_answer_ans_lqs_id_seq", sequenceName = "lquest_sc.mst_ans_answer_ans_lqs_id_seq")
@Column(name = "ans_lqs_id")
private int id;
@Column(name = "qst_lqs_id")
private int questionId;
@Column(name = "ans_text")
private String text;
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "qst_lqs_id", insertable=false, updatable=false)
@JsonIgnore
private Question question;
//getters and setters
}
Question
实体是:
@Entity
@Table(name = "mst_qst_question", schema = "lquest_sc")
public class Question implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "lquest_sc.mst_qst_question_qst_lqs_id_seq")
@SequenceGenerator(name = "lquest_sc.mst_qst_question_qst_lqs_id_seq", sequenceName = "lquest_sc.mst_qst_question_qst_lqs_id_seq")
@Column(name = "qst_lqs_id")
private int id;
@Column(name = "qst_title")
private String title;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "question")
@OrderBy("order asc")
private Set<Answer> answers = new HashSet<Answer>();
//getters and setters here
控制器中的呼叫是:
@RequestMapping(value = "/questionId/{id}", method = RequestMethod.GET)
public List<Answer> listAll( @PathVariable("id") int id ){
List<Answer> answers = answerRepository.findByEnabledAndQuestionIdOrderByOrderAsc(1,id);
return answers;
}
并且存储库是
public interface AnswerRepository extends JpaRepository<Answer, Long> {
List<Answer> findByEnabledAndQuestionIdOrderByOrderAsc(int enabled,int questionId);
}
问题是在控制器中,当我尝试评估时
answers.get(0).getQuestion()
,我收到了问题的实体,其中的属性填充了null
值和错误Method threw 'org.hibernate.LazyInitializationException' exception. Cannot evaluate Question_$$_jvst5b6_1.toString()
。我做错了什么?
答案 0 :(得分:1)
我不知道为什么spring.jpa.open-in-view = true
在您的情况下不起作用。当您评估OpenEntityManagerInViewInterceptor
时,可能Question
没有被触发或者线程已经离开。或者您有一个不支持它的旧版本。
延迟加载仅适用于事务内部。解决方案可能是 -
正如@Pradeep已经给你提示 - 在业务逻辑类中使用@Tranactional
。
即使您将@Transactional
放入存储库中也无效,因为您必须将注释放在您尝试评估answers.get(0).getQuestion()
的方法的顶部。
此外,我建议您不要直接从控制器调用存储库,而是使用服务层,在那里放置业务逻辑。
这只是一个示例实现,向您展示如何构建应用程序以及重要的关键字。另请注意,您可以使用@Inject
或@Autowired
。实现逻辑后,只需将服务注入控制器并在那里使用即可。
AnswerService.java
public interface AnswerService {
List<Answer> findByEnabledAndQuestionIdOrderByOrderAsc(int enabled, Long id);
}
AnswerServiceImpl.java
@Service
public class AnswerServiceImpl implements AnswerService {
private AnswerRepository answerRepository;
@Inject
public AnswerServiceImpl(AnswerRepository answerRepository) {
this.answerRepository = answerRepository;
}
@Transactional
@Override
public List<Answer> findByEnabledAndQuestionIdOrderByOrderAsc(int enabled, Long id) {
List<Answer> answerList = findByEnabledAndQuestionIdOrderByOrderAsc(int enabled,int questionId);
// do your lazy loading here
// because you are still in the same transactional context
// return the list
return answerList;
}
}