Java org.hibernate.LazyInitializationException:无法初始化代理-无会话,encore un fois

Java org.hibernate.LazyInitializationException:无法初始化代理-无会话,encore un fois,java,spring,hibernate,Java,Spring,Hibernate,Foo looks中包含以下内容: @ManyToMany private Set<User> favouritedBy; manytomy中的默认值是LAZY,而的hibernate文档清楚地将这种访问称为错误。您只能在会话仍处于打开状态时与延迟关联的对象进行交互。文档的这一部分还提供了访问对象的此类延迟关联成员的替代方法。在我们的应用程序中,我们更愿意在所使用的条件中将获取模式指定为JOIN 编辑: Set<Foo> favourites = user.getFav

Foo looks中包含以下内容:

@ManyToMany
private Set<User> favouritedBy;
manytomy
中的默认值是
LAZY
,而的hibernate文档清楚地将这种访问称为错误。您只能在会话仍处于打开状态时与延迟关联的对象进行交互。文档的这一部分还提供了访问对象的此类延迟关联成员的替代方法。在我们的应用程序中,我们更愿意在所使用的条件中将获取模式指定为
JOIN

编辑

Set<Foo> favourites = user.getFavourites();
Set favorites=user.getfavorites();
上面的语句实际上并没有返回包含所有
Foo
对象的集合。它只是一个代理。实际的
Foo
对象只有在访问集合中的元素(如
favorites.iterator()
等)时才会被提取,此操作显然发生在
getFavorites()方法之外。但是
getFavorites()
方法上的
@Transactional
注释表明会话将在该方法结束时关闭

因此,当对收藏夹集调用方法时,会话已经关闭,因此出现异常


为了解决这个问题,您应该使用Criteria对象来检索用户,并将获取类型指定为
JOIN
,以便在返回的用户对象中填充Foo对象。

是,应该在事务上下文中访问对象,否则操作将抛出一个
lazyiinitializationexception

有两种解决方案

  • 不要使用延迟加载

    在XML中设置
    lazy=false
    ,或者在注释中设置
    @OneToMany(fetch=FetchType.EAGER)

  • 使用延迟加载

    在XML中设置
    lazy=true
    ,或在注释中设置
    @OneToMany(fetch=FetchType.lazy)

    并在
    web.xml

     <listener>
         ...
     </listener>
     <filter>
         <filter-name>hibernateFilter</filter-name>
         <filter-class>
             org.springframework.orm.hibernate4.support.OpenSessionInViewFilter
         </filter-class>
         <init-param>
             <param-name>sessionFactoryBeanName</param-name>
             <param-value>mySessionFactory</param-value> 
         </init-param>
     </filter>
     <filter-mapping>
         <filter-name>hibernateFilter</filter-name>
         <url-pattern>/*</url-pattern>
     </filter-mapping>
     <servlet>
         ...
     </servlet>
    
    
    ...
    冬眠过滤器
    org.springframework.orm.hibernate4.support.OpenSessionInViewFilter
    sessionFactoryBeanName
    mySessionFactory
    冬眠过滤器
    /*
    ...
    

  • mySessionFactory
    是您在
    applicationContext.xml

    中定义的sessionFacory bean名称,如果您使用了@…中的任何一个。。。关系以及获取类型“Lazy”
     <listener>
         ...
     </listener>
     <filter>
         <filter-name>hibernateFilter</filter-name>
         <filter-class>
             org.springframework.orm.hibernate4.support.OpenSessionInViewFilter
         </filter-class>
         <init-param>
             <param-name>sessionFactoryBeanName</param-name>
             <param-value>mySessionFactory</param-value> 
         </init-param>
     </filter>
     <filter-mapping>
         <filter-name>hibernateFilter</filter-name>
         <url-pattern>/*</url-pattern>
     </filter-mapping>
     <servlet>
         ...
     </servlet>
    
    而且你会得到LazyInitializationException- 这意味着你关掉了OpenInView,这很好

    要避免两者懒散初始化异常 以及打开OIV(这使得Hibernate会话打开的时间比大多数情况下需要的时间更长)- 确保在发布列上指定了@Fetch(FetchMode.JOIN)。

    例如: 之前:

    @ManyToMany(fetch=FetchType.LAZY)
    私人设置桶;
    
    之后:

    @Fetch(FetchMode.JOIN)
    @ManyToMany(fetch = FetchType.LAZY)
    private Set<Kek> keks;
    
    @Fetch(FetchMode.JOIN)
    @ManyToMany(fetch=FetchType.LAZY)
    私人设置桶;
    

    通过这种方式,您将强制连接获取类型,该类型将(非常简单地说)提供正确的查询,并连接所需的链接实体,不强制您使用即时获取。

    您确定您在spring上下文中设置了
    transactionManager
    并定义了
    tx:annotation-driven
    吗?是的,其他地方一切正常……您能在此处发布堆栈跟踪吗?我们将检查是否存在事务处理代码是的,我认为会话仍然处于打开状态,尽管这是问题所在,因为该方法是事务性的,并且使用已将会话注入其中的dao。当您的延迟关联集被复制以供调用
    getFavorites()
    方法的调用方使用时,会话将已关闭,因为事务的范围在
    getFavorites()
    方法的末尾结束。我一点也不明白。“事务的作用域在getFavorites()的结尾处结束”这就是我希望它结束的时候,我调用了user.getFavorities。会话打开时,它将从db加载数据并填充哈希集?(显然不是,我错了,我有时希望我从来没有为hibernate烦恼过)请看我试图解释到底发生了什么的更新。我可以只做“Set favorites=new HashSet(user.getfavorites());”这篇文章讨论了这些建议的解决方案:OpenInView是一个糟糕的解决方案,在其他任何可用的解决方案之前都是第一个。在这个反模式出现之前,我们应该使用更多的方法来解决这个问题
    Set<Foo> favourites = user.getFavourites();
    
     <listener>
         ...
     </listener>
     <filter>
         <filter-name>hibernateFilter</filter-name>
         <filter-class>
             org.springframework.orm.hibernate4.support.OpenSessionInViewFilter
         </filter-class>
         <init-param>
             <param-name>sessionFactoryBeanName</param-name>
             <param-value>mySessionFactory</param-value> 
         </init-param>
     </filter>
     <filter-mapping>
         <filter-name>hibernateFilter</filter-name>
         <url-pattern>/*</url-pattern>
     </filter-mapping>
     <servlet>
         ...
     </servlet>
    
    @ManyToMany(fetch = FetchType.LAZY)
    private Set<Kek> keks;
    
    @Fetch(FetchMode.JOIN)
    @ManyToMany(fetch = FetchType.LAZY)
    private Set<Kek> keks;