Spring Hibernate的lazyinitializationexception异常
我在项目中使用数据库中实体的延迟初始化。作为JPA实现,我使用Hibernate。但当我需要在自定义JSP上获取实体集合时,我会得到一个lazyinitializationexception,因为Hibernate会话已经关闭。请告诉我是否有可能在不使用特殊请求的情况下防止此异常,如中所述。以下是我的一些代码:Spring Hibernate的lazyinitializationexception异常,spring,hibernate,Spring,Hibernate,我在项目中使用数据库中实体的延迟初始化。作为JPA实现,我使用Hibernate。但当我需要在自定义JSP上获取实体集合时,我会得到一个lazyinitializationexception,因为Hibernate会话已经关闭。请告诉我是否有可能在不使用特殊请求的情况下防止此异常,如中所述。以下是我的一些代码: @Entity public class Statistic extends EntityAbstract { private static final long serial
@Entity
public class Statistic extends EntityAbstract {
private static final long serialVersionUID = -6372957177860305322L;
@Temporal(TemporalType.TIMESTAMP)
private Date date;
private boolean correct;
@ManyToOne(fetch = FetchType.LAZY, cascade = {MERGE, PERSIST, REFRESH, DETACH})
@JoinColumn(name = "questionId", nullable = false)
private Question question;
@ManyToOne(fetch = FetchType.LAZY, cascade = {MERGE, PERSIST, REFRESH, DETACH})
@JoinColumn(name = "userId", nullable = false)
private User user;
public Statistic() {
}
public Statistic(Date date, boolean correct, Question question, User user) {
this.date = date;
this.correct = correct;
this.question = question;
this.user = user;
}
getter... setter...
}
@Entity
public class Question extends EntityAbstract {
private static final long serialVersionUID = -2751224412459986012L;
private String description;
@ManyToOne(fetch = FetchType.LAZY, cascade = {MERGE, PERSIST, REFRESH, DETACH})
@JoinColumn(name = "testId", nullable = false)
private Test test;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "question")
@OnDelete(action = OnDeleteAction.CASCADE)
private Set<Answer> answers;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "question")
@OnDelete(action = OnDeleteAction.CASCADE)
private Set<Literature> literature;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "question")
@OnDelete(action = OnDeleteAction.CASCADE)
private Set<Statistic> statistics;
public Question() {
}
public Question(String description, Test test) {
this.description = description;
this.test = test;
}
getter... setter...
}
@Entity
public class Literature extends EntityAbstract {
private static final long serialVersionUID = 218407080623072886L;
private String description;
@ManyToOne(fetch = FetchType.LAZY, cascade = {MERGE, PERSIST, REFRESH, DETACH})
@JoinColumn(name = "questionId", nullable = false)
private Question question;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "literature")
@OnDelete(action = OnDeleteAction.CASCADE)
private Set<Link> links;
public Literature() {
}
public Literature(String description, Question question) {
this.description = description;
this.question = question;
}
getter... setter...
}
@Entity
public class Link extends EntityAbstract {
private static final long serialVersionUID = 6494218299043499655L;
private String link;
@ManyToOne(fetch = FetchType.LAZY, cascade = {MERGE, PERSIST, REFRESH, DETACH})
@JoinColumn(name = "literatureId", nullable = false)
private Literature literature;
public Link() {
}
public Link(String link, Literature literature) {
this.link = link;
this.literature = literature;
}
getter... setter...
}
And I need to get a collection of questions from statistics and further along the chain. I use this service:
@Repository
@Transactional
public interface CrudRepository<T extends EntityAbstract> {
SessionFactory getBeanToBeAutowired();
// create
@SuppressWarnings("unchecked")
default T add(T entity){
return (T) getBeanToBeAutowired().getCurrentSession().merge(entity);
}
// read
@SuppressWarnings("unchecked")
default T getById(Class<T> entityClass, long id){
return (T)getBeanToBeAutowired().getCurrentSession().find(entityClass, id);
}
// update
@SuppressWarnings("unchecked")
default T update(T entity){
return (T) getBeanToBeAutowired().getCurrentSession().merge(entity);
}
// delete
default void delete(T entity){
getBeanToBeAutowired().getCurrentSession().remove(entity);
}
@SuppressWarnings("unchecked")
default List<T> getAll(Class<T> t){
return (List<T>)getBeanToBeAutowired()
.getCurrentSession()
.createQuery("FROM " + t.getSimpleName())
.list();
}
}
public interface StatisticRepository extends CrudRepository<Statistic> {
}
public interface StatisticService extends StatisticRepository {
Statistic getById(long id);
List<Statistic> getAll();
}
@Service("statisticService")
public class StatisticServiceImpl implements StatisticService {
private SessionFactory sessionFactory;
@Autowired
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
@Override
public SessionFactory getBeanToBeAutowired() {
return sessionFactory;
}
@Override
public Statistic getById(long id) {
return getById(Statistic.class, id);
}
@Override
public List<Statistic> getAll() {
return getAll(Statistic.class);
}
}
@实体
公共类统计扩展了EntityAbstract{
私有静态最终长serialVersionUID=-6372957177860305322L;
@时态(TemporalType.TIMESTAMP)
私人日期;
私有布尔正确;
@manytone(fetch=FetchType.LAZY,cascade={MERGE,PERSIST,REFRESH,DETACH})
@JoinColumn(name=“questionId”,null=false)
私人问题;
@manytone(fetch=FetchType.LAZY,cascade={MERGE,PERSIST,REFRESH,DETACH})
@JoinColumn(name=“userId”,nullable=false)
私人用户;
公共统计(){
}
公共统计(日期、布尔值正确、问题、用户){
this.date=日期;
this.correct=正确;
这个问题=问题;
this.user=用户;
}
盖特…塞特。。。
}
@实体
公共类问题扩展实体抽象{
私有静态最终长serialVersionUID=-2751224412459986012L;
私有字符串描述;
@manytone(fetch=FetchType.LAZY,cascade={MERGE,PERSIST,REFRESH,DETACH})
@JoinColumn(name=“testId”,nullable=false)
私人测试;
@OneToMany(fetch=FetchType.LAZY,mappedBy=“question”)
@OnDelete(action=OnDeleteAction.CASCADE)
私人设定答案;
@OneToMany(fetch=FetchType.LAZY,mappedBy=“question”)
@OnDelete(action=OnDeleteAction.CASCADE)
私家文学;
@OneToMany(fetch=FetchType.LAZY,mappedBy=“question”)
@OnDelete(action=OnDeleteAction.CASCADE)
私有集统计;
公众问题({
}
公开问题(字符串描述、测试){
this.description=描述;
这个。测试=测试;
}
盖特…塞特。。。
}
@实体
公共类文献扩展了实体抽象{
私有静态最终长serialVersionUID=218407080623072886;
私有字符串描述;
@manytone(fetch=FetchType.LAZY,cascade={MERGE,PERSIST,REFRESH,DETACH})
@JoinColumn(name=“questionId”,null=false)
私人问题;
@OneToMany(fetch=FetchType.LAZY,mappedBy=“文学”)
@OnDelete(action=OnDeleteAction.CASCADE)
专用集链接;
公共文学(){
}
公共文献(字符串描述、问题){
this.description=描述;
这个问题=问题;
}
盖特…塞特。。。
}
@实体
公共类链接扩展了EntityAbstract{
私有静态最终长serialVersionUID=649421829904349655L;
私有字符串链接;
@manytone(fetch=FetchType.LAZY,cascade={MERGE,PERSIST,REFRESH,DETACH})
@JoinColumn(name=“literatureId”,nullable=false)
私人文学;
公共链接(){
}
公共链接(字符串链接、文献){
this.link=link;
文学=文学;
}
盖特…塞特。。。
}
我需要从统计数据中收集问题,并进一步沿着这条链。我使用这项服务:
@存储库
@交易的
公共接口存储{
SessionFactory GetBeantobauToWired();
//创造
@抑制警告(“未选中”)
默认T添加(T实体){
返回(T)getBeantobautowired().getCurrentSession().merge(实体);
}
//阅读
@抑制警告(“未选中”)
默认T getById(类entityClass,长id){
返回(T)getBeantobautowired().getCurrentSession().find(entityClass,id);
}
//更新
@抑制警告(“未选中”)
默认T更新(T实体){
返回(T)getBeantobautowired().getCurrentSession().merge(实体);
}
//删除
默认无效删除(T实体){
GetBeanToBeautWired().getCurrentSession().remove(实体);
}
@抑制警告(“未选中”)
默认列表getAll(t类){
return(List)getbeantobautowired()
.getCurrentSession()
.createQuery(“来自”+t.getSimpleName())
.list();
}
}
公共接口StatisticRepository扩展了Crudepository{
}
公共接口StatisticService扩展了StatisticRepository{
统计getById(长id);
List getAll();
}
@服务(“统计服务”)
公共类StatisticServiceImpl实现StatisticService{
私人会话工厂会话工厂;
@自动连线
public void setSessionFactory(SessionFactory SessionFactory){
this.sessionFactory=sessionFactory;
}
@凌驾
public SessionFactory getBeantobautowired(){
返回工厂;
}
@凌驾
公共统计getById(长id){
返回getById(Statistic.class,id);
}
@凌驾
公共列表getAll(){
返回getAll(Statistic.class);
}
}
我解决了以下问题(在这里使用本文):
@NamedEntityGraph(
name=“graph.statistic”,
attributeNodes=@NamedAttributeNode(value=“question”,subgraph=“questionGraph”),
子图={
@NamedSubgraph(name=“questionGraph”,
attributeNodes=@NamedAttributeNode(value=“文学”,subgraph=“文学图形”),
@NamedSubgraph(name=“文学图形”,
attributeNodes=@NamedAttributeNode(value=“links”)}
)
@实体
公共类统计扩展了EntityAbstract{
私有静态最终长serialVersionUID=-6372957177860305322L;
@时态(TemporalType.TIMESTAMP)
私人日期;
私有布尔正确;
@manytone(fetch=FetchType.LAZY,ca
@NamedEntityGraph(
name = "graph.statistic",
attributeNodes = @NamedAttributeNode(value = "question", subgraph = "questionGraph"),
subgraphs = {
@NamedSubgraph(name = "questionGraph",
attributeNodes = @NamedAttributeNode(value = "literature", subgraph = "literatureGraph")),
@NamedSubgraph(name = "literatureGraph",
attributeNodes = @NamedAttributeNode(value = "links"))}
)
@Entity
public class Statistic extends EntityAbstract {
private static final long serialVersionUID = -6372957177860305322L;
@Temporal(TemporalType.TIMESTAMP)
private Date date;
private boolean correct;
@ManyToOne(fetch = FetchType.LAZY, cascade = {MERGE, PERSIST, REFRESH, DETACH})
@JoinColumn(name = "questionId", nullable = false)
private Question question;
@ManyToOne(fetch = FetchType.LAZY, cascade = {MERGE, PERSIST, REFRESH, DETACH})
@JoinColumn(name = "userId", nullable = false)
private User user;
public Statistic() {
}
public Statistic(Date date, boolean correct, Question question, User user) {
this.date = date;
this.correct = correct;
this.question = question;
this.user = user;
}
getters... and setters.....
}
@Service("statisticService")
public class StatisticServiceImpl implements StatisticService {
...
@Override
@Transactional
public List<Statistic> getUserStatisticByUserIdAndDate(long id, Date startDate, Date endDate) {
Session session = sessionFactory.openSession();
session.beginTransaction();
RootGraph<?> graph = session.getEntityGraph("graph.statistic");
List<Statistic> statistics = session
.createQuery("FROM Statistic WHERE user.id = :id AND date between :startDate AND :endDate", Statistic.class)
.setParameter("id", id)
.setParameter("startDate", startDate)
.setParameter("endDate", endDate)
.setHint("javax.persistence.fetchgraph", graph)
.getResultList();
session.getTransaction().commit();
session.close();
return statistics;
}