如何解决“未能懒散地初始化角色集合”的Hibernate异常

时间:2022-12-21 17:24:45

I have this problem:

我有这个问题:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: mvc3.model.Topic.comments, no session or session was closed

org.hibernate.LazyInitializationException:无法懒惰地初始化角色集合:mvc3.model.Topic.comments,没有会话或会话被关闭

Here is the model:

这是模型:

@Entity
@Table(name = "T_TOPIC")
public class Topic {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private int id;

    @ManyToOne
    @JoinColumn(name="USER_ID")
    private User author;

    @Enumerated(EnumType.STRING)    
    private Tag topicTag;

    private String name;
    private String text;

    @OneToMany(mappedBy = "topic", cascade = CascadeType.ALL)
    private Collection<Comment> comments = new LinkedHashSet<Comment>();

    ...

    public Collection<Comment> getComments() {
           return comments;
    }

}

The controller, which calls model looks like the following:

调用模型的控制器如下所示:

@Controller
@RequestMapping(value = "/topic")
public class TopicController {

    @Autowired
    private TopicService service;

    private static final Logger logger = LoggerFactory.getLogger(TopicController.class);


    @RequestMapping(value = "/details/{topicId}", method = RequestMethod.GET)
    public ModelAndView details(@PathVariable(value="topicId") int id)
    {

            Topic topicById = service.findTopicByID(id);
            Collection<Comment> commentList = topicById.getComments();

            Hashtable modelData = new Hashtable();
            modelData.put("topic", topicById);
            modelData.put("commentList", commentList);

            return new ModelAndView("/topic/details", modelData);

     }

}

The jsp-page looks li the following:

jsp页面看起来如下:

<%@page import="com.epam.mvc3.helpers.Utils"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
      <title>View Topic</title>
</head>
<body>

<ul>
<c:forEach items="${commentList}" var="item">
<jsp:useBean id="item" type="mvc3.model.Comment"/>
<li>${item.getText()}</li>

</c:forEach>
</ul>
</body>
</html>

Exception is rised, when viewing jsp. In the line with c:forEach loop

查看jsp时会出现例外情况。在c:forEach循环的行中

21 个解决方案

#1


149  

If you know that you'll want to see all Comments every time you retrieve a Topic then change your field mapping for comments to:

如果您知道每次检索主题时都要查看所有注释,请将注释的字段映射更改为:

@OneToMany(fetch = FetchType.EAGER, mappedBy = "topic", cascade = CascadeType.ALL)
private Collection<Comment> comments = new LinkedHashSet<Comment>();

Collections are lazy-loaded by default, take a look at this if you want to know more.

默认情况下,集合是延迟加载的,如果您想了解更多,请查看此处。

#2


127  

From my experience, I have the following methods to solved the famous LazyInitializationException:

根据我的经验,我有以下方法来解决着名的LazyInitializationException:

(1) Use Hibernate.initialize

(1)使用Hibernate.initialize

Hibernate.initialize(topics.getComments());

(2) Use JOIN FETCH

(2)使用JOIN FETCH

You can use the JOIN FETCH syntax in your JPQL to explicitly fetch the child collection out. This is some how like EAGER fetching.

您可以在JPQL中使用JOIN FETCH语法显式获取子集合。这有点像EAGER的提取方式。

(3) Use OpenSessionInViewFilter

(3)使用OpenSessionInViewFilter

LazyInitializationException often occur in view layer. If you use Spring framework, you can use OpenSessionInViewFilter. However, I do not suggest you to do so. It may leads to performance issue if not use correctly.

LazyInitializationException经常出现在视图层中。如果使用Spring框架,则可以使用OpenSessionInViewFilter。但是,我不建议你这样做。如果不正确使用,可能会导致性能问题。

#3


37  

The origin of your problem:

By default hibernate lazily loads the collections (relationships) which means whenver you use the collection in your code(here comments field in Topic class) the hibernate gets that from database, now the problem is that you are getting the collection in your controller (where the JPA session is closed).This is the line of code that causes the exception (where you are loading the comments collection):

默认情况下,hibernate懒洋洋地加载集合(关系),这意味着当你在代码中使用集合时(这里是Topic类中的注释字段),hibernate从数据库中获取,现在问题是你在控制器中获取集合(其中JPA会话已关闭。。这是导致异常的代码行(您正在加载comments集合):

    Collection<Comment> commentList = topicById.getComments();

You are getting "comments" collection (topic.getComments()) in your controller(where JPA session has ended) and that causes the exception. Also if you had got the comments collection in your jsp file like this(instead of getting it in your controller):

您正在控制器中获取“comments”集合(topic.getComments())(JPA会话已结束)并导致异常。此外,如果你在你的jsp文件中有这样的评论集合(而不是在你的控制器中获取它):

<c:forEach items="topic.comments" var="item">
//some code
</c:forEach>

You would still have the same exception for the same reason.

出于同样的原因,你仍会有相同的例外。

Solving the problem:

Because you just can have only two collections with the FetchType.Eager(eagerly fetched collection) in an Entity class and because lazy loading is more efficient than eagerly loading, I think this way of solving your problem is better than just changing the FetchType to eager:

因为你只能在Entity类中只有两个带有FetchType.Eager(eagerly fetched collection)的集合,并且因为延迟加载比急切加载更有效,我认为这种解决问题的方法比仅仅将FetchType更改为eager更好:

If you want to have collection lazy initialized, and also make this work, it is better to add this snippet of code to your web.xml :

如果您想要初始化集合延迟,并且还要使其工作,最好将这段代码添加到您的web.xml:

<filter>
    <filter-name>SpringOpenEntityManagerInViewFilter</filter-name>
    <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>SpringOpenEntityManagerInViewFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

What this code does is that it will increase the length of your JPA session or as the documentation says, it is used "to allow for lazy loading in web views despite the original transactions already being completed." so this way the JPA session will be open a bit longer and because of that you can lazily load collections in your jsp files and controller classes.

这段代码的作用是它会增加JPA会话的长度,或者正如文档所说,它用于“允许在Web视图中进行延迟加载,尽管原始事务已经完成”。所以这样JPA会话会打开一点时间,因此你可以在jsp文件和控制器类中懒洋洋地加载集合。

#4


25  

I know it's an old question but I want to help. You can put the transactional annotation on the service method you need, in this case findTopicByID(id) should have

我知道这是一个老问题,但我想提供帮助。您可以将事务注释放在所需的服务方法上,在这种情况下,findTopicByID(id)应该具有

@Transactional(propagation=Propagation.REQUIRED, readOnly=true, noRollbackFor=Exception.class)

more info about this annotation can be found here

有关此注释的更多信息可以在这里找到

About the other solutions:

关于其他解决方案:

fetch = FetchType.EAGER 

is not a good practice, it should be used ONLY if necessary.

这不是一个好习惯,只有在必要时才应该使用它。

Hibernate.initialize(topics.getComments());

The hibernate initializer binds your classes to the hibernate technology. If you are aiming to be flexible is not a good way to go.

hibernate初始化程序将您的类绑定到hibernate技术。如果你的目标是灵活不是一个好的方法。

Hope it helps

希望能帮助到你

#5


24  

The reason is that when you use lazy load, the session is closed.

原因是当您使用延迟加载时,会话将关闭。

There are two solutions.

有两种解决方案。

  1. Don't use lazy load.

    不要使用延迟加载。

    Set lazy=false in XML or Set @OneToMany(fetch = FetchType.EAGER) In annotation.

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

  2. Use lazy load.

    使用延迟加载。

    Set lazy=true in XML or Set @OneToMany(fetch = FetchType.LAZY) In annotation.

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

    and add OpenSessionInViewFilter filter in your web.xml

    并在web.xml中添加OpenSessionInViewFilter过滤器

Detail See my POST.

细节见我的帖子。

#6


17  

In order to lazy load a collection there must be an active session. In a web app there are two ways to do this. You can use the Open Session In View pattern, where you use an interceptor to open the session at the beginning of the request and close it at the end. The risk there is that you have to have solid exception handling or you could bind up all your sessions and your app could hang.

为了延迟加载集合,必须有一个活动的会话。在Web应用程序中,有两种方法可以执行此操作。您可以使用Open Session In View模式,您可以使用拦截器在请求开始时打开会话,并在结束时关闭它。存在这样的风险:您必须具有可靠的异常处理,或者您可以绑定所有会话,并且您的应用可能会挂起。

The other way to handle this is to collect all the data you need in your controller, close your session, and then stuff the data into your model. I personally prefer this approach, as it seems a little closer to the spirit of the MVC pattern. Also if you get an error from the database this way you can handle it a lot better than if it happens in your view renderer. Your friend in this scenario is Hibernate.initialize(myTopic.getComments()). You will also have to reattach the object to the session, since you're creating a new transaction with every request. Use session.lock(myTopic,LockMode.NONE) for that.

处理此问题的另一种方法是收集控制器中所需的所有数据,关闭会话,然后将数据填充到模型中。我个人更喜欢这种方法,因为它似乎更接近MVC模式的精神。此外,如果您从数据库中收到错误,则可以比在视图渲染器中更好地处理它。在这种情况下你的朋友是Hibernate.initialize(myTopic.getComments())。您还必须将对象重新附加到会话,因为您正在为每个请求创建一个新事务。使用session.lock(myTopic,LockMode.NONE)。

#7


11  

The problem is caused by accessing an attribute with the hibernate session closed. You have not a hibernate transaction in the controller.

该问题是由关闭hibernate会话访问属性引起的。您没有控制器中的休眠事务。

Possible solutions:

可能的解决方案:

  1. Do all this logic, in the service layer, (with the @Transactional), not in the controller. There should be the right place to do this, it is part of the logic of the app, not in the controller (in this case, an interface to load the model). All the operations in the service layer should be transactional. i.e.: Move this line to the TopicService.findTopicByID method:

    在服务层中(使用@Transactional)执行所有这些逻辑,而不是在控制器中。应该有合适的位置,它是应用程序逻辑的一部分,而不是控制器(在这种情况下,是加载模型的接口)。服务层中的所有操作都应该是事务性的。即:将此行移至TopicService.findTopicByID方法:

    Collection commentList = topicById.getComments();

    集合commentList = topicById.getComments();

  2. Use 'eager' instead of 'lazy'. Now you are not using 'lazy' .. it is not a real solution, if you want to use lazy, works like a temporary (very temporary) workaround.

    使用'渴望'而不是'懒惰'。现在你没有使用'懒惰'..它不是一个真正的解决方案,如果你想使用懒惰,就像一个临时(非常临时)的解决方法。

  3. use @Transactional in the Controller. It should not be used here, you are mixing service layer with presentation, it is not a good design.
  4. 在Controller中使用@Transactional。它不应该在这里使用,你将服务层与表示混合,它不是一个好的设计。
  5. use OpenSessionInViewFilter, many disadvantages reported, possible instability.
  6. 使用OpenSessionInViewFilter,报告了许多缺点,可能不稳定。

In general, the best solution is the 1.

一般来说,最好的解决方案是1。

#8


9  

I found out that declaring @PersistenceContext as EXTENDED also solves this problem:

我发现将@PersistenceContext声明为EXTENDED也解决了这个问题:

@PersistenceContext(type = PersistenceContextType.EXTENDED)

#9


9  

@Controller
@RequestMapping(value = "/topic")
@Transactional

i solve this problem by adding @Transactional,i think this can make session open

我通过添加@Transactional来解决这个问题,我认为这可以使会话打开

#10


7  

If you are trying to have a relation between a entity and a Collection or a List of java objects (for example Long type), it would like something like this:

如果您尝试在实体和Collection或Java对象列表之间建立关系(例如Long类型),它会像这样:

@ElementCollection(fetch = FetchType.EAGER)
    public List<Long> ids;

#11


5  

it was the problem i recently faced which i solved with using

这是我最近遇到的问题,我用它解决了

<f:attribute name="collectionType" value="java.util.ArrayList" />

more detailed decription here and this saved my day.

更详细的解释在这里,这节省了我的一天。

#12


5  

@Transactional annotation on controller is missing

控制器上的@Transactional注释缺失

@Controller
@RequestMapping("/")
@Transactional
public class UserController {
}

#13


5  

your list is lazy loading, so the list wasn't loaded. call to get on the list is not enough. use in Hibernate.initialize in order to init the list. If dosnt work run on the list element and call Hibernate.initialize for each . this need to be before you return from the transaction scope. look at this post.
search for -

您的列表是延迟加载,因此列表未加载。打电话到列表是不够的。在Hibernate.initialize中使用以初始化列表。如果dosnt工作在list元素上运行并为每个元素调用Hibernate.initialize。这需要在从事务范围返回之前。看看这篇文章。搜索 -

Node n = // .. get the node
Hibernate.initialize(n); // initializes 'parent' similar to getParent.
Hibernate.initialize(n.getChildren()); // pass the lazy collection into the session 

#14


4  

To solve the problem in my case it was just missing this line

为了解决我的问题,它只是错过了这一行

<tx:annotation-driven transaction-manager="myTxManager" />

in the application-context file.

在应用程序上下文文件中。

The @Transactional annotation over a method was not taken into account.

未考虑方法上的@Transactional注释。

Hope the answer will help someone

希望答案会对某人有所帮助

#15


2  

For those working with Criteria, I found that

对于那些与Criteria合作的人,我发现了这一点

criteria.setFetchMode("lazily_fetched_member", FetchMode.EAGER);

did everything I needed had done.

做了我需要做的一切。

Initial fetch mode for collections is set to FetchMode.LAZY to provide performance, but when I need the data, I just add that line and enjoy the fully populated objects.

集合的初始提取模式设置为FetchMode.LAZY以提供性能,但是当我需要数据时,我只需添加该行并享受完全填充的对象。

#16


2  

In my case following code was a problem:

在我的情况下,代码是一个问题:

entityManager.detach(topicById);
topicById.getComments() // exception thrown

Because it detached from the database and Hibernate no longer retrieved list from the field when it was needed. So I initialize it before detaching:

因为它与数据库分离,并且Hibernate在需要时不再从字段中检索列表。所以我在分离之前初始化它:

Hibernate.initialize(topicById.getComments());
entityManager.detach(topicById);
topicById.getComments() // works like a charm

#17


2  

As I explained in this article, the best way to handle the LazyInitializationException is to fetch it upon query time, like this:

正如我在本文中解释的那样,处理LazyInitializationException的最佳方法是在查询时获取它,如下所示:

select t
from Topic t
left join fetch t.comments

You should ALWAYS avoid the following anti-patterns:

你应该总是避免以下反模式:

Therefore, make sure that your FetchType.LAZY associations are initialized at query time or within the original @Transactional scope using Hibernate.initialize for secondary collections.

因此,请确保在查询时或在原始@Transactional范围内使用Hibernate.initialize为初级集合初始化FetchType.LAZY关联。

#18


0  

The reason is you are trying to get the commentList on your controller after closing the session inside the service.

原因是您在关闭服务中的会话后尝试在控制器上获取commentList。

topicById.getComments();

Above will load the commentList only if your hibernate session is active, which I guess you closed in your service.

只有当您的休眠会话处于活动状态时,上面才会加载commentList,我想您已在服务中关闭了。

So, you have to get the commentList before closing the session.

因此,您必须在关闭会话之前获取commentList。

#19


0  

In my cae, I had the mapping b/w A and B like

在我的cae中,我有映射b / w A和B之类的

A has

A有

@OneToMany(mappedBy = "a", cascade = CascadeType.ALL)
Set<B> bs;

in the DAO layer, the method needs to be annotated with @Transactional if you haven't annotated the mapping with Fetch Type - Eager

在DAO层中,如果没有使用Fetch Type注释映射,则需要使用@Transactional注释该方法 - Eager

#20


-1  

add this to your persistence.xml

将其添加到persistence.xml中

<property name="hibernate.enable_lazy_load_no_trans" value="true" />

#21


-7  

i resolved using List instead of Set:

我解决使用List而不是Set:

private List<Categories> children = new ArrayList<Categories>();

#1


149  

If you know that you'll want to see all Comments every time you retrieve a Topic then change your field mapping for comments to:

如果您知道每次检索主题时都要查看所有注释,请将注释的字段映射更改为:

@OneToMany(fetch = FetchType.EAGER, mappedBy = "topic", cascade = CascadeType.ALL)
private Collection<Comment> comments = new LinkedHashSet<Comment>();

Collections are lazy-loaded by default, take a look at this if you want to know more.

默认情况下,集合是延迟加载的,如果您想了解更多,请查看此处。

#2


127  

From my experience, I have the following methods to solved the famous LazyInitializationException:

根据我的经验,我有以下方法来解决着名的LazyInitializationException:

(1) Use Hibernate.initialize

(1)使用Hibernate.initialize

Hibernate.initialize(topics.getComments());

(2) Use JOIN FETCH

(2)使用JOIN FETCH

You can use the JOIN FETCH syntax in your JPQL to explicitly fetch the child collection out. This is some how like EAGER fetching.

您可以在JPQL中使用JOIN FETCH语法显式获取子集合。这有点像EAGER的提取方式。

(3) Use OpenSessionInViewFilter

(3)使用OpenSessionInViewFilter

LazyInitializationException often occur in view layer. If you use Spring framework, you can use OpenSessionInViewFilter. However, I do not suggest you to do so. It may leads to performance issue if not use correctly.

LazyInitializationException经常出现在视图层中。如果使用Spring框架,则可以使用OpenSessionInViewFilter。但是,我不建议你这样做。如果不正确使用,可能会导致性能问题。

#3


37  

The origin of your problem:

By default hibernate lazily loads the collections (relationships) which means whenver you use the collection in your code(here comments field in Topic class) the hibernate gets that from database, now the problem is that you are getting the collection in your controller (where the JPA session is closed).This is the line of code that causes the exception (where you are loading the comments collection):

默认情况下,hibernate懒洋洋地加载集合(关系),这意味着当你在代码中使用集合时(这里是Topic类中的注释字段),hibernate从数据库中获取,现在问题是你在控制器中获取集合(其中JPA会话已关闭。。这是导致异常的代码行(您正在加载comments集合):

    Collection<Comment> commentList = topicById.getComments();

You are getting "comments" collection (topic.getComments()) in your controller(where JPA session has ended) and that causes the exception. Also if you had got the comments collection in your jsp file like this(instead of getting it in your controller):

您正在控制器中获取“comments”集合(topic.getComments())(JPA会话已结束)并导致异常。此外,如果你在你的jsp文件中有这样的评论集合(而不是在你的控制器中获取它):

<c:forEach items="topic.comments" var="item">
//some code
</c:forEach>

You would still have the same exception for the same reason.

出于同样的原因,你仍会有相同的例外。

Solving the problem:

Because you just can have only two collections with the FetchType.Eager(eagerly fetched collection) in an Entity class and because lazy loading is more efficient than eagerly loading, I think this way of solving your problem is better than just changing the FetchType to eager:

因为你只能在Entity类中只有两个带有FetchType.Eager(eagerly fetched collection)的集合,并且因为延迟加载比急切加载更有效,我认为这种解决问题的方法比仅仅将FetchType更改为eager更好:

If you want to have collection lazy initialized, and also make this work, it is better to add this snippet of code to your web.xml :

如果您想要初始化集合延迟,并且还要使其工作,最好将这段代码添加到您的web.xml:

<filter>
    <filter-name>SpringOpenEntityManagerInViewFilter</filter-name>
    <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>SpringOpenEntityManagerInViewFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

What this code does is that it will increase the length of your JPA session or as the documentation says, it is used "to allow for lazy loading in web views despite the original transactions already being completed." so this way the JPA session will be open a bit longer and because of that you can lazily load collections in your jsp files and controller classes.

这段代码的作用是它会增加JPA会话的长度,或者正如文档所说,它用于“允许在Web视图中进行延迟加载,尽管原始事务已经完成”。所以这样JPA会话会打开一点时间,因此你可以在jsp文件和控制器类中懒洋洋地加载集合。

#4


25  

I know it's an old question but I want to help. You can put the transactional annotation on the service method you need, in this case findTopicByID(id) should have

我知道这是一个老问题,但我想提供帮助。您可以将事务注释放在所需的服务方法上,在这种情况下,findTopicByID(id)应该具有

@Transactional(propagation=Propagation.REQUIRED, readOnly=true, noRollbackFor=Exception.class)

more info about this annotation can be found here

有关此注释的更多信息可以在这里找到

About the other solutions:

关于其他解决方案:

fetch = FetchType.EAGER 

is not a good practice, it should be used ONLY if necessary.

这不是一个好习惯,只有在必要时才应该使用它。

Hibernate.initialize(topics.getComments());

The hibernate initializer binds your classes to the hibernate technology. If you are aiming to be flexible is not a good way to go.

hibernate初始化程序将您的类绑定到hibernate技术。如果你的目标是灵活不是一个好的方法。

Hope it helps

希望能帮助到你

#5


24  

The reason is that when you use lazy load, the session is closed.

原因是当您使用延迟加载时,会话将关闭。

There are two solutions.

有两种解决方案。

  1. Don't use lazy load.

    不要使用延迟加载。

    Set lazy=false in XML or Set @OneToMany(fetch = FetchType.EAGER) In annotation.

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

  2. Use lazy load.

    使用延迟加载。

    Set lazy=true in XML or Set @OneToMany(fetch = FetchType.LAZY) In annotation.

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

    and add OpenSessionInViewFilter filter in your web.xml

    并在web.xml中添加OpenSessionInViewFilter过滤器

Detail See my POST.

细节见我的帖子。

#6


17  

In order to lazy load a collection there must be an active session. In a web app there are two ways to do this. You can use the Open Session In View pattern, where you use an interceptor to open the session at the beginning of the request and close it at the end. The risk there is that you have to have solid exception handling or you could bind up all your sessions and your app could hang.

为了延迟加载集合,必须有一个活动的会话。在Web应用程序中,有两种方法可以执行此操作。您可以使用Open Session In View模式,您可以使用拦截器在请求开始时打开会话,并在结束时关闭它。存在这样的风险:您必须具有可靠的异常处理,或者您可以绑定所有会话,并且您的应用可能会挂起。

The other way to handle this is to collect all the data you need in your controller, close your session, and then stuff the data into your model. I personally prefer this approach, as it seems a little closer to the spirit of the MVC pattern. Also if you get an error from the database this way you can handle it a lot better than if it happens in your view renderer. Your friend in this scenario is Hibernate.initialize(myTopic.getComments()). You will also have to reattach the object to the session, since you're creating a new transaction with every request. Use session.lock(myTopic,LockMode.NONE) for that.

处理此问题的另一种方法是收集控制器中所需的所有数据,关闭会话,然后将数据填充到模型中。我个人更喜欢这种方法,因为它似乎更接近MVC模式的精神。此外,如果您从数据库中收到错误,则可以比在视图渲染器中更好地处理它。在这种情况下你的朋友是Hibernate.initialize(myTopic.getComments())。您还必须将对象重新附加到会话,因为您正在为每个请求创建一个新事务。使用session.lock(myTopic,LockMode.NONE)。

#7


11  

The problem is caused by accessing an attribute with the hibernate session closed. You have not a hibernate transaction in the controller.

该问题是由关闭hibernate会话访问属性引起的。您没有控制器中的休眠事务。

Possible solutions:

可能的解决方案:

  1. Do all this logic, in the service layer, (with the @Transactional), not in the controller. There should be the right place to do this, it is part of the logic of the app, not in the controller (in this case, an interface to load the model). All the operations in the service layer should be transactional. i.e.: Move this line to the TopicService.findTopicByID method:

    在服务层中(使用@Transactional)执行所有这些逻辑,而不是在控制器中。应该有合适的位置,它是应用程序逻辑的一部分,而不是控制器(在这种情况下,是加载模型的接口)。服务层中的所有操作都应该是事务性的。即:将此行移至TopicService.findTopicByID方法:

    Collection commentList = topicById.getComments();

    集合commentList = topicById.getComments();

  2. Use 'eager' instead of 'lazy'. Now you are not using 'lazy' .. it is not a real solution, if you want to use lazy, works like a temporary (very temporary) workaround.

    使用'渴望'而不是'懒惰'。现在你没有使用'懒惰'..它不是一个真正的解决方案,如果你想使用懒惰,就像一个临时(非常临时)的解决方法。

  3. use @Transactional in the Controller. It should not be used here, you are mixing service layer with presentation, it is not a good design.
  4. 在Controller中使用@Transactional。它不应该在这里使用,你将服务层与表示混合,它不是一个好的设计。
  5. use OpenSessionInViewFilter, many disadvantages reported, possible instability.
  6. 使用OpenSessionInViewFilter,报告了许多缺点,可能不稳定。

In general, the best solution is the 1.

一般来说,最好的解决方案是1。

#8


9  

I found out that declaring @PersistenceContext as EXTENDED also solves this problem:

我发现将@PersistenceContext声明为EXTENDED也解决了这个问题:

@PersistenceContext(type = PersistenceContextType.EXTENDED)

#9


9  

@Controller
@RequestMapping(value = "/topic")
@Transactional

i solve this problem by adding @Transactional,i think this can make session open

我通过添加@Transactional来解决这个问题,我认为这可以使会话打开

#10


7  

If you are trying to have a relation between a entity and a Collection or a List of java objects (for example Long type), it would like something like this:

如果您尝试在实体和Collection或Java对象列表之间建立关系(例如Long类型),它会像这样:

@ElementCollection(fetch = FetchType.EAGER)
    public List<Long> ids;

#11


5  

it was the problem i recently faced which i solved with using

这是我最近遇到的问题,我用它解决了

<f:attribute name="collectionType" value="java.util.ArrayList" />

more detailed decription here and this saved my day.

更详细的解释在这里,这节省了我的一天。

#12


5  

@Transactional annotation on controller is missing

控制器上的@Transactional注释缺失

@Controller
@RequestMapping("/")
@Transactional
public class UserController {
}

#13


5  

your list is lazy loading, so the list wasn't loaded. call to get on the list is not enough. use in Hibernate.initialize in order to init the list. If dosnt work run on the list element and call Hibernate.initialize for each . this need to be before you return from the transaction scope. look at this post.
search for -

您的列表是延迟加载,因此列表未加载。打电话到列表是不够的。在Hibernate.initialize中使用以初始化列表。如果dosnt工作在list元素上运行并为每个元素调用Hibernate.initialize。这需要在从事务范围返回之前。看看这篇文章。搜索 -

Node n = // .. get the node
Hibernate.initialize(n); // initializes 'parent' similar to getParent.
Hibernate.initialize(n.getChildren()); // pass the lazy collection into the session 

#14


4  

To solve the problem in my case it was just missing this line

为了解决我的问题,它只是错过了这一行

<tx:annotation-driven transaction-manager="myTxManager" />

in the application-context file.

在应用程序上下文文件中。

The @Transactional annotation over a method was not taken into account.

未考虑方法上的@Transactional注释。

Hope the answer will help someone

希望答案会对某人有所帮助

#15


2  

For those working with Criteria, I found that

对于那些与Criteria合作的人,我发现了这一点

criteria.setFetchMode("lazily_fetched_member", FetchMode.EAGER);

did everything I needed had done.

做了我需要做的一切。

Initial fetch mode for collections is set to FetchMode.LAZY to provide performance, but when I need the data, I just add that line and enjoy the fully populated objects.

集合的初始提取模式设置为FetchMode.LAZY以提供性能,但是当我需要数据时,我只需添加该行并享受完全填充的对象。

#16


2  

In my case following code was a problem:

在我的情况下,代码是一个问题:

entityManager.detach(topicById);
topicById.getComments() // exception thrown

Because it detached from the database and Hibernate no longer retrieved list from the field when it was needed. So I initialize it before detaching:

因为它与数据库分离,并且Hibernate在需要时不再从字段中检索列表。所以我在分离之前初始化它:

Hibernate.initialize(topicById.getComments());
entityManager.detach(topicById);
topicById.getComments() // works like a charm

#17


2  

As I explained in this article, the best way to handle the LazyInitializationException is to fetch it upon query time, like this:

正如我在本文中解释的那样,处理LazyInitializationException的最佳方法是在查询时获取它,如下所示:

select t
from Topic t
left join fetch t.comments

You should ALWAYS avoid the following anti-patterns:

你应该总是避免以下反模式:

Therefore, make sure that your FetchType.LAZY associations are initialized at query time or within the original @Transactional scope using Hibernate.initialize for secondary collections.

因此,请确保在查询时或在原始@Transactional范围内使用Hibernate.initialize为初级集合初始化FetchType.LAZY关联。

#18


0  

The reason is you are trying to get the commentList on your controller after closing the session inside the service.

原因是您在关闭服务中的会话后尝试在控制器上获取commentList。

topicById.getComments();

Above will load the commentList only if your hibernate session is active, which I guess you closed in your service.

只有当您的休眠会话处于活动状态时,上面才会加载commentList,我想您已在服务中关闭了。

So, you have to get the commentList before closing the session.

因此,您必须在关闭会话之前获取commentList。

#19


0  

In my cae, I had the mapping b/w A and B like

在我的cae中,我有映射b / w A和B之类的

A has

A有

@OneToMany(mappedBy = "a", cascade = CascadeType.ALL)
Set<B> bs;

in the DAO layer, the method needs to be annotated with @Transactional if you haven't annotated the mapping with Fetch Type - Eager

在DAO层中,如果没有使用Fetch Type注释映射,则需要使用@Transactional注释该方法 - Eager

#20


-1  

add this to your persistence.xml

将其添加到persistence.xml中

<property name="hibernate.enable_lazy_load_no_trans" value="true" />

#21


-7  

i resolved using List instead of Set:

我解决使用List而不是Set:

private List<Categories> children = new ArrayList<Categories>();